10 Commits

13 changed files with 200 additions and 147 deletions

View File

@@ -1,3 +1,3 @@
((nil . ((compile-command . (concat "make -C "
(vc-root-dir)
" -k -j4 testing")))))
" -k -j4 dev")))))

View File

@@ -1,2 +1,2 @@
** Some current ideas
- helpers for square, pieces, etc: validity, conversions
- hmmm. Empty brain.

View File

@@ -19,7 +19,7 @@ ifeq ($(CC),cc)
CC = gcc
endif
ifeq ($(BUILD),)
BUILD = perf
BUILD = dev
endif
BEAR := bear
@@ -398,9 +398,9 @@ TEST += movedo-test perft-test tt-test
PIECE_OBJS := piece.o
FEN_OBJS := $(PIECE_OBJS) fen.o position.o bitboard.o board.o \
hyperbola-quintessence.o attack.o hash.o init.o misc.o
hyperbola-quintessence.o attack.o hash.o init.o misc.o move.o
BB_OBJS := $(FEN_OBJS)
MOVEGEN_OBJS := $(BB_OBJS) move.o move-gen.o
MOVEGEN_OBJS := $(BB_OBJS) move-gen.o
ATTACK_OBJS := $(MOVEGEN_OBJS)
MOVEDO_OBJS := $(ATTACK_OBJS) move-do.o
PERFT_OBJS := $(MOVEDO_OBJS) search.o

View File

@@ -50,6 +50,7 @@ int do_moves(pos_t *, char *);
int do_diagram(pos_t *, char *);
int do_perft(pos_t *, char *);
int do_hist(pos_t *, char *);
int do_help(pos_t *, char *);
int do_quit(pos_t *, char *);
@@ -67,6 +68,7 @@ struct command commands[] = {
{ "perft", do_perft, "(not UCI) perft [divide] [alt] depth" },
{ "moves", do_moves, "(not UCI) moves ..." },
{ "diagram", do_diagram, "(not UCI) print current position diagram" },
{ "hist", do_hist, "(not UCI) print history states" },
/*
* { "init", do_init, "Set position to normal start position" },
@@ -255,7 +257,6 @@ int do_ucinewgame(__unused pos_t *pos, __unused char *arg)
{
pos_clear(pos);
tt_clear();
hist_init();
return 1;
}
@@ -291,62 +292,62 @@ int do_position(pos_t *pos, char *arg)
startpos(pos);
do_diagram(pos, "");
} else if (!strcmp(token, "fen")) {
fen = strtok_r(NULL, " ", &saveptr);
fen2pos(pos, fen);
fen = strtok_r(NULL, "", &saveptr); /* full fen (till '\0') */
//printf("fen=%s\n", fen);
if (!fen)
return 1;
if (!fen2pos(pos, fen))
return 1;
//do_diagram(pos, "");
} else {
puts("fuck");
return 1;
}
//puts("zob");
//move_t move_none = MOVE_NONE;
//hist_push(&pos->state, &move_none);
if (moves) {
//puts("zobi");
saveptr = NULL;
moves = strtok_r(moves, " ", &saveptr);
moves = strtok_r(NULL, "", &saveptr);
printf("moves = %s\n", moves);
moves = strtok_r(moves, " ", &saveptr); /* skip "moves" */
moves = strtok_r(NULL, "", &saveptr); /* all moves (till '\0') */
//printf("moves = %s\n", moves);
do_moves(pos, moves);
}
/* link last position t history */
//hist_pop();
hist_link(pos);
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, *token, check[8];
move_t move, *foundmove;
move_t move;
state_t state;
movelist_t movelist;
saveptr = NULL;
token = strtok_r(arg, " ", &saveptr);
while (token) {
move = move_from_str(pos, token);
move = move_from_str(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");
move = move_find_in_movelist(move, &movelist);
if (move == MOVE_NONE) {
/* should we reset here ? */
return 1;
}
move_do(pos, *foundmove, &state);
hist_push(&state, &move);
//printf("move: %s\n", move_to_str(check, move, 0));
hist_push(&pos->state); /* push previous state */
move_do(pos, move, &state);
pos_print(pos);
hist_static_print();
token = strtok_r(NULL, " ", &saveptr);
}
hist_static_print();
//hist_static_print();
return 1;
}
@@ -381,13 +382,12 @@ int do_perft(__unused pos_t *pos, __unused char *arg)
return 1;
}
/*
* int do_debug(__unused pos_t *pos, __unused char *arg)
* {
* debug_level_set(atoi(arg));
* return 1;
* }
*/
int do_hist(__unused pos_t *pos, __unused char *arg)
{
hist_static_print();
return 0;
}
int do_help(__unused pos_t *pos, __unused char *arg)
{
@@ -516,11 +516,13 @@ static int usage(char *prg)
int main(int ac, char **av)
{
pos_t *pos = pos_new();
pos_t *pos;
int opt;
printf("brchess " VERSION "\n");
init_all();
pos = pos_new();
hist_link(pos);
printf("\nWelcome to brchess " VERSION "\nEngine ready.\n");
// size_t len = 0;
// char *str = NULL;

View File

@@ -14,9 +14,11 @@
#ifndef HASH_H
#define HASH_H
#include <brlib.h>
#include <bug.h>
#include "chessdefs.h"
#include "move.h"
#define ENTRIES_PER_BUCKET 4 /* buckets per hash table entry */
@@ -31,9 +33,9 @@
typedef u64 hkey_t; /* cannot use typedef for key_t */
/**
* hash_short: return the value of a hash first 7 MSB.
* hash_short: get the most significant 7 nibble of a 64 bits value.
*/
#define hash_short(hash) ((hash) >> (64 - 8))
#define hash_short(hash) ((hash) >> (64 - 4 * 7))
/**
* hentry_t: hashtable bucket.
@@ -48,9 +50,9 @@ typedef struct {
struct {
u16 depth; /* ply in search */
s16 eval;
u16 move;
u8 flags; /* maybe for locking, etc... */
u8 filler;
move_t move;
//u8 flags; /* maybe for locking, etc... */
//u8 filler;
};
};
} hentry_t;

