More efficient searching
This commit is contained in:
Binary file not shown.
@@ -18,6 +18,7 @@
|
|||||||
#include "movegen.h"
|
#include "movegen.h"
|
||||||
#include "uci.h"
|
#include "uci.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -57,8 +58,8 @@ static int parse_skill(const char* options, int fallback) {
|
|||||||
return v < 1 ? 1 : v > 20 ? 20 : v;
|
return v < 1 ? 1 : v > 20 ? 20 : v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Maps the 1..20 difficulty to a search depth. Kept modest: the search has no move
|
/* Maps the 1..20 difficulty to a search depth. Kept modest: the search has no
|
||||||
* ordering or quiescence yet, so deep fixed-depth runs get expensive quickly. */
|
* quiescence yet, so deep fixed-depth runs get expensive quickly. */
|
||||||
static int depth_for_skill(int skill) {
|
static int depth_for_skill(int skill) {
|
||||||
return skill; /* skill 1 -> 2 plies ... skill 20 -> 7 plies */
|
return skill; /* skill 1 -> 2 plies ... skill 20 -> 7 plies */
|
||||||
}
|
}
|
||||||
@@ -178,6 +179,52 @@ static int evaluate(const chess::Position& pos) {
|
|||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int piece_value(chess::PieceType pt) {
|
||||||
|
switch (pt) {
|
||||||
|
case chess::PAWN: return 100;
|
||||||
|
case chess::KNIGHT: return 320;
|
||||||
|
case chess::BISHOP: return 330;
|
||||||
|
case chess::ROOK: return 500;
|
||||||
|
case chess::QUEEN: return 900;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heuristic for searching the most promising moves first, which makes alpha-beta
|
||||||
|
* prune far more. Checks rank highest, then captures by MVV-LVA (grab the most
|
||||||
|
* valuable victim with the least valuable attacker). */
|
||||||
|
static int order_score(chess::Position& pos, chess::Move m) {
|
||||||
|
int score = 0;
|
||||||
|
|
||||||
|
if (pos.gives_check(m))
|
||||||
|
score += 1000;
|
||||||
|
|
||||||
|
chess::Piece victim = pos.piece_on(m.to());
|
||||||
|
if (victim != chess::NO_PIECE)
|
||||||
|
score += 100 + 10 * piece_value(chess::type_of(victim))
|
||||||
|
- piece_value(chess::type_of(pos.piece_on(m.from())));
|
||||||
|
else if (m.type() == chess::EN_PASSANT)
|
||||||
|
score += 100 + 10 * piece_value(chess::PAWN);
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sort the move list in place, best-scoring first. Scores are computed once up
|
||||||
|
* front so gives_check isn't re-evaluated on every comparison. */
|
||||||
|
static void order_moves(chess::Position& pos, chess::MoveList& moves) {
|
||||||
|
struct ScoredMove { int score; chess::Move move; };
|
||||||
|
ScoredMove scored[256];
|
||||||
|
|
||||||
|
for (int i = 0; i < moves.size(); i++)
|
||||||
|
scored[i] = { order_score(pos, moves.moves[i]), moves.moves[i] };
|
||||||
|
|
||||||
|
std::sort(scored, scored + moves.size(),
|
||||||
|
[](const ScoredMove& a, const ScoredMove& b) { return a.score > b.score; });
|
||||||
|
|
||||||
|
for (int i = 0; i < moves.size(); i++)
|
||||||
|
moves.moves[i] = scored[i].move;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
CHESS_API EngineHandle CHESS_CALL engine_create(const char* options) {
|
CHESS_API EngineHandle CHESS_CALL engine_create(const char* options) {
|
||||||
@@ -205,6 +252,8 @@ static int alpha_beta(chess::Position& pos, int depth, int maxDepth, int bestFor
|
|||||||
if (moves.size() == 0)
|
if (moves.size() == 0)
|
||||||
return pos.is_draw() ? 0 : whiteToMove ? -200000 + depth : 200000 - depth;
|
return pos.is_draw() ? 0 : whiteToMove ? -200000 + depth : 200000 - depth;
|
||||||
|
|
||||||
|
order_moves(pos, moves);
|
||||||
|
|
||||||
for (int i = 0; i < moves.size(); i++) {
|
for (int i = 0; i < moves.size(); i++) {
|
||||||
chess::Move move = moves.moves[i];
|
chess::Move move = moves.moves[i];
|
||||||
pos.do_move(move);
|
pos.do_move(move);
|
||||||
@@ -247,6 +296,8 @@ CHESS_API int CHESS_CALL engine_best_move(EngineHandle engine,
|
|||||||
if (moves.size() == 0)
|
if (moves.size() == 0)
|
||||||
return CHESS_ERR_NO_MOVE;
|
return CHESS_ERR_NO_MOVE;
|
||||||
|
|
||||||
|
order_moves(pos, moves);
|
||||||
|
|
||||||
int maxDepth = depth_for_skill(engine->skill);
|
int maxDepth = depth_for_skill(engine->skill);
|
||||||
|
|
||||||
int bestForWhite = std::numeric_limits<int>::min();
|
int bestForWhite = std::numeric_limits<int>::min();
|
||||||
|
|||||||
Reference in New Issue
Block a user