Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MateHunter

A Stockfish 19 fork for finding forced mates, version 0.1.0; see CHANGELOG.md. It is distributed as a patch against the Stockfish 19 release: 6 files and 27,470 bytes of diff, which is smaller than a binary and shows exactly what was changed.

Building

The base is the Stockfish 19 release: tag sf_19, commit edb0d9db6731067ec50ce619ff372b463bc4dd5d, whose src/ directory has the git tree hash 15c9967c8add24a07ef4a34522cb6fb5c71ca580. The patch paths are relative to src/:

git clone --branch sf_19 --depth 1 https://github.com/official-stockfish/Stockfish.git
cd Stockfish
git rev-parse HEAD:src
cd src
patch -p1 < /path/to/matehunter.patch
make -j build ARCH=x86-64-avx2

git rev-parse HEAD:src must print 15c9967c8add24a07ef4a34522cb6fb5c71ca580. make validates the NNUE network, and fetches it if it is missing; the patch does not change it.

Check the build before trusting any result. With MateEval off, MateHunter searches exactly as stock Stockfish 19 does, so

printf "setoption name MateEval value false\nbench\nquit\n" | ./stockfish

must report Nodes searched of 2497913, the bench recorded in the Stockfish 19 release commit. With its defaults, bench reports 5314178.

Options

option default effect
MateEval true replace NNUE's static evaluation with the mate evaluation
MateEvalNull true with MateEval, fix the static evaluation at 0, so the only evaluation the search sees is the correction history Stockfish learns during the search. With it off, MateEval uses a king-danger evaluator that ignores material

The defaults, MateEval=true and MateEvalNull=true with every other option at its default, are the recommended profile. Scripts should still set every option they rely on explicitly.

For reproducing the measurements

These options exist so the results in FINDINGS.md can be reproduced. None is part of the recommended profile, and at their defaults they change nothing.

option effect
MateEscapeW, MateCheckW, MateExposeW, MateDefendW, MateAttackW, MateNearW, MateScale the king-danger evaluator's weights; they matter only with MateEvalNull=false
MateEvalMain, MateEvalQS route the mate evaluation to one consumer of the static evaluation only: the main search, or quiescence. MateEval overrides both
MateMode switch off razoring, futility and null-move pruning, and relieve one ply of reduction for checks
MateNoRazor, MateNoFutility, MateNoNull the three prunings MateMode switches off, separately
MateEvalOff bitmask switching off one consumer of the static evaluation per bit, listed in engine.cpp and FINDINGS.md; 0 in normal use

What it does, measured

Correction, 2026-09-16: these results are in-sample

The measurements below say neither engine was tuned on ChestUCI. For MateHunter that is wrong. Its options and recommended profile were chosen on matetrack, and 6,526 of ChestUCI's 6,545 positions are also in matetrack, including 2,460 of the 2,477 at mate in 10 or more. The ChestUCI results measure MateHunter on the positions it was developed on, and do not show that it finds more mates than stock Stockfish in general.

Out of sample the advantage is far smaller, it depends on the clock, and Huntsman 1 finds more mates than either profile at every clock measured. The positions below are ones no engine could have been tuned on: generated by walking back from random checkmates, the shortest mate of each proved by MateProver 0.2.0, every position in matetrack or ChestUCI excluded, and each measurement planned before it ran. The positions, the plans and every run log are in MateBench: corpora/, studies/ and rounds/. One thread, paired, every mate claim verified by MateProver, none refuted.

At equal time. The recommended profile skips NNUE and searches about 2.7 times as many nodes per second as stock (4.0M against 1.5M on the same positions), so time, not nodes, is the fair budget. Verified mates, one thread a search:

mate in positions clock Stockfish 19 recommended profile full king-danger evaluator Huntsman 1 recommended vs Stockfish
9 to 11 993 0.5 s 293 215 285 630 +86/-164, p < 0.0001
9 to 11 993 1 s 411 374 411 695 +100/-137, p = 0.019
9 to 11 993 2 s 473 524 484 741 +143/-92, p = 0.0011
9 to 11 993 5 s 585 650 620 776 +125/-60, p < 0.0001
9 to 11 993 10 s 645 691 670 795 +99/-53, p = 0.0002
10 and 11 304 5 s 161 180 181 248 +39/-20, p = 0.018
6 to 8 1,171 0.5 s 719 699 749 908 +121/-141, p = 0.24
6 to 8 1,171 1 s 844 844 878 972 +103/-103, p = 1.0
6 to 8 1,171 2 s 914 929 941 1,011 +87/-72, p = 0.27
6 to 8 1,171 5 s 984 1,003 1,014 1,049 +59/-40, p = 0.07
  • Against stock, the recommended profile is behind below about 2 seconds a position and ahead from 2 seconds, on mate in 9 to 11. At 5 seconds it finds about 12% more mates than stock at mate in 10 and 11 (repeated at half the machine load: +42/-20, p = 0.007); on ChestUCI, under the same clock at mate in 10 to 13, it found 74% more. On mate in 6 to 8 it is never significantly ahead.
  • Which profile to use. The full king-danger evaluator (MateEvalNull=false) is better at 0.5 and 1 second (+154/-84 and +145/-108 over the recommended profile on mate in 9 to 11), and it is the only profile ahead of stock on mate in 6 to 8 (at 1, 2 and 5 seconds). The recommended profile is better at 2 and 5 seconds on mate in 9 to 11 (+137/-97 and +93/-63), and the two are level at 10 seconds.
  • Huntsman 1 is ahead of both profiles and of stock at every clock and depth, at p < 0.0001: +74/-6 against the recommended profile at 5 seconds on mate in 10 and 11, and +440/-25 at 0.5 seconds on mate in 9 to 11. It was ahead at equal nodes too (below), so its lead is not speed. The in-sample ChestUCI comparison below, where MateHunter led Huntsman, does not carry over.

At equal nodes the recommended profile has about a third of stock's time, and it is never ahead. On 4,934 generated mates in 1 to 9, split 20/80 by a salt committed before any engine ran:

positions budget Stockfish 19 recommended profile Huntsman 1 MateHunter vs Stockfish MateHunter vs Huntsman
held out, 972 10M nodes 963 963 971 +5/-5, p = 1.0 +0/-8, p = 0.008
held out, 972 100k nodes 872 815 914 +14/-71, p < 0.0001 +6/-105, p < 0.0001
held out, 972 10k nodes 767 642 801 +3/-128, p < 0.0001 +2/-161, p < 0.0001
development, 3,962 10M nodes 3,938 3,935 3,956 +12/-15, p = 0.70 +3/-24, p < 0.0001

and on 3,421 more, one mate length at a time, at 10M nodes:

mate in positions Stockfish 19 recommended profile Huntsman 1 MateHunter vs Stockfish
1 to 5 1,238 1,216 1,216 1,238 within 1 or 2 at each
6 407 390 373 402 +3/-20, p = 0.0005
7 486 418 406 438 +13/-25, p = 0.07
8 297 210 200 233 +13/-23, p = 0.13
9 689 455 436 537 +50/-69, p = 0.10
10 and 11 304 181 169 248 +25/-37, p = 0.16

The node-budget rows up to mate in 8 include 39 positions no game can reach, which Stockfish and MateHunter refuse and Huntsman accepts; without them MateHunter against Stockfish is unchanged, and the clock tables above leave them out. A clock result belongs to the machine it ran on (a 16-core Ryzen 9 7945HX, 8 searches at a time), so the 2-second crossover will move on other hardware. Mate in 12 and deeper, and composed problems not in matetrack, are untested. The 19 ChestUCI positions not in matetrack are too few to decide anything: at 10M nodes MateHunter solved 5, Stockfish 19 4 and Huntsman 1 7.

Everything else in this section and in FINDINGS.md stands as a description of MateHunter on ChestUCI, including the mechanism study. Its margins there are not evidence of margins that size elsewhere.

On ChestUCI, in-sample

Against stock Stockfish 19 on ChestUCI, one thread, paired, with every mate option set explicitly:

positions budget Stockfish 19 full king-danger evaluator recommended profile
d14+, 953 10M nodes 343 586 590
d10-13, 1,524 10M nodes 757 1,176 1,225
d14+, 953 5 s 324 592 606
d10-13, 1,524 5 s 715 1,195 1,244

With every mate option off the fork matched stock exactly: 343 = 343, zero discordant.

Against Huntsman 1, a Stockfish fork with a MateSearch option, on the same positions at 10M nodes: 590 against 542 at d14+ and 1,225 against 1,101 at d10-13. Every mate only one of the two engines reported was re-proved with MateProver, and none was refuted. On proved claims MateHunter is +220/−97 (p < 0.0001): ahead from mate in 10 to 17, level from mate in 18.

Why, replicated at both depth ranges. The gain comes from replacing NNUE's evaluation with the correction history Stockfish learns inside the current search. With MateEvalNull the static evaluation is 0 plus that correction term. Remove the term from the static evaluation (MateEvalOff=2048) and the profile falls below stock: 169 at d14+, 732 at d10-13. A genuinely flat evaluation is worse than NNUE. The king-danger terms add nothing over the recommended profile, and switching off any single consumer of the evaluation under NNUE recovers none of the gain. The measurements, the mechanism study and how to reproduce them are in FINDINGS.md.

Provenance

This patch is a port of the Stockfish 18 fork to Stockfish 19. The king-danger evaluator was carried over unchanged from the Stockfish 18 fork, not rewritten.

The measurements in FINDINGS.md were made with a development build that also carried experimental options since removed from the patch: move-ordering, move-restriction and learned-evaluation experiments, none of them part of any profile measured here. Removing them does not change the search. Under 13 option settings covering every option that remains, bench reports the same node count for the development build and for this patch (depth 9 for the two settings that switch pruning off under NNUE, the default depth otherwise).

Stockfish base tag sf_19, commit edb0d9db6731067ec50ce619ff372b463bc4dd5d
patch sha256 d14cb5c22a513c8eb98c2323b3c0c7b35f92a670d86e8a6036c840c7ef8a821a
stock Stockfish 19 bench 2497913 nodes
MateHunter, MateEval=false, bench 2497913 nodes
MateHunter, defaults, bench 5314178 nodes

Licence

GPL-3, inherited from Stockfish; see COPYING.txt. This patch is a derivative work of Stockfish and carries the same terms, which is why it lives apart from MateProver and MateBench, both MIT.

About

A Stockfish 19 fork for finding forced mates, distributed as a patch against the Stockfish 19 release

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors