110 lines
3.0 KiB
C
110 lines
3.0 KiB
C
#include "types.h"
|
|
#include "help.h"
|
|
#include "moves.h"
|
|
#include <stddef.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
|
|
#define PAWN_VALUE 100
|
|
#define KNIGHT_VALUE 320
|
|
#define BISHOP_VALUE 330
|
|
#define ROOK_VALUE 500
|
|
#define QUEEN_VALUE 900
|
|
#define KING_VALUE 20000
|
|
#define INF 9000000
|
|
#define MAX_DEPTH 3
|
|
|
|
int evaluateBoard(game *game);
|
|
void makeMove(game *g, move* m);
|
|
int negamax(game *g, int depth, int alpha, int beta, int color);
|
|
|
|
move *findBest(move* moves, size_t size, game* g){
|
|
int bestScore = -INF;
|
|
move *bestMove = NULL;
|
|
int color = g->whiteToMove ? 1 : -1;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
game gg = *g;
|
|
makeMove(&gg, &moves[i]);
|
|
int score = -negamax(&gg, MAX_DEPTH, -INF, INF, -color);
|
|
if (score > bestScore || bestScore == -INF) {
|
|
bestScore = score;
|
|
bestMove = &moves[i];
|
|
printf("info score cp %d\n", g->whiteToMove ? bestScore : -bestScore);
|
|
}
|
|
}
|
|
return bestMove;
|
|
}
|
|
|
|
int evaluateBoard(game *game) {
|
|
int score = 0;
|
|
score += __builtin_popcountll(game->white.pawns) * PAWN_VALUE;
|
|
score += __builtin_popcountll(game->white.knights) * KNIGHT_VALUE;
|
|
score += __builtin_popcountll(game->white.bishops) * BISHOP_VALUE;
|
|
score += __builtin_popcountll(game->white.rooks) * ROOK_VALUE;
|
|
score += __builtin_popcountll(game->white.queen) * QUEEN_VALUE;
|
|
score += __builtin_popcountll(game->white.king) * KING_VALUE;
|
|
|
|
score -= __builtin_popcountll(game->black.pawns) * PAWN_VALUE;
|
|
score -= __builtin_popcountll(game->black.knights) * KNIGHT_VALUE;
|
|
score -= __builtin_popcountll(game->black.bishops) * BISHOP_VALUE;
|
|
score -= __builtin_popcountll(game->black.rooks) * ROOK_VALUE;
|
|
score -= __builtin_popcountll(game->black.queen) * QUEEN_VALUE;
|
|
score -= __builtin_popcountll(game->black.king) * KING_VALUE;
|
|
|
|
return score;
|
|
}
|
|
|
|
void makeMove(game *g, move* m) {
|
|
unsigned long long from_bit = 1ULL << m->From;
|
|
unsigned long long to_bit = 1ULL << m->To;
|
|
|
|
unsigned long long *set = findSet(g, from_bit);
|
|
if (!set)
|
|
return;
|
|
*set &= ~from_bit;
|
|
|
|
unsigned long long *captured = findSet(g, to_bit);
|
|
if (captured) *captured &= ~to_bit;
|
|
|
|
if (m->Promo) {
|
|
char promoChar = g->whiteToMove ? toupper(m->Promo) : m->Promo;
|
|
unsigned long long *newSet = charToSet(g, promoChar);
|
|
if (newSet)
|
|
*newSet |= to_bit;
|
|
} else {
|
|
*set |= to_bit;
|
|
}
|
|
|
|
g->whiteToMove = !g->whiteToMove;
|
|
}
|
|
|
|
int negamax(game *g, int depth, int alpha, int beta, int color) {
|
|
if (depth == 0)
|
|
return color * evaluateBoard(g);
|
|
|
|
move moves[1500];
|
|
int cnt = pawnMove(g, moves);
|
|
cnt += knightMove(g, moves + cnt);
|
|
cnt += rookMove(g, moves + cnt);
|
|
cnt += bishopMove(g, moves + cnt);
|
|
cnt += kingMove(g, moves + cnt);
|
|
cnt += queenMove(g, moves + cnt);
|
|
|
|
if (cnt == 0)
|
|
return 0;
|
|
|
|
int bestValue = -INF;
|
|
for (int i = 0; i < cnt; i++) {
|
|
game gg = *g;
|
|
makeMove(&gg, &moves[i]);
|
|
|
|
int value = -negamax(&gg, depth - 1, -beta, -alpha, -color);
|
|
|
|
if (value > bestValue) bestValue = value;
|
|
if (value > alpha) alpha = value;
|
|
if (alpha >= beta) break;
|
|
}
|
|
return bestValue;
|
|
}
|