View File

@@ -21,7 +21,7 @@
hist_t hist = {
.nstates = 1,
{ { .move = MOVE_NO_MOVE, .key = U64(0), .prev = &hist.state[0] } },
{ { .move = MOVE_NONE, .key = U64(0), .prev = &hist.state[0] } },
};
/**
@@ -33,23 +33,39 @@ void hist_init(void)
{
hist.nstates = 1;
hist.state[0].key = U64(0);
hist.state[0].move = MOVE_NO_MOVE;
hist.state[0].move = MOVE_NONE;
hist.state[0].prev = &hist.state[0];
}
/**
* hist_push() - add a state and move to hist
* hist_push() - add a state to hist list
* @st: &state_t to add
* @move: &move_t to add in @st
*
* Used to add moves when the UCI "position" command includes moves.
* These moves, but last one, should be pushed. Last move should be
* linked to hist with @hist_link().
*/
void hist_push(state_t *st, move_t *move)
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.state[last].move = *move;
}
/**
* hist_link() - link a position to last hist element.
* @pos: &pos_t to link
*
* Used to add position resulting from last "move" in UCI "position" command.
* All other moves in UCI "position" command should be pushed instead, with
* hist_push().
*/
void hist_link(pos_t *pos)
{
pos->prev = hist_last();
}
/**
@@ -59,7 +75,9 @@ void hist_push(state_t *st, move_t *move)
*/
state_t *hist_pop(void)
{
return hist.state + --hist.nstates;
if (hist.nstates > 1)
hist.nstates--;
return hist_last();
}
/**
@@ -107,17 +125,41 @@ state_t *hist_prev4(state_t *st)
}
/**
* hist_print() - print hist entries
* hist_static_print() - print hist entries
*/
void hist_static_print(void)
{
char movestr[8];
state_t *st = hist_last();
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("UCI state history: ");
while (true) {
printf("%s(#%lx) ",
move_to_str(movestr, st->move, 0),
hash_short(st->key));
if (st == HIST_START)
break;
st = hist_prev(st);
}
printf("\n");
}
/**
* hist_print() - print position history
* @pos: &pos to start from
*/
void hist_print(pos_t *pos)
{
char movestr[8];
state_t *st = &pos->state;
printf("position states history: ");
while (true) {
printf("%s(#%lx) ",
move_to_str(movestr, st->move, 0),
hash_short(st->key));
if (st == HIST_START)
break;
st = hist_prev(st);
}
printf("\n");
}

View File

