UCI moves && games states list
This commit is contained in:
8
Makefile
8
Makefile
@@ -148,6 +148,9 @@ else ifeq ($(BUILD),perf)
|
||||
CFLAGS += -g # symbols (gdb, perf, etc.)
|
||||
CFLAGS += -ginline-points # inlined funcs debug info
|
||||
CFLAGS += -funroll-loops
|
||||
else ifeq ($(BUILD),debug)
|
||||
CFLAGS += -O0
|
||||
CFLAGS += -g # symbols (gdb, perf, etc.)
|
||||
# for gprof
|
||||
#CFLAGS += -pg
|
||||
# Next one may be useful for valgrind (when invalid instructions)
|
||||
@@ -207,7 +210,7 @@ $(sort all $(MAKECMDGOALS)):
|
||||
else
|
||||
|
||||
##################################### General targets
|
||||
.PHONY: all release dev perf compile clean cleanall
|
||||
.PHONY: all release dev perf debug compile clean cleanall
|
||||
|
||||
all: testing $(TARGET)
|
||||
|
||||
@@ -220,6 +223,9 @@ dev:
|
||||
perf:
|
||||
$(MAKE) BUILD=perf clean all
|
||||
|
||||
debug:
|
||||
$(MAKE) BUILD=debug clean all
|
||||
|
||||
compile: brlib objs
|
||||
|
||||
libs: brlib
|
||||
|
@@ -26,6 +26,9 @@
|
||||
#include "hash.h"
|
||||
#include "fen.h"
|
||||
#include "search.h"
|
||||
#include "hist.h"
|
||||
#include "move-gen.h"
|
||||
#include "move-do.h"
|
||||
|
||||
struct command {
|
||||
char *name; /* User printable name */
|
||||
@@ -252,6 +255,7 @@ int do_ucinewgame(__unused pos_t *pos, __unused char *arg)
|
||||
{
|
||||
pos_clear(pos);
|
||||
tt_clear();
|
||||
hist_init();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -275,37 +279,74 @@ int do_position(pos_t *pos, char *arg)
|
||||
{
|
||||
char *saveptr, *token, *fen, *moves;
|
||||
|
||||
hist_init();
|
||||
|
||||
/* separate "moves" section */
|
||||
saveptr = NULL;
|
||||
if ((moves = strstr(arg, "moves"))) {
|
||||
*(moves - 1) = 0;
|
||||
token = strtok_r(moves, " ", &saveptr);
|
||||
}
|
||||
saveptr = NULL;
|
||||
token = strtok_r(arg, " ", &saveptr);
|
||||
if (!strcmp(token, "startpos")) {
|
||||
startpos(pos);
|
||||
do_diagram(pos, "");
|
||||
} else if (!strcmp(token, "fen")) {
|
||||
fen = strtok_r(NULL, " ", &saveptr);
|
||||
fen2pos(pos, fen);
|
||||
} else {
|
||||
puts("fuck");
|
||||
}
|
||||
|
||||
if (moves) {
|
||||
saveptr = NULL;
|
||||
moves = strtok_r(moves, " ", &saveptr);
|
||||
moves = strtok_r(NULL, "", &saveptr);
|
||||
printf("moves = %s\n", moves);
|
||||
do_moves(pos, moves);
|
||||
}
|
||||
|
||||
saveptr = NULL;
|
||||
token = strtok_r(arg, " ", &saveptr);
|
||||
if (!strcmp(token, "startpos")) {
|
||||
startpos(pos);
|
||||
} else if (!strcmp(token, "fen")) {
|
||||
fen = strtok_r(NULL, "", &saveptr);
|
||||
fen2pos(pos, fen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static move_t *move_find_move(move_t target, movelist_t *list)
|
||||
{
|
||||
move_t *move = list->move, *last = move + list->nmoves;
|
||||
|
||||
for (; move < last; ++move) {
|
||||
if (move_from(target) == move_from(*move) &&
|
||||
move_to(target) == move_to(*move) &&
|
||||
move_to(target) == move_to(*move) &&
|
||||
move_promoted(target) == move_promoted(*move))
|
||||
return move;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int do_moves(__unused pos_t *pos, char *arg)
|
||||
{
|
||||
char *saveptr = NULL, *move;
|
||||
|
||||
char *saveptr = NULL, *token, check[8];
|
||||
move_t move, *foundmove;
|
||||
state_t state;
|
||||
movelist_t movelist;
|
||||
saveptr = NULL;
|
||||
move = strtok_r(arg, " ", &saveptr);
|
||||
while (move) {
|
||||
printf("move: [%s]\n", move);
|
||||
move = strtok_r(NULL, " ", &saveptr);
|
||||
token = strtok_r(arg, " ", &saveptr);
|
||||
while (token) {
|
||||
move = move_from_str(pos, token);
|
||||
move_to_str(check, move, 0);
|
||||
|
||||
printf("move: [%s] %s\n", token, check);
|
||||
pos_set_checkers_pinners_blockers(pos);
|
||||
pos_legal(pos, pos_gen_pseudo(pos, &movelist));
|
||||
foundmove = move_find_move(move, &movelist);
|
||||
if (!foundmove) {
|
||||
printf("illegal move");
|
||||
return 1;
|
||||
}
|
||||
move_do(pos, *foundmove, &state);
|
||||
hist_push(&state, &move);
|
||||
token = strtok_r(NULL, " ", &saveptr);
|
||||
}
|
||||
hist_static_print();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -97,9 +97,10 @@ typedef u64 bitboard_t;
|
||||
*/
|
||||
//typedef s32 eval_t;
|
||||
|
||||
/* forward enum definition is impossible in C11, to simplify
|
||||
* cross-dependancies, all important enum are moved here.
|
||||
/* forward enum definition is impossible in C11.
|
||||
* To simplify cross-dependancies, all important enum are moved here.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
_SSQUARE_ = -1, /* force signed enum */
|
||||
A1 = 0, B1, C1, D1, E1, F1, G1, H1,
|
||||
|
123
src/hist.c
Normal file
123
src/hist.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/* hist.c - history management.
|
||||
*
|
||||
* Copyright (C) 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 <brlib.h>
|
||||
#include <bug.h>
|
||||
|
||||
#include "position.h"
|
||||
#include "hash.h"
|
||||
#include "move.h"
|
||||
#include "hist.h"
|
||||
|
||||
hist_t hist = {
|
||||
.nstates = 1,
|
||||
{ { .move = MOVE_NO_MOVE, .key = U64(0), .prev = &hist.state[0] } },
|
||||
};
|
||||
|
||||
/**
|
||||
* hist_init() - initialize history states data.
|
||||
*
|
||||
* This should be done every time a new position must be handled.
|
||||
*/
|
||||
void hist_init(void)
|
||||
{
|
||||
hist.nstates = 1;
|
||||
hist.state[0].key = U64(0);
|
||||
hist.state[0].move = MOVE_NO_MOVE;
|
||||
hist.state[0].prev = &hist.state[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* hist_push() - add a state and move to hist
|
||||
* @st: &state_t to add
|
||||
* @move: &move_t to add in @st
|
||||
*/
|
||||
void hist_push(state_t *st, move_t *move)
|
||||
{
|
||||
int last = hist.nstates++;
|
||||
|
||||
bug_on(last >= HIST_SIZE);
|
||||
hist.state[last] = *st;
|
||||
hist.state[last].prev = &hist.state[last - 1];
|
||||
hist.state[last].move = *move;
|
||||
}
|
||||
|
||||
/**
|
||||
* hist_pop() - return last state from hist entry, and remove it from list
|
||||
*
|
||||
* Not used, only for debug.
|
||||
*/
|
||||
state_t *hist_pop(void)
|
||||
{
|
||||
return hist.state + --hist.nstates;
|
||||
}
|
||||
|
||||
/**
|
||||
* hist_last() - return last state from hist.
|
||||
*/
|
||||
state_t *hist_last(void)
|
||||
{
|
||||
return hist.state + hist.nstates - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* hist_prev() - return a state's ancestor.
|
||||
* @st: &state_t state
|
||||
*
|
||||
* No test is done on ancestor. Caller should check it is different
|
||||
* from HIST_START.
|
||||
*/
|
||||
state_t *hist_prev(state_t *st)
|
||||
{
|
||||
return st->prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* hist_prev2() - return a state's second ancestor.
|
||||
* @st: &state_t state
|
||||
*
|
||||
* No test is done on ancestors. Caller should check it is different
|
||||
* from HIST_START.
|
||||
*/
|
||||
state_t *hist_prev2(state_t *st)
|
||||
{
|
||||
return st->prev->prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* hist_prev4() - return a state's 4th ancestor.
|
||||
* @st: &state_t state
|
||||
*
|
||||
* No test is done on ancestors. Caller should check it is different
|
||||
* from HIST_START.
|
||||
*/
|
||||
state_t *hist_prev4(state_t *st)
|
||||
{
|
||||
return st->prev->prev->prev->prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* hist_print() - print hist entries
|
||||
*/
|
||||
void hist_static_print(void)
|
||||
{
|
||||
char movestr[8];
|
||||
|
||||
printf("rev history: ");
|
||||
for (state_t *p = hist_last(); p != HIST_START; p = hist_prev(p)) {
|
||||
printf("%s(%lx) ",
|
||||
p->move == MOVE_NO_MOVE? "none": move_to_str(movestr, p->move, 0),
|
||||
hash_short(p->key));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
59
src/hist.h
Normal file
59
src/hist.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* hist.h - history management.
|
||||
*
|
||||
* Copyright (C) 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 HIST_H
|
||||
#define HIST_H
|
||||
|
||||
#include <brlib.h>
|
||||
#include <bug.h>
|
||||
|
||||
#include "position.h"
|
||||
#include "hash.h"
|
||||
|
||||
#define HIST_SIZE 4096 /* I know, I know... */
|
||||
|
||||
/**
|
||||
* hist - history states data.
|
||||
*
|
||||
* This variable is of type hist_t, which contains:
|
||||
* @state: state_t array, size HIST_SIZE
|
||||
* @nstates: current number of @state
|
||||
*
|
||||
* hist contains moves already played.
|
||||
*
|
||||
* Only HIST_SIZE - 1 hist elements are available, as the first element is
|
||||
* used as a sentinel value (hist[0].state.prev = &hist[0].state).
|
||||
* This first element allows multiple backards searches (p->prev->prev).
|
||||
*
|
||||
* hist is only written by main thread, and read by other threads/processes,
|
||||
* therefore is never duplicated (even after a fork(), due to COW).
|
||||
*/
|
||||
typedef struct {
|
||||
int nstates;
|
||||
state_t state[HIST_SIZE];
|
||||
} hist_t;
|
||||
|
||||
extern hist_t hist;
|
||||
|
||||
#define HIST_START (hist.state)
|
||||
|
||||
void hist_init(void);
|
||||
void hist_push(state_t *st, move_t *move);
|
||||
state_t *hist_pop(void);
|
||||
state_t *hist_last(void);
|
||||
state_t *hist_prev(state_t *st);
|
||||
state_t *hist_prev2(state_t *st);
|
||||
state_t *hist_prev4(state_t *st);
|
||||
void hist_static_print(void);
|
||||
|
||||
#endif /* HIST_H */
|
@@ -80,7 +80,6 @@ pos_t *move_do(pos_t *pos, const move_t move, state_t *state)
|
||||
|
||||
if (captured != EMPTY) {
|
||||
pos->clock_50 = 0;
|
||||
//pos->captured = pos->board[to]; /* save capture info */
|
||||
bug_on(pos->board[to] == EMPTY || COLOR(pos->captured) != them);
|
||||
key ^= zobrist_pieces[captured][to];
|
||||
pos_clr_sq(pos, to); /* clear square */
|
||||
|
31
src/move.c
31
src/move.c
@@ -116,6 +116,37 @@ char *move_to_str(char *dst, const move_t move, __unused const int flags)
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* move_from_str() - create a move from a position and UCI move string
|
||||
* @pos: &pos_t
|
||||
* @str: uci move string
|
||||
*
|
||||
* string and corresponding move are considered valid (no check is done).
|
||||
*
|
||||
* @return move, or NULL if error.
|
||||
*/
|
||||
move_t move_from_str(const pos_t *pos, const char *str)
|
||||
{
|
||||
move_t move;
|
||||
square_t from = sq_from_string(str);
|
||||
square_t to = sq_from_string(str + 2);
|
||||
piece_type_t piece = PIECE(pos->board[from]);
|
||||
piece_type_t promoted = piece_t_from_char(*(str+5));
|
||||
|
||||
if (piece == KING && sq_dist(from, to) > 1) { /* castling */
|
||||
move = move_make_flags(from, to, M_CASTLE);
|
||||
} else if (piece == PAWN && /* en-passant */
|
||||
sq_file(from) != sq_file(to) &&
|
||||
pos->board[to] == EMPTY) {
|
||||
move = move_make_enpassant(from, to);
|
||||
} else if (promoted != NO_PIECE_TYPE) { /* promotion */
|
||||
move = move_make_promote(from, to, promoted);
|
||||
} else {
|
||||
move = move_make(from, to);
|
||||
}
|
||||
return move;
|
||||
}
|
||||
|
||||
/**
|
||||
* moves_print() - print movelist moves.
|
||||
* @moves: &movelist_t moves list
|
||||
|
12
src/move.h
12
src/move.h
@@ -29,11 +29,7 @@
|
||||
* ppp 3 12 12-14 piece_type_t 070000 (>>12) &07 promoted
|
||||
* FFF 3 15 15-17 move_flags_t 0700000 (>>15) &07 flags
|
||||
*/
|
||||
typedef s32 move_t;
|
||||
|
||||
/* special move_t values */
|
||||
#define MOVE_NONE ((move_t) -1)
|
||||
#define MOVE_NULL ((move_t) 0) /* hack: from = to = A1 */
|
||||
typedef u32 move_t;
|
||||
|
||||
enum {
|
||||
M_OFF_FROM = 0,
|
||||
@@ -50,6 +46,11 @@ typedef enum {
|
||||
// M_CHECK = (3 << M_OFF_FLAGS) /* maybe unknown/useless ? */
|
||||
} move_flags_t;
|
||||
|
||||
/* special move_t values */
|
||||
#define MOVE_NULL 0 /* hack: from = to = A1 */
|
||||
#define MOVE_NONE 07777 /* hack: from = to = H8 */
|
||||
#define MOVE_NO_MOVE 01010 /* hack: from = to = A2 */
|
||||
|
||||
#define move_set_flags(move, flags) ((move) | (flags))
|
||||
#define move_flags(move) ((move) & M_FLAGS_MASK)
|
||||
|
||||
@@ -144,6 +145,7 @@ static inline move_t move_make_promote(square_t from, square_t to,
|
||||
|
||||
//int move_print(int movenum, move_t *move, move_flags_t flags);
|
||||
char *move_to_str(char *dst, const move_t move, __unused const int flags);
|
||||
move_t move_from_str(const pos_t *pos, const char *str);
|
||||
void moves_print(movelist_t *moves, int flags);
|
||||
void move_sort_by_sq(movelist_t *moves);
|
||||
|
||||
|
Reference in New Issue
Block a user