Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
fathzer committed Dec 11, 2024
1 parent 0e6ffcd commit 7a6ed27
Show file tree
Hide file tree
Showing 8 changed files with 586 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.fathzer.chess.utils.evaluators.pesto;

public class PestoEvaluator {
// Piece types
public static final int PAWN = 0;
public static final int KNIGHT = 1;
public static final int BISHOP = 2;
public static final int ROOK = 3;
public static final int QUEEN = 4;
public static final int KING = 5;

// Board representation
public static final int WHITE = 0;
public static final int BLACK = 1;

// Piece definitions
public static final int WHITE_PAWN = (2 * PAWN + WHITE);
public static final int BLACK_PAWN = (2 * PAWN + BLACK);
public static final int WHITE_KNIGHT = (2 * KNIGHT + WHITE);
public static final int BLACK_KNIGHT = (2 * KNIGHT + BLACK);
public static final int WHITE_BISHOP = (2 * BISHOP + WHITE);
public static final int BLACK_BISHOP = (2 * BISHOP + BLACK);
public static final int WHITE_ROOK = (2 * ROOK + WHITE);
public static final int BLACK_ROOK = (2 * ROOK + BLACK);
public static final int WHITE_QUEEN = (2 * QUEEN + WHITE);
public static final int BLACK_QUEEN = (2 * QUEEN + BLACK);
public static final int WHITE_KING = (2 * KING + WHITE);
public static final int BLACK_KING = (2 * KING + BLACK);
public static final int EMPTY = BLACK_KING + 1;

public static int sideToMove;
public static int[] board = new int[64];

public static int[] mgValue = {82, 337, 365, 477, 1025, 0};
public static int[] egValue = {94, 281, 297, 512, 936, 0};

public static int[][] mgPestoTable = { /* Add mg tables here */ };
public static int[][] egPestoTable = { /* Add eg tables here */ };

public static int[][] mgTable = new int[12][64];
public static int[][] egTable = new int[12][64];

public static final int[] gamePhaseInc = {0, 0, 1, 1, 1, 1, 2, 2, 4, 4, 0, 0};

public static void initTables() {
for (int p = PAWN, pc = WHITE_PAWN; p <= KING; pc += 2, p++) {
for (int sq = 0; sq < 64; sq++) {
mgTable[pc][sq] = mgValue[p] + mgPestoTable[p][sq];
egTable[pc][sq] = egValue[p] + egPestoTable[p][sq];
mgTable[pc + 1][sq] = mgValue[p] + mgPestoTable[p][flip(sq)];
egTable[pc + 1][sq] = egValue[p] + egPestoTable[p][flip(sq)];
}
}
}

public static int flip(int square) {
return square ^ 56;
}

public static int other(int side) {
return side ^ 1;
}

public static int pcolor(int p) {
return p & 1;
}

public static int eval() {
int[] mg = {0, 0};
int[] eg = {0, 0};
int gamePhase = 0;

for (int sq = 0; sq < 64; ++sq) {
int pc = board[sq];
if (pc != EMPTY) {
mg[pcolor(pc)] += mgTable[pc][sq];
eg[pcolor(pc)] += egTable[pc][sq];
gamePhase += gamePhaseInc[pc];
}
}

int mgScore = mg[sideToMove] - mg[other(sideToMove)];
int egScore = eg[sideToMove] - eg[other(sideToMove)];
int mgPhase = Math.min(gamePhase, 24);
int egPhase = 24 - mgPhase;

return (mgScore * mgPhase + egScore * egPhase) / 24;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.fathzer.chess.utils.evaluators.simplified.two;

import java.util.function.Supplier;

import com.fathzer.chess.utils.adapters.MoveData;
import com.fathzer.games.MoveGenerator;
import com.fathzer.games.ai.evaluation.ZeroSumEvaluator;

public abstract class AbstractSimplifiedEvaluator2 <M, B extends MoveGenerator<M>> implements ZeroSumEvaluator<M,B>, Supplier<MoveData<M,B>> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.fathzer.chess.utils.evaluators.simplified.two;

import com.fathzer.chess.utils.evaluators.utils.AbstractPieceSquareTableEvaluator;
import com.fathzer.games.MoveGenerator;

public abstract class PiecesOnlySquareTable<M, B extends MoveGenerator<M>> extends AbstractPieceSquareTableEvaluator<M, B> {
private static final int[] PIECE_VALUES = {0, 100, 320, 330, 500, 900, 20000};
private static final int [][] PIECE_POSITION_VALUES = new int[][] {
// Just to have index equals to piece type codes
new int[0],
// PAWN
new int[] {
0, 0, 0, 0, 0, 0, 0, 0,
50, 50, 50, 50, 50, 50, 50, 50,
10, 10, 20, 30, 30, 20, 10, 10,
5, 5, 10, 25, 25, 10, 5, 5,
0, 0, 0, 20, 20, 0, 0, 0,
5, -5,-10, 0, 0,-10, -5, 5,
5, 10, 10,-20,-20, 10, 10, 5,
0, 0, 0, 0, 0, 0, 0, 0},
// KNIGHT
new int[] {
-50,-40,-30,-30,-30,-30,-40,-50,
-40,-20, 0, 0, 0, 0,-20,-40,
-30, 0, 10, 15, 15, 10, 0,-30,
-30, 5, 15, 20, 20, 15, 5,-30,
-30, 0, 15, 20, 20, 15, 0,-30,
-30, 5, 10, 15, 15, 10, 5,-30,
-40,-20, 0, 5, 5, 0,-20,-40,
-50,-40,-30,-30,-30,-30,-40,-50},
// BISHOP
new int[] {
-20,-10,-10,-10,-10,-10,-10,-20,
-10, 0, 0, 0, 0, 0, 0,-10,
-10, 0, 5, 10, 10, 5, 0,-10,
-10, 5, 5, 10, 10, 5, 5,-10,
-10, 0, 10, 10, 10, 10, 0,-10,
-10, 10, 10, 10, 10, 10, 10,-10,
-10, 5, 0, 0, 0, 0, 5,-10,
-20,-10,-10,-10,-10,-10,-10,-20},
// ROOK
new int[] {
0, 0, 0, 0, 0, 0, 0, 0,
5, 10, 10, 10, 10, 10, 10, 5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
0, 0, 0, 5, 5, 0, 0, 0},
// QUEEN
new int[] {
-20,-10,-10, -5, -5,-10,-10,-20,
-10, 0, 0, 0, 0, 0, 0,-10,
-10, 0, 5, 5, 5, 5, 0,-10,
-5, 0, 5, 5, 5, 5, 0, -5,
0, 0, 5, 5, 5, 5, 0, -5,
-10, 5, 5, 5, 5, 5, 0,-10,
-10, 0, 5, 0, 0, 0, 0,-10,
-20,-10,-10, -5, -5,-10,-10,-20},
// KING
new int[] {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
}};

static {
for (int i = 0; i < PIECE_VALUES.length; i++) {
add(PIECE_POSITION_VALUES[i], PIECE_VALUES[i]);
}
}

protected PiecesOnlySquareTable() {
super();
}

protected PiecesOnlySquareTable(int eval) {
super(eval);
}

private static void add(int[] array, int value) {
for (int i = 0; i < array.length; i++) {
array[i] = array[i]+value;
}
}

@Override
protected int getPositionValue(int piece, int index) {
return PIECE_POSITION_VALUES[piece][index];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.fathzer.chess.utils.evaluators.utils;

import java.util.LinkedList;
import java.util.List;
import java.util.function.Supplier;

import com.fathzer.chess.utils.adapters.BoardExplorerBuilder;
import com.fathzer.chess.utils.adapters.MoveData;
import com.fathzer.games.MoveGenerator;
import com.fathzer.games.ai.evaluation.ZeroSumEvaluator;

public abstract class AbstractComposedEvaluator<M, B extends MoveGenerator<M>> implements ZeroSumEvaluator<M,B>, BoardExplorerBuilder<B>, Supplier<MoveData<M,B>> {
private MoveData<M, B> moveData;
private List<ComposableEvaluator<M, B>> evaluators;

protected AbstractComposedEvaluator() {
moveData = get();
evaluators = new LinkedList<>();
}

@Override
public void prepareMove(B board, M move) {
if (!moveData.update(move, board)) {
return;
}
evaluators.forEach(ev -> ev.prepareMove(moveData));
}

@Override
public void init(B board) {
evaluators.forEach(ev -> ev.init(board));
}

@Override
public void commitMove() {
evaluators.forEach(ZeroSumEvaluator::commitMove);
}

@Override
public void unmakeMove() {
evaluators.forEach(ev -> ev.unmakeMove());
}

@Override
public int evaluateAsWhite(B board) {
return evaluators.stream().mapToInt(ev -> ev.evaluateAsWhite(board)).sum();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package com.fathzer.chess.utils.evaluators.utils;

import static com.fathzer.chess.utils.Pieces.KING;
import static com.fathzer.chess.utils.Pieces.ROOK;

import java.util.concurrent.atomic.AtomicInteger;

import com.fathzer.chess.utils.Pieces;
import com.fathzer.chess.utils.adapters.BoardExplorer;
import com.fathzer.chess.utils.adapters.BoardExplorerBuilder;
import com.fathzer.chess.utils.adapters.MoveData;
import com.fathzer.games.MoveGenerator;
import com.fathzer.games.ai.evaluation.Evaluator;
import com.fathzer.games.util.Stack;

/** An incremental evaluator based on a <a href="https://www.chessprogramming.org/Piece-Square_Tables"> piece square table</a> implementation.
*/
public abstract class AbstractPieceSquareTableEvaluator<M, B extends MoveGenerator<M>> implements ComposableEvaluator<M,B>, BoardExplorerBuilder<B> {

private final Stack<AtomicInteger> states; //TODO implement something lighter
private int toCommit;

protected AbstractPieceSquareTableEvaluator() {
this.states = new Stack<>(AtomicInteger::new);
}

protected AbstractPieceSquareTableEvaluator(int eval) {
this();
this.states.get().set(eval);
}

@Override
public void init(B board) {
states.clear();
states.set(new AtomicInteger(getRawEvaluation(getExplorer(board))));
}

private int getRawEvaluation(BoardExplorer explorer) {
int points = 0;
do {
final int p = explorer.getPiece();
final int piece = Math.abs(p);
final int index = explorer.getIndex();
final boolean isBlack = p<0;
points += getPositionValue(piece, isBlack, index);
} while (explorer.next());
return points;
}

@Override
public void prepareMove(MoveData<M, B> moveData) {
final boolean isBlack = moveData.getMovingPiece()<0;
int moving = Math.abs(moveData.getMovingPiece());
final int movingIndex = moveData.getMovingIndex();
int inc = 0;
if (moving==KING) {
// Be cautious with castling
int rookIndex = moveData.getCastlingRookIndex();
if (rookIndex>=0) {
// It's a castling move, update rook positions values
inc = getPositionValue(ROOK, isBlack, moveData.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex);
}
}
// Remove the old position value of the moving piece
inc -= getPositionValue(moving, isBlack, movingIndex);
final int promoType = moveData.getPromotionType();
if (promoType!=0) {
// If promotion, update the moving piece
moving = promoType;
}
// Adds the new position value of the
inc += getPositionValue(moving, isBlack, moveData.getMovingDestination());
int captured = moveData.getCapturedType();
if (captured!=0) {
// If the move is a capture add its position value
inc -= getPositionValue(captured, !isBlack, moveData.getCapturedIndex());
}
toCommit = states.get().get() + inc;
}

@Override
public void commitMove() {
states.next();
states.set(new AtomicInteger(toCommit));
}

@Override
public void unmakeMove() {
states.previous();
}

@Override
public Evaluator<M, B> fork() {
return fork(states.get().get());
}

@Override
public int evaluateAsWhite(B board) {
return states.get().get();
}

/** Gets the position value associated with a white piece at an index.
* @param piece The piece type as define in {@link Pieces}
* @param index The index of the piece on the board as defined in {@link BoardExplorer}
* @return an integer
*/
protected abstract int getPositionValue(int piece, int index);

/** Gets the value (from the white point of view) of a piece at a position.
* @param piece The piece type as define in {@link Pieces}
* @param black true if piece is black
* @param index The index of the piece on the board as defined in {@link BoardExplorer}
* @return an integer
*/
private int getPositionValue(int piece, boolean black, int index) {
if (black) {
final int row = 7 - index/8;
final int col = index%8;
index = row*8 + col;
return -getPositionValue(piece, index);
} else {
return getPositionValue(piece, index);
}
}

/** Creates a new instance initialized with current evaluation that will become the initial state of created instance.
* @param state The initial state.
* @return a new evaluator of the same class as this, the same view point, and initialized with the state.
*/
protected abstract AbstractPieceSquareTableEvaluator<M, B> fork(int evaluation);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.fathzer.chess.utils.evaluators.utils;

import com.fathzer.chess.utils.adapters.MoveData;
import com.fathzer.games.MoveGenerator;
import com.fathzer.games.ai.evaluation.ZeroSumEvaluator;

public interface ComposableEvaluator<M, B extends MoveGenerator<M>> extends ZeroSumEvaluator<M, B> {
void prepareMove(MoveData<M, B> moveData);

@Override
default void prepareMove(B board, M move) {
throw new IllegalStateException("Prepare move is not implemented");
}
}
Loading

0 comments on commit 7a6ed27

Please sign in to comment.