@@ -48,12 +48,14 @@ extern hist_t hist;
#define HIST_START (hist.state)
void hist_init(void);
void hist_push(state_t *st, move_t *move);
void hist_push(state_t *st); //, move_t *move);
void hist_link(pos_t *pos);
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);
void hist_print(pos_t *pos);
#endif /* HIST_H */

View File

@@ -12,6 +12,7 @@
*/
#include <stdio.h>
#include <unistd.h>
#include <locale.h>
#include "chessdefs.h"
@@ -20,23 +21,36 @@
#include "hyperbola-quintessence.h"
#include "hash.h"
#include "hist.h"
#define printff(x) ({ printf(x); fflush(stdout); })
void init_all(void)
{
/* for printf() numeric thousands separator */
setlocale(LC_NUMERIC, "");
/* line-buffered stdout */
printff("initiazing stdout buffering... ");
setlinebuf(stdout);
/* for printf() numeric thousands separator */
printff("locale... ");
setlocale(LC_NUMERIC, "");
/* pseudo random generator seed */
printff("random generator... ");
rand_init(RAND_SEED_DEFAULT);
/* bitboards & hq */
printff("bitboards... ");
bitboard_init();
printff("hq bitboards... ");
hyperbola_init();
/* zobrist tables & default tt hashtable */
printff("zobrist tables... ");
zobrist_init();
printff("transposition tables... ");
tt_create(HASH_SIZE_DEFAULT);
printf("done.\n");
}

View File

@@ -70,6 +70,7 @@ pos_t *move_do(pos_t *pos, const move_t move, state_t *state)
pos->en_passant = SQUARE_NONE;
pos->turn = them;
pos->captured = captured;
pos->move = move;
bug_on(COLOR(piece) != us);
@@ -237,6 +238,7 @@ pos_t *move_do_alt(pos_t *pos, const move_t move, state_t *state)
pos->en_passant = SQUARE_NONE;
pos->turn = them;
pos->captured = captured;
pos->move = move;
bug_on(COLOR(piece) != us);

View File

@@ -94,6 +94,8 @@
* @move: move
* @flags: moves selection and display options.
*
* @dst should be large enough to contain move string + '\0' terminator.
*
* Possible flags are:
* M_PR_CAPT: print move if capture
* M_PR_NCAPT: print move if non capture
@@ -104,42 +106,43 @@
*/
char *move_to_str(char *dst, const move_t move, __unused const int flags)
{
if (move == MOVE_NONE) {
strcpy(dst, "none");
} else if (move == MOVE_NULL) {
strcpy(dst, "null");
} else {
square_t from = move_from(move);
square_t to = move_to(move);
int len;
sprintf(dst, "%s%s%n", sq_to_string(from), sq_to_string(to), &len);
if (is_promotion(move)) {
piece_t promoted = (piece_t) move_promoted(move);
sprintf(dst + len, "%s", piece_to_low(promoted));
}
}
return dst;
}
/**
* move_from_str() - create a move from a position and UCI move string
* @pos: &pos_t
* move_from_str() - create a move from an UCI move string
* @str: uci move string
*
* string and corresponding move are considered valid (no check is done).
* Only from/to squares and promotion information are filled.
* To get a full move, @move_find_in_movelist() can be called,
* with a list of moves to choose from.
*
* @return move, or NULL if error.
* @return: partial move.
*/
move_t move_from_str(const pos_t *pos, const char *str)
move_t move_from_str(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));
piece_type_t promoted = piece_t_from_char(*(str+4));
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 */
if (promoted != NO_PIECE_TYPE) { /* promotion */
move = move_make_promote(from, to, promoted);
} else {
move = move_make(from, to);
@@ -147,6 +150,31 @@ move_t move_from_str(const pos_t *pos, const char *str)
return move;
}
/**
* move_find_in_movelist() - find a partial move in movelist.
* @target: partial move
* @list: &movelist_t to search
*
* Look for @target into @list. @target must at least contain from and
* to square, as well as promotion information - see move_from_str().
* If these three pieces of information match, the corresponding move in
* @list is returned.
*
* @return: move, or MOVE_NONE if error.
*/
move_t move_find_in_movelist(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_promoted(target) == move_promoted(*move))
return *move;
}
return MOVE_NONE;
}
/**
* moves_print() - print movelist moves.
* @moves: &movelist_t moves list

View File

@@ -49,7 +49,7 @@ typedef enum {
/* 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_NO_MOVE 01010 /* hack: from = to = A2 */
#define move_set_flags(move, flags) ((move) | (flags))
#define move_flags(move) ((move) & M_FLAGS_MASK)
@@ -143,9 +143,9 @@ static inline move_t move_make_promote(square_t from, square_t to,
#define M_PR_SEPARATE 0x40 /* separate captures */
#define M_PR_LONG 0x80
//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);
move_t move_from_str(const char *str);
move_t move_find_in_movelist(move_t target, movelist_t *list);
void moves_print(movelist_t *moves, int flags);
void move_sort_by_sq(movelist_t *moves);

View File

@@ -108,6 +108,7 @@ pos_t *pos_clear(pos_t *pos)
pos->castle = 0;
pos->clock_50 = 0;
pos->plycount = 0;
pos->move = MOVE_NONE;
pos->captured = NO_PIECE;
for (square_t sq = A1; sq <= H8; ++sq)
@@ -430,8 +431,9 @@ void pos_print(const pos_t *pos)
char str[128];
board_print(pos->board);
printf("key:%lx (#%lx)", pos->key, hash_short(pos->key));
printf("fen: %s\n", pos2fen(pos, str));
printf("last move:%s ", move_to_str(str, pos->move, 0));
printf("key:%lx\n", pos->key);
printf("checkers:%s ", pos_checkers2str(pos, str, sizeof(str)));
printf("pinners: %s ", pos_pinners2str(pos, str, sizeof(str)));
printf("blockers: %s\n", pos_blockers2str(pos, str, sizeof(str)));

View File

@@ -29,50 +29,6 @@
#include "move-gen.h"
#include "search.h"
// #include "common-test.h"
static move_t move_in_movelist(movelist_t *ml, square_t from, square_t to, piece_type_t pt)
{
const int nmoves = ml->nmoves;
const move_t *moves = ml->move;
int movenum = 0;
move_t move;
for (movenum = 0; movenum < nmoves; ++movenum) {
move = moves[movenum];
printf("compare %s%s to %s%s pt=%d ",
sq_to_string(from), sq_to_string(to),
sq_to_string(move_from(move)),
sq_to_string(move_to(move)),
pt
);
if (move_from(move) == from && move_to(move) == to) {
printf("HIT!\n");
if (pt != NO_PIECE_TYPE && move_promoted(move) != pt)
continue;
printf("move_in_movelist(%s%s) found from=%s to=%s\n",
sq_to_string(from), sq_to_string(to),
sq_to_string(move_from(move)),
sq_to_string(move_to(move)));
return move;
} else
puts("");
}
return MOVE_NONE;
}
static move_t move_from_str(pos_t *pos, const char *move)
{
movelist_t movelist;
square_t from = sq_from_string(move);
square_t to = sq_from_string(move + 2);
piece_type_t promoted = piece_t_from_char(*(move + 4));
printf("from=%o to=%o promoted=%d\n", from, to, promoted);
pos_set_checkers_pinners_blockers(pos);
pos_legal(pos, pos_gen_pseudo(pos, &movelist));
return move_in_movelist(&movelist, from, to, promoted);
}
static void pr_entry(hentry_t *entry)
{
if (!entry)
@@ -91,7 +47,7 @@ int main()
hentry_t *entry;
move_t move;
state_t state;
//movelist_t movelist;
movelist_t movelist;
const char *moves_array[] = {
"e2e4 e7e5 g1f3 b8c6",
@@ -113,10 +69,12 @@ int main()
depth++;
printf("%s ", token);
//pos_set_checkers_pinners_blockers(pos);
//pos_legal(pos, pos_gen_pseudo(pos, &movelist));
move = move_from_str(pos, token);
move = move_from_str(token);
pos_set_checkers_pinners_blockers(pos);
pos_legal(pos, pos_gen_pseudo(pos, &movelist));
printf("move: %s\n", move_to_str(buf, move, 0));
move = move_find_in_movelist(move, &movelist);
if (move != MOVE_NONE) {
move_do(pos, move, &state);
if ((entry = tt_probe_perft(pos->key, depth))) {
printf("tt hit: depth=%d val=%lu",
@@ -126,6 +84,7 @@ int main()
tt_store_perft(pos->key, i + 1, depth);
printf("tt store: depth=%d val=%lu", depth, (u64)i * 123);
};
}
token = strtok(NULL, " \t");
}