Skip to content

Commit f2ca9bd

Browse files
committed
Support filtering for unique mate
1 parent 9c44bf4 commit f2ca9bd

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

docs/generate_puzzles.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Currently the following options are available:
3434

3535
`mate_ply` - only keep positions with mate in at least this many plies. Filters out mates that are too short. When using `puzzle_depth` it applies to this validation search, otherwise uses the regular search result. Default: 1.
3636

37+
`unique_mate` - either 0 or 1. When enabled (1), uses multipv 2 during puzzle verification and filters out positions where the second best line also has a mate score. This ensures only positions with a single unique mating line are kept as puzzles, improving puzzle quality. Default: 1.
38+
3739
`random_move_min_ply` - the minimal ply at which a random move may be executed instead of a move chosen by search. Default: 1.
3840

3941
`random_move_max_ply` - the maximal ply at which a random move may be executed instead of a move chosen by search. Default: 150.

src/tools/puzzle_generator.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ namespace Stockfish::Tools
5757
int king_safety_limit = 64000;
5858
int material_limit = 64000;
5959
int mate_ply = 1;
60+
bool unique_mate = true;
6061

6162
// minimum ply with random move
6263
// maximum ply with random move
@@ -342,10 +343,21 @@ namespace Stockfish::Tools
342343
// If puzzle_depth is set, we will check if the position is a mate or not.
343344
else if (params.puzzle_depth > 0)
344345
{
345-
auto [search_value2, search_pv2] = Search::search(pos, params.puzzle_depth, 1, 0);
346+
auto [search_value2, search_pv2] = Search::search(pos, params.puzzle_depth, params.unique_mate ? 2 : 1, 0);
346347
// Filter non-mate and short mate positions
347348
if (search_value2 < VALUE_MATE_IN_MAX_PLY || search_value2 > mate_in(params.mate_ply))
348349
keep = false;
350+
// Filter positions where the second line also has a mate score (if unique_mate is enabled)
351+
else if (params.unique_mate)
352+
{
353+
auto& rm = pos.this_thread()->rootMoves;
354+
if (rm.size() >= 2)
355+
{
356+
Value second_value = rm[1].score;
357+
if (second_value >= VALUE_MATE_IN_MAX_PLY)
358+
keep = false;
359+
}
360+
}
349361
}
350362

351363
// As a fallback if puzzle_depth is not set
@@ -728,6 +740,8 @@ namespace Stockfish::Tools
728740
is >> params.material_limit;
729741
else if (token == "mate_ply")
730742
is >> params.mate_ply;
743+
else if (token == "unique_mate")
744+
is >> params.unique_mate;
731745
else if (token == "random_move_min_ply")
732746
is >> params.random_move_minply;
733747
else if (token == "random_move_max_ply")
@@ -826,6 +840,7 @@ namespace Stockfish::Tools
826840
<< " - king_safety_limit = " << params.king_safety_limit << endl
827841
<< " - material_limit = " << params.material_limit << endl
828842
<< " - mate_ply = " << params.mate_ply << endl
843+
<< " - unique_mate = " << params.unique_mate << endl
829844
<< " - num threads (UCI) = " << params.num_threads << endl
830845
<< " - random_move_min_ply = " << params.random_move_minply << endl
831846
<< " - random_move_max_ply = " << params.random_move_maxply << endl

0 commit comments

Comments
 (0)