Skip to content

Commit

Permalink
Adapts to games-core changes + adds AbstractBasicQuiesceEvaluator
Browse files Browse the repository at this point in the history
  • Loading branch information
fathzer committed Feb 27, 2024
1 parent 79e9ad6 commit 48cfe14
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 37 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<version>1.0.8</version>
</parent>
<artifactId>chess-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>0.0.2-SNAPSHOT</version>

<name>chess-utils</name>
<description>Some helpful piece of code to implement chess engines.</description>
Expand Down Expand Up @@ -38,7 +38,7 @@
<dependency>
<groupId>com.fathzer</groupId>
<artifactId>games-core</artifactId>
<version>0.0.6-SNAPSHOT</version>
<version>0.0.8-SNAPSHOT</version>
</dependency>
<dependency>
<!-- This dependency is used to compile the com.fathzer.chess.utils.test package.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.fathzer.chess.utils.evaluators.quiesce;

import java.util.List;

import com.fathzer.games.MoveGenerator;
import com.fathzer.games.MoveGenerator.MoveConfidence;
import com.fathzer.games.ai.SearchContext;
import com.fathzer.games.ai.SearchStatistics;
import com.fathzer.games.ai.evaluation.QuiesceEvaluator;

/** A basic quiescence search evaluator.
*/
public abstract class AbstractBasicQuiesceEvaluator<M, B extends MoveGenerator<M>> implements QuiesceEvaluator<M,B> {
/** Constructor.
*/
protected AbstractBasicQuiesceEvaluator() {
super();
}

@Override
public int evaluate(SearchContext<M, B> context, int alpha, int beta) {
return quiesce(context, alpha, beta, 0);
}

private int quiesce(SearchContext<M, B> context, int alpha, int beta, int quiesceDepth) {
final SearchStatistics statistics = context.getStatistics();
final int standPat = context.getEvaluator().evaluate(context.getGamePosition());
statistics.evaluationDone();
if (standPat>=beta) {
return beta;
}
if (alpha < standPat) {
alpha = standPat;
}
final List<M> moves = getMoves(context, quiesceDepth);
statistics.movesGenerated(moves.size());
for (M move : moves) {
if (makeMove(context, move)) {
statistics.movePlayed();
final int score = -quiesce(context, -beta, -alpha, quiesceDepth+1);
context.unmakeMove();
if (score >= beta) {
return beta;
}
if (score > alpha) {
alpha = score;
}
}
}
return alpha;
}

/** Gets the list of quiesce moves.
* @param context The search context (can be used to get the board)
* @param quiesceDepth The quiesce depth. 0 for the first level
* @return A list of moves to analyze deeper, an empty list to stop deepening.
*/
protected abstract List<M> getMoves(SearchContext<M, B> context, int quiesceDepth);

/** Make a move.
* <br>The default implementation make the move with a {@link MoveConfidence#PSEUDO_LEGAL} confidence.
* @param context The context on which to apply the move
* @param move The move to play
* @return true if the move was successfully played, false if the move is illegal
*/
protected boolean makeMove(SearchContext<M, B> context, M move) {
return context.makeMove(move, MoveConfidence.PSEUDO_LEGAL);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public void unmakeMove() {
}

@Override
public List<Move> getMoves(boolean quiesce) {
final List<Move> moves = quiesce ? board.pseudoLegalCaptures() : board.pseudoLegalMoves();
public List<Move> getMoves() {
final List<Move> moves = board.pseudoLegalMoves();
if (comparator==null) {
return moves;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.fathzer.chess.utils.evaluators;

import com.fathzer.chess.utils.adapters.BoardExplorer;
import com.fathzer.chess.utils.adapters.chesslib.BasicMoveDecoder;
import com.fathzer.chess.utils.adapters.chesslib.ChessLibBoardExplorer;
import com.fathzer.chess.utils.adapters.chesslib.ChessLibMoveGenerator;
import com.github.bhlangonijr.chesslib.move.Move;

public class ChessLibNaiveEvaluator extends AbstractNaiveEvaluator<Move, ChessLibMoveGenerator> {
public ChessLibNaiveEvaluator() {
super();
}

private ChessLibNaiveEvaluator(int score) {
super(score);
}

@Override
public AbstractNaiveEvaluator<Move, ChessLibMoveGenerator> fork(int score) {
return new ChessLibNaiveEvaluator(score);
}

@Override
public BoardExplorer getExplorer(ChessLibMoveGenerator board) {
return new ChessLibBoardExplorer(board.getBoard());
}

@Override
protected int getCapturedType(ChessLibMoveGenerator board, Move move) {
return BasicMoveDecoder.getCapturedType(board, move);
}

@Override
protected int getPromotionType(ChessLibMoveGenerator board, Move move) {
return BasicMoveDecoder.getPromotionType(board, move);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,13 @@
import org.junit.jupiter.api.Test;

import com.fathzer.chess.test.utils.FENUtils;
import com.fathzer.chess.utils.adapters.BoardExplorer;
import com.fathzer.chess.utils.adapters.chesslib.BasicMoveDecoder;
import com.fathzer.chess.utils.adapters.chesslib.ChessLibBoardExplorer;
import com.fathzer.chess.utils.adapters.chesslib.ChessLibMoveGenerator;
import com.fathzer.games.MoveGenerator.MoveConfidence;
import com.fathzer.games.ai.evaluation.Evaluator;
import com.github.bhlangonijr.chesslib.Piece;
import com.github.bhlangonijr.chesslib.move.Move;

class NaiveEvaluatorTest {
private static class ChessLibNaiveEvaluator extends AbstractNaiveEvaluator<Move, ChessLibMoveGenerator> {
protected ChessLibNaiveEvaluator() {
super();
}

private ChessLibNaiveEvaluator(int score) {
super(score);
}

@Override
public AbstractNaiveEvaluator<Move, ChessLibMoveGenerator> fork(int score) {
return new ChessLibNaiveEvaluator(score);
}

@Override
public BoardExplorer getExplorer(ChessLibMoveGenerator board) {
return new ChessLibBoardExplorer(board.getBoard());
}

@Override
protected int getCapturedType(ChessLibMoveGenerator board, Move move) {
return BasicMoveDecoder.getCapturedType(board, move);
}

@Override
protected int getPromotionType(ChessLibMoveGenerator board, Move move) {
return BasicMoveDecoder.getPromotionType(board, move);
}
}

private static class ATest {
private final ChessLibNaiveEvaluator eval;
private final ChessLibMoveGenerator mvg;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.fathzer.chess.utils.evaluators.quiesce;

import static com.github.bhlangonijr.chesslib.Square.*;
import static org.junit.jupiter.api.Assertions.*;

import java.util.List;

import org.junit.jupiter.api.Test;

import com.fathzer.chess.utils.adapters.chesslib.ChessLibMoveGenerator;
import com.fathzer.chess.utils.evaluators.ChessLibNaiveEvaluator;
import com.fathzer.games.MoveGenerator.MoveConfidence;
import com.fathzer.games.ai.SearchContext;
import com.fathzer.games.ai.evaluation.Evaluator;
import com.fathzer.games.ai.evaluation.QuiesceEvaluator;

import com.github.bhlangonijr.chesslib.Board;
import com.github.bhlangonijr.chesslib.move.Move;

class MinimaxTest {
static class SimpleQuiesce extends AbstractBasicQuiesceEvaluator<Move, ChessLibMoveGenerator> {
private SimpleQuiesce() {
super();
}

@Override
protected List<Move> getMoves(SearchContext<Move, ChessLibMoveGenerator> context, int quiesceDepth) {
return context.getGamePosition().getBoard().pseudoLegalCaptures();
}
}

@Test
void testQuiesce() {
final Evaluator<Move, ChessLibMoveGenerator> ev = new ChessLibNaiveEvaluator();
final Board board = new Board();
board.loadFromFen("3n1rk1/1pp2p1p/2r2bq1/2P1p1p1/3pP3/PQ1P2PP/1R3PB1/2B2RK1 w - - 2 26");
final ChessLibMoveGenerator mg = new ChessLibMoveGenerator(board);
final SearchContext<Move, ChessLibMoveGenerator> context = SearchContext.get(mg, ()->ev);
final QuiesceEvaluator<Move, ChessLibMoveGenerator> qev = new SimpleQuiesce();

assertTrue(context.makeMove(new Move(B3, F7), MoveConfidence.UNSAFE));
assertEquals(800, qev.evaluate(context, Integer.MIN_VALUE+1, Integer.MAX_VALUE));
context.unmakeMove();

assertTrue(context.makeMove(new Move(B3, B7), MoveConfidence.UNSAFE));
assertEquals(600, qev.evaluate(context, Integer.MIN_VALUE+1, Integer.MAX_VALUE));
context.unmakeMove();
}
}

0 comments on commit 48cfe14

Please sign in to comment.