evaluation
This commit is contained in:
@ -26,7 +26,7 @@ uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece
|
||||
|
||||
void undoMove(uint_least64_t *board, struct move_t move, bool color);
|
||||
struct gameState_t makeMove(struct gameState_t gameState, struct move_t move);
|
||||
struct gameState_t computerMove(struct gameState_t gameState);
|
||||
void initMagicTable();
|
||||
bool kingInCheck(const uint_least64_t *board, const bool color);
|
||||
|
||||
#endif
|
||||
|
||||
@ -28,3 +28,4 @@ void printerull(FILE *file, unsigned long long num);
|
||||
void printPieceMask(uint_least64_t mask);
|
||||
void fieldToString(uint_least8_t field, char *output);
|
||||
void printMove(const struct move_t move);
|
||||
void printMoveln(const struct move_t move);
|
||||
|
||||
100
src/chess/evaluate.c
Normal file
100
src/chess/evaluate.c
Normal file
@ -0,0 +1,100 @@
|
||||
#include "chess/move.h"
|
||||
#include "chess/types.h"
|
||||
#include <stdint.h>
|
||||
#include <chess/bitboard.h>
|
||||
#include <chess/print.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// These min and max values will not overflow, when negated
|
||||
#define INT_16_SAFE_MIN (INT_LEAST16_MIN + 1)
|
||||
#define INT_16_SAFE_MAX (INT_LEAST16_MAX - 1)
|
||||
|
||||
#ifdef __GNUC__ // Check if using GCC or compatible compiler
|
||||
static int_least16_t countOnes(uint_least64_t num) {
|
||||
return __builtin_popcountll(num); // Use GCC built-in function if available
|
||||
}
|
||||
#elif defined(_MSC_VER) // Check if using Microsoft Visual C++
|
||||
#include <intrin.h>
|
||||
static int_least16_t countOnes(uint_least64_t num) {
|
||||
return __popcnt64(num); // Use MSVC intrinsic if available
|
||||
}
|
||||
#else
|
||||
static int_least16_t countOnes(uint_least64_t num) {
|
||||
int_least16_t count = 0;
|
||||
while(num) {
|
||||
count += num & 1;
|
||||
num >>= 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int_least16_t evaluate(const struct gameState_t gameState) {
|
||||
int_least16_t value = 0;
|
||||
const uint_least64_t *board = gameState.board;
|
||||
int_least16_t pieceValues[PIECES_LENGTH];
|
||||
pieceValues[PAWN] = 100;
|
||||
pieceValues[KNIGHT] = 300;
|
||||
pieceValues[BISHOP] = 310;
|
||||
pieceValues[QUEEN] = 900;
|
||||
pieceValues[ROOK] = 500;
|
||||
|
||||
for(uint_least8_t pieceType = QUEEN; pieceType < PIECES_LENGTH; ++pieceType) {
|
||||
for(uint_least8_t color = BLACK; color <= WHITE; ++color) {
|
||||
const struct piece_t piece = {pieceType, color};
|
||||
const int_least16_t sign = color == gameState.color ? 1 : -1;
|
||||
value += sign * countOnes(bitboardGetMask(board, piece)) * pieceValues[pieceType];
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static int_least16_t alphaBeta(const struct gameState_t gameState, int_fast16_t alpha,
|
||||
int_least16_t beta, uint_least8_t depth) {
|
||||
if(depth == 0) return evaluate(gameState);
|
||||
struct move_t moves[MAX_VALID_MOVES];
|
||||
uint_least8_t movesLength = validMoves(gameState, moves);
|
||||
if(movesLength == 0) {
|
||||
if(kingInCheck(gameState.board, gameState.color)) {
|
||||
return INT_16_SAFE_MIN + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
for(uint_least8_t i = 0; i < movesLength; ++i) {
|
||||
const struct move_t move = moves[i];
|
||||
const struct gameState_t newGameState = makeMove(gameState, move);
|
||||
const int_least16_t score = -alphaBeta(newGameState, -beta, -alpha, depth - 1);
|
||||
undoMove(gameState.board, move, gameState.color);
|
||||
if(score >= beta) {
|
||||
return beta; // beta-cutoff
|
||||
}
|
||||
if(score > alpha) {
|
||||
alpha = score; // alpha acts like max in MiniMax
|
||||
}
|
||||
}
|
||||
return alpha;
|
||||
}
|
||||
|
||||
static struct move_t searchRoot(const struct gameState_t gameState, uint_least8_t depth) {
|
||||
struct move_t moves[MAX_VALID_MOVES];
|
||||
uint_least8_t movesLength = validMoves(gameState, moves);
|
||||
int_least16_t alpha = INT_16_SAFE_MIN;
|
||||
int_least16_t beta = INT_16_SAFE_MAX;
|
||||
struct move_t selectedMove;
|
||||
for(uint_least8_t i = 0; i < movesLength; ++i) {
|
||||
const struct move_t move = moves[i];
|
||||
const struct gameState_t newGameState = makeMove(gameState, move);
|
||||
const int_least16_t score = -alphaBeta(newGameState, -beta, -alpha, depth - 1);
|
||||
undoMove(gameState.board, move, gameState.color);
|
||||
if(score > alpha) {
|
||||
alpha = score; // alpha acts like max in MiniMax
|
||||
selectedMove = move;
|
||||
}
|
||||
}
|
||||
return selectedMove;
|
||||
}
|
||||
|
||||
struct move_t bestMove(const struct gameState_t gameState) {
|
||||
const uint_least8_t depth = 6;
|
||||
return searchRoot(gameState, depth);
|
||||
}
|
||||
8
src/chess/evaluate.h
Normal file
8
src/chess/evaluate.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef CHESS_EVALUATE_H
|
||||
#define CHESS_EVALUATE_H
|
||||
|
||||
#include <chess/types.h>
|
||||
|
||||
struct move_t bestMove(const struct gameState_t gameState);
|
||||
|
||||
#endif
|
||||
@ -9,6 +9,7 @@
|
||||
#include <chess/types.h>
|
||||
#include <chess/move.h>
|
||||
#include <chess/bitboard.h>
|
||||
#include "evaluate.h"
|
||||
|
||||
#define drawPiece(file, rank, piece) do { \
|
||||
const RsvgRectangle rect = {xOffset + (file) * fieldSize, yOffset + (rank) * fieldSize, fieldSize, fieldSize};\
|
||||
@ -49,7 +50,8 @@ static struct gameState_t userMove(struct gameState_t gameState, struct move_t m
|
||||
#ifdef NO_COMPUTER
|
||||
turn = !turn;
|
||||
#else
|
||||
gameState = computerMove(gameState);
|
||||
move = bestMove(gameState);
|
||||
gameState = makeMove(gameState, move);
|
||||
#endif
|
||||
return gameState;
|
||||
}
|
||||
|
||||
@ -10,7 +10,9 @@
|
||||
#include "magicNumber.h"
|
||||
#include <chess/magic.h>
|
||||
|
||||
#define trailingBits(num) __builtin_ctzll(num)
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
struct addMoveCtx_t {
|
||||
struct gameState_t gameState;
|
||||
@ -20,6 +22,23 @@ struct addMoveCtx_t {
|
||||
|
||||
const static uint_least8_t MAIN_DIRECTION[] = {NORTH, WEST, EAST, SOUTH};
|
||||
|
||||
static uint_least8_t trailingBits(uint_least64_t num) {
|
||||
#ifdef __GNUC__
|
||||
return __builtin_ctzll(num);
|
||||
#elif defined(_MSC_VER)
|
||||
unsigned long i;
|
||||
_BitScanForward(&i, num);
|
||||
return i;
|
||||
#elif
|
||||
uint_least8_t count = 0;
|
||||
while ((num & 1) == 0) { // Keep shifting num right until the least significant bit is 1
|
||||
num >>= 1;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint_least8_t getDirectionOffset(uint_least8_t field, uint_least8_t direction) {
|
||||
defineDirectionOffset;
|
||||
return DIRECTION_OFFSET[field * DIRECTION_LENGTH + direction];
|
||||
@ -109,6 +128,11 @@ static bool inCheck(const uint_least64_t *board, const uint_least64_t kingMask,
|
||||
checkMagic(board, queen, rookMagic, kingMask) || checkMagic(board, queen, bishopMagic, kingMask);
|
||||
}
|
||||
|
||||
bool kingInCheck(const uint_least64_t *board, const bool color) {
|
||||
const struct piece_t king = {KING, color};
|
||||
return inCheck(board, bitboardGetMask(board, king), color);
|
||||
}
|
||||
|
||||
static uint_least8_t getCastleRankI(bool color) {
|
||||
if(color == WHITE) {
|
||||
return (BOARD_SIZE - 1) * BOARD_SIZE;
|
||||
@ -163,8 +187,7 @@ static void addMove(struct addMoveCtx_t ctx, struct piece_t movedPiece, uint_lea
|
||||
makeMove(ctx.gameState, move);
|
||||
{
|
||||
const bool color = ctx.gameState.color;
|
||||
const struct piece_t king = {KING, color};
|
||||
if(!inCheck(board, bitboardGetMask(board, king), color)) {
|
||||
if(!kingInCheck(board, color)) {
|
||||
ctx.moves[*movesLength] = move;
|
||||
++*movesLength;
|
||||
}
|
||||
@ -360,9 +383,3 @@ struct gameState_t makeMove(struct gameState_t gameState, struct move_t move) {
|
||||
gameState.color = !gameState.color;
|
||||
return gameState;
|
||||
}
|
||||
|
||||
struct gameState_t computerMove(struct gameState_t gameState) {
|
||||
struct move_t moves[MAX_VALID_MOVES];
|
||||
validMoves(gameState, moves);
|
||||
return makeMove(gameState, moves[0]);
|
||||
}
|
||||
|
||||
@ -53,3 +53,8 @@ void printMove(const struct move_t move) {
|
||||
printf("%c", piece);
|
||||
}
|
||||
}
|
||||
|
||||
void printMoveln(const struct move_t move) {
|
||||
printMove(move);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user