separate perft (from search.c)
This commit is contained in:
2
Makefile
2
Makefile
@@ -420,7 +420,7 @@ BB_OBJS := $(FEN_OBJS)
|
|||||||
MOVEGEN_OBJS := $(BB_OBJS) move-gen.o
|
MOVEGEN_OBJS := $(BB_OBJS) move-gen.o
|
||||||
ATTACK_OBJS := $(MOVEGEN_OBJS)
|
ATTACK_OBJS := $(MOVEGEN_OBJS)
|
||||||
MOVEDO_OBJS := $(ATTACK_OBJS) move-do.o
|
MOVEDO_OBJS := $(ATTACK_OBJS) move-do.o
|
||||||
PERFT_OBJS := $(MOVEDO_OBJS) search.o
|
PERFT_OBJS := $(MOVEDO_OBJS) perft.o
|
||||||
TT_OBJS := $(MOVEDO_OBJS)
|
TT_OBJS := $(MOVEDO_OBJS)
|
||||||
|
|
||||||
TEST := $(addprefix $(BINDIR)/,$(TEST))
|
TEST := $(addprefix $(BINDIR)/,$(TEST))
|
||||||
|
131
src/perft.c
Normal file
131
src/perft.c
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/* perft.c - perft functions.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023-2024 Bruno Raoult ("br")
|
||||||
|
* Licensed under the GNU General Public License v3.0 or later.
|
||||||
|
* Some rights reserved. See COPYING.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this
|
||||||
|
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <brlib.h>
|
||||||
|
|
||||||
|
#include "perft.h"
|
||||||
|
#include "move-gen.h"
|
||||||
|
#include "move-do.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* perft() - Perform perft on position
|
||||||
|
* @pos: &position to search
|
||||||
|
* @depth: Wanted depth.
|
||||||
|
* @ply: current perft depth level (root = 1)
|
||||||
|
* @divide: output total for 1st level moves.
|
||||||
|
*
|
||||||
|
* Run perft on a position. This function displays the available moves at @depth
|
||||||
|
* level for each possible first move, and the total of moves.
|
||||||
|
*
|
||||||
|
* This version uses the algorithm:
|
||||||
|
* if last depth
|
||||||
|
* return 1;
|
||||||
|
* gen legal moves
|
||||||
|
* loop for legal move
|
||||||
|
* do-move
|
||||||
|
* perft (depth -1)
|
||||||
|
* undo-move
|
||||||
|
*
|
||||||
|
* @return: total moves found at @depth level.
|
||||||
|
*/
|
||||||
|
u64 perft(pos_t *pos, int depth, int ply, bool divide)
|
||||||
|
{
|
||||||
|
u64 subnodes = 0, nodes = 0;
|
||||||
|
movelist_t movelist;
|
||||||
|
move_t *move, *last;
|
||||||
|
state_t state;
|
||||||
|
|
||||||
|
pos_set_checkers_pinners_blockers(pos);
|
||||||
|
|
||||||
|
pos_legal(pos, pos_gen_pseudo(pos, &movelist));
|
||||||
|
last = movelist.move + movelist.nmoves;
|
||||||
|
for (move = movelist.move; move < last; ++move) {
|
||||||
|
if (depth == 1) {
|
||||||
|
subnodes = 1;
|
||||||
|
} else {
|
||||||
|
move_do(pos, *move, &state);
|
||||||
|
if (depth == 2) {
|
||||||
|
movelist_t movelist2;
|
||||||
|
pos_set_checkers_pinners_blockers(pos);
|
||||||
|
subnodes = pos_legal(pos, pos_gen_pseudo(pos, &movelist2))->nmoves;
|
||||||
|
} else if (ply >= 3) {
|
||||||
|
hentry_t *entry = tt_probe_perft(pos->key, depth);
|
||||||
|
if (entry != TT_MISS) {
|
||||||
|
subnodes = HASH_PERFT_VAL(entry->data);
|
||||||
|
} else {
|
||||||
|
subnodes = perft(pos, depth - 1, ply + 1, divide);
|
||||||
|
tt_store_perft(pos->key, depth, subnodes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
subnodes = perft(pos, depth - 1, ply + 1, divide);
|
||||||
|
}
|
||||||
|
move_undo(pos, *move, &state);
|
||||||
|
}
|
||||||
|
nodes += subnodes;
|
||||||
|
if (ply == 1 && divide) {
|
||||||
|
char movestr[8];
|
||||||
|
printf("%s: %lu\n", move_to_str(movestr, *move, 0), subnodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* perft_alt() - Perform perft on position, experimental version.
|
||||||
|
* @pos: &position to search
|
||||||
|
* @depth: Wanted depth.
|
||||||
|
* @ply: current perft depth level (root = 1)
|
||||||
|
* @divide: output total for 1st level moves.
|
||||||
|
*
|
||||||
|
* Run perft on a position. This function displays the available moves at @depth
|
||||||
|
* level for each possible first move, and the total of moves.
|
||||||
|
*
|
||||||
|
* @return: total moves found at @depth level.
|
||||||
|
*/
|
||||||
|
u64 perft_alt(pos_t *pos, int depth, int ply, bool divide)
|
||||||
|
{
|
||||||
|
u64 subnodes = 0, nodes = 0;
|
||||||
|
movelist_t movelist;
|
||||||
|
move_t *move, *last;
|
||||||
|
state_t state;
|
||||||
|
|
||||||
|
pos_set_checkers_pinners_blockers(pos);
|
||||||
|
|
||||||
|
pos_legal(pos, pos_gen_pseudo(pos, &movelist));
|
||||||
|
last = movelist.move + movelist.nmoves;
|
||||||
|
for (move = movelist.move; move < last; ++move) {
|
||||||
|
if (depth == 1) {
|
||||||
|
subnodes = 1;
|
||||||
|
} else {
|
||||||
|
move_do_alt(pos, *move, &state);
|
||||||
|
if (depth == 2) {
|
||||||
|
movelist_t movelist2;
|
||||||
|
pos_set_checkers_pinners_blockers(pos);
|
||||||
|
subnodes = pos_legal(pos, pos_gen_pseudo(pos, &movelist2))->nmoves;
|
||||||
|
} else {
|
||||||
|
subnodes = perft_alt(pos, depth - 1, ply + 1, divide);
|
||||||
|
}
|
||||||
|
move_undo_alt(pos, *move, &state);
|
||||||
|
}
|
||||||
|
nodes += subnodes;
|
||||||
|
if (ply == 1 && divide) {
|
||||||
|
char movestr[8];
|
||||||
|
printf("%s: %lu\n", move_to_str(movestr, *move, 0), subnodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
22
src/perft.h
Normal file
22
src/perft.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/* perft.h.h - perft.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021-2024 Bruno Raoult ("br")
|
||||||
|
* Licensed under the GNU General Public License v3.0 or later.
|
||||||
|
* Some rights reserved. See COPYING.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this
|
||||||
|
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PERFT_H
|
||||||
|
#define PERFT_H
|
||||||
|
|
||||||
|
#include "position.h"
|
||||||
|
|
||||||
|
u64 perft(pos_t *pos, int depth, int ply, bool output);
|
||||||
|
u64 perft_alt(pos_t *pos, int depth, int ply, bool output);
|
||||||
|
|
||||||
|
#endif /* PERFT_H */
|
113
src/search.c
113
src/search.c
@@ -1,4 +1,4 @@
|
|||||||
/* search.c - perft + search.
|
/* search.c - search for perfect move.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2023-2024 Bruno Raoult ("br")
|
* Copyright (C) 2023-2024 Bruno Raoult ("br")
|
||||||
* Licensed under the GNU General Public License v3.0 or later.
|
* Licensed under the GNU General Public License v3.0 or later.
|
||||||
@@ -21,117 +21,6 @@
|
|||||||
#include "search.h"
|
#include "search.h"
|
||||||
#include "attack.h"
|
#include "attack.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* perft() - Perform perft on position
|
|
||||||
* @pos: &position to search
|
|
||||||
* @depth: Wanted depth.
|
|
||||||
* @ply: current perft depth level (root = 1)
|
|
||||||
* @divide: output total for 1st level moves.
|
|
||||||
*
|
|
||||||
* Run perft on a position. This function displays the available moves at @depth
|
|
||||||
* level for each possible first move, and the total of moves.
|
|
||||||
*
|
|
||||||
* This version uses the algorithm:
|
|
||||||
* if last depth
|
|
||||||
* return 1;
|
|
||||||
* gen legal moves
|
|
||||||
* loop for legal move
|
|
||||||
* do-move
|
|
||||||
* perft (depth -1)
|
|
||||||
* undo-move
|
|
||||||
*
|
|
||||||
* @return: total moves found at @depth level.
|
|
||||||
*/
|
|
||||||
u64 perft(pos_t *pos, int depth, int ply, bool divide)
|
|
||||||
{
|
|
||||||
u64 subnodes = 0, nodes = 0;
|
|
||||||
movelist_t movelist;
|
|
||||||
move_t *move, *last;
|
|
||||||
state_t state;
|
|
||||||
|
|
||||||
pos_set_checkers_pinners_blockers(pos);
|
|
||||||
|
|
||||||
pos_legal(pos, pos_gen_pseudo(pos, &movelist));
|
|
||||||
last = movelist.move + movelist.nmoves;
|
|
||||||
for (move = movelist.move; move < last; ++move) {
|
|
||||||
if (depth == 1) {
|
|
||||||
subnodes = 1;
|
|
||||||
} else {
|
|
||||||
move_do(pos, *move, &state);
|
|
||||||
if (depth == 2) {
|
|
||||||
movelist_t movelist2;
|
|
||||||
pos_set_checkers_pinners_blockers(pos);
|
|
||||||
subnodes = pos_legal(pos, pos_gen_pseudo(pos, &movelist2))->nmoves;
|
|
||||||
} else if (ply >= 3) {
|
|
||||||
hentry_t *entry = tt_probe_perft(pos->key, depth);
|
|
||||||
if (entry != TT_MISS) {
|
|
||||||
subnodes = HASH_PERFT_VAL(entry->data);
|
|
||||||
} else {
|
|
||||||
subnodes = perft(pos, depth - 1, ply + 1, divide);
|
|
||||||
tt_store_perft(pos->key, depth, subnodes);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
subnodes = perft(pos, depth - 1, ply + 1, divide);
|
|
||||||
}
|
|
||||||
move_undo(pos, *move, &state);
|
|
||||||
}
|
|
||||||
nodes += subnodes;
|
|
||||||
if (ply == 1 && divide) {
|
|
||||||
char movestr[8];
|
|
||||||
printf("%s: %lu\n", move_to_str(movestr, *move, 0), subnodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* perft_alt() - Perform perft on position, experimental version.
|
|
||||||
* @pos: &position to search
|
|
||||||
* @depth: Wanted depth.
|
|
||||||
* @ply: current perft depth level (root = 1)
|
|
||||||
* @divide: output total for 1st level moves.
|
|
||||||
*
|
|
||||||
* Run perft on a position. This function displays the available moves at @depth
|
|
||||||
* level for each possible first move, and the total of moves.
|
|
||||||
*
|
|
||||||
* @return: total moves found at @depth level.
|
|
||||||
*/
|
|
||||||
u64 perft_alt(pos_t *pos, int depth, int ply, bool divide)
|
|
||||||
{
|
|
||||||
u64 subnodes = 0, nodes = 0;
|
|
||||||
movelist_t movelist;
|
|
||||||
move_t *move, *last;
|
|
||||||
state_t state;
|
|
||||||
|
|
||||||
pos_set_checkers_pinners_blockers(pos);
|
|
||||||
|
|
||||||
pos_legal(pos, pos_gen_pseudo(pos, &movelist));
|
|
||||||
last = movelist.move + movelist.nmoves;
|
|
||||||
for (move = movelist.move; move < last; ++move) {
|
|
||||||
if (depth == 1) {
|
|
||||||
subnodes = 1;
|
|
||||||
} else {
|
|
||||||
move_do_alt(pos, *move, &state);
|
|
||||||
if (depth == 2) {
|
|
||||||
movelist_t movelist2;
|
|
||||||
pos_set_checkers_pinners_blockers(pos);
|
|
||||||
subnodes = pos_legal(pos, pos_gen_pseudo(pos, &movelist2))->nmoves;
|
|
||||||
} else {
|
|
||||||
subnodes = perft_alt(pos, depth - 1, ply + 1, divide);
|
|
||||||
}
|
|
||||||
move_undo_alt(pos, *move, &state);
|
|
||||||
}
|
|
||||||
nodes += subnodes;
|
|
||||||
if (ply == 1 && divide) {
|
|
||||||
char movestr[8];
|
|
||||||
printf("%s: %lu\n", move_to_str(movestr, *move, 0), subnodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* negamax() - search position negamax.
|
* negamax() - search position negamax.
|
||||||
* @pos: &position to search
|
* @pos: &position to search
|
||||||
|
@@ -19,7 +19,4 @@
|
|||||||
//eval_t negamax(pos_t *pos, int depth, int color);
|
//eval_t negamax(pos_t *pos, int depth, int color);
|
||||||
//eval_t pvs(pos_t *pos, int depth, int alpha, int beta, int color);
|
//eval_t pvs(pos_t *pos, int depth, int alpha, int beta, int color);
|
||||||
|
|
||||||
u64 perft(pos_t *pos, int depth, int ply, bool output);
|
|
||||||
u64 perft_alt(pos_t *pos, int depth, int ply, bool output);
|
|
||||||
|
|
||||||
#endif /* SEARCH_H */
|
#endif /* SEARCH_H */
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include "move-gen.h"
|
#include "move-gen.h"
|
||||||
#include "move-do.h"
|
#include "move-do.h"
|
||||||
#include "search.h"
|
#include "search.h"
|
||||||
|
#include "perft.h"
|
||||||
#include "eval-defs.h"
|
#include "eval-defs.h"
|
||||||
#include "uci.h"
|
#include "uci.h"
|
||||||
|
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
#include "move.h"
|
#include "move.h"
|
||||||
#include "move-do.h"
|
#include "move-do.h"
|
||||||
#include "move-gen.h"
|
#include "move-gen.h"
|
||||||
#include "search.h"
|
#include "perft.h"
|
||||||
|
|
||||||
#include "common-test.h"
|
#include "common-test.h"
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user