Skip to content

Commit

Permalink
Add futility pruning (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenphuminh authored Jul 23, 2024
1 parent 59a3e72 commit e42cfc5
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

Note that you may also want to use Bun which is a much faster JS runtime env than Node.js.


## Setup

1. Clone the repository to your machine.
Expand Down Expand Up @@ -74,6 +75,7 @@ Note that the config file is compiled with the engine itself, so if you are usin
* Countermove heuristic.
* Transposition table.
* Null-move pruning.
* Futility pruning.
* Late move reductions.
* Search extensions:
* Check extensions.
Expand Down
2 changes: 1 addition & 1 deletion catto.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = {
// Current version to show in UCI
version: "v0.7.0",
version: "v0.8.0",
// Late move reduction config
lmrFullDepth: 4, // Number of moves to be searched in full depth
lmrMaxReduction: 3, // Only apply LMR above this depth
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "catto",
"version": "0.7.0",
"version": "0.8.0",
"description": "The Catto chess engine",
"main": "index.js",
"scripts": {
Expand Down
25 changes: 24 additions & 1 deletion src/core.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Chess, Color, Move } from "chess.js";
import { Chess, Move } from "chess.js";
import { evaluateBoard } from "./evaluate";
import { mvv_lva, PIECE_NUM } from "./evaluations";
import { genZobristKey } from "./zobrist";
import { mgMaterial } from "./evaluations";

export enum HashFlag {
exact,
Expand Down Expand Up @@ -309,6 +310,15 @@ export class Engine {
possibleMoves = this.sortMoves(possibleMoves);
let searchedMoves = 0, bestMoveSoFar: Move;

// Futility pruning
let fpEnabled = false;
if (depth < 4 && Math.abs(alpha) < 48000) {
const currentEval = evaluateBoard(this.chess);
// Margin for each depth, the shallower the depth the more we reduce the margin
const futilityMargin = [ 0, mgMaterial[0], mgMaterial[1], mgMaterial[3] ];
fpEnabled = currentEval + futilityMargin[depth] <= alpha;
}

// Find the best move
for (const move of possibleMoves) {
// const tempMove = move;
Expand All @@ -319,6 +329,19 @@ export class Engine {
this.chess.move(move);
let score = 0;

// Apply futility pruning
if (
fpEnabled &&
searchedMoves > 0 &&
!move.captured &&
!move.promotion &&
!this.chess.inCheck()
) {
this.chess.undo();
this.ply--;
continue;
}

// Do normal, alpha-beta full search on first (PV) move
if (searchedMoves === 0) {
score = -this.negamax(depth - 1 + extensions, -beta, -alpha, extended + extensions);
Expand Down

0 comments on commit e42cfc5

Please sign in to comment.