5 Commits

13 changed files with 195 additions and 66 deletions

View File

@@ -25,20 +25,24 @@
#ifdef DEBUG_DEBUG
void debug_init(u32 level, FILE *stream);
void debug_level_set(u32 level);
void debug_init(uint level, FILE *stream, bool flush);
void debug_level_set(uint level);
void debug_stream_set(FILE *stream);
void _printf debug(u32 level, bool timestamp,
u32 indent, const char *src,
u32 line, const char *fmt, ...);
void debug_flush_set(bool flush);
void _printf debug(uint level, bool timestamp,
uint indent, const char *src,
uint line, const char *fmt, ...);
#else /* DEBUG_DEBUG */
static inline void debug_init(__unused u32 level, __unused FILE *stream) {}
static inline void debug_level_set(__unused u32 level) {}
static inline void debug_init(__unused uint level,
__unused FILE *stream,
_unused bool flush) {}
static inline void debug_level_set(__unused uint level) {}
static inline void debug_stream_set(__unused FILE *stream) {}
static inline void _printf debug(__unused u32 level, __unused bool timestamp,
__unused u32 indent, __unused const char *src,
__unused u32 line, __unused const char *fmt, ...) {}
static inline void debug_flush_set(__unused bool level) {}
static inline void _printf debug(__unused uint level, __unused bool timestamp,
__unused uint indent, __unused const char *src,
__unused uint line, __unused const char *fmt, ...) {}
#endif /* DEBUG_DEBUG */

View File

@@ -26,10 +26,15 @@
#define MILLISEC 1000000 /* milli sec in sec */
static long long timer_start; /* in nanosecond */
static u32 debug_level = 0;
static uint debug_level = 0;
static bool debug_flush = false;
static FILE *stream = NULL;
void debug_level_set(u32 level)
/**
* debug_level_set() - set debug level.
* @level: unsigned debug level.
*/
void debug_level_set(uint level)
{
debug_level = level;
log(0, "debug level set to %u\n", level);
@@ -41,12 +46,19 @@ void debug_stream_set(FILE *_stream)
log(0, "stream set to %d\n", stream? fileno(stream): -1);
}
void debug_init(u32 level, FILE *_stream)
void debug_flush_set(bool flush)
{
debug_flush = flush;
log(0, "debug flush set to %d\n", flush);
}
void debug_init(uint level, FILE *_stream, bool flush)
{
struct timespec timer;
debug_stream_set(_stream);
debug_level_set(level);
debug_flush_set(flush);
if (!clock_gettime(CLOCK_MONOTONIC, &timer)) {
timer_start = timer.tv_sec * NANOSEC + timer.tv_nsec;
}
@@ -64,14 +76,16 @@ inline static long long timer_elapsed()
return (timer.tv_sec * NANOSEC + timer.tv_nsec) - timer_start;
}
/* void debug - log function
* @timestamp : boolean
* @indent : indent level (2 spaces each)
* @src : source file/func name (or NULL)
* @line : line number
/**
* debug() - log function
* @level: log level
* @timestamp: boolean, print timestamp if true
* @indent: indent level (2 spaces each)
* @src: source file/func name (or NULL)
* @line: line number
*/
void debug(u32 level, bool timestamp, u32 indent, const char *src,
u32 line, const char *fmt, ...)
void debug(uint level, bool timestamp, uint indent, const char *src,
uint line, const char *fmt, ...)
{
if (!stream || level > debug_level)
return;
@@ -96,6 +110,8 @@ void debug(u32 level, bool timestamp, u32 indent, const char *src,
va_start(ap, fmt);
vfprintf(stream, fmt, ap);
va_end(ap);
if (debug_flush)
fflush(stream);
}
#ifdef BIN_debug

View File

@@ -29,6 +29,7 @@
#include "move.h"
#include "fen.h"
#include "eval.h"
#include "search.h"
struct command {
char *name; /* User printable name */
@@ -62,6 +63,8 @@ int do_eval(pos_t *, char*);
int do_move(pos_t *, char*);
int do_quit(pos_t *, char*);
int do_debug(pos_t *, char*);
int do_depth(pos_t *, char*);
int do_search(pos_t *, char*);
struct command commands[] = {
{ "help", do_help, "Display this text" },
@@ -78,10 +81,13 @@ struct command commands[] = {
{ "eval", do_eval, "Eval current position" },
{ "do_move", do_move, "execute nth move on current position" },
{ "debug", do_debug, "Set log level to LEVEL" },
{ "depth", do_depth, "Set search depth to N" },
{ "search", do_search, "Search best move" },
{ NULL, (int(*)()) NULL, NULL }
};
static int done=0;
static int depth=1;
int brchess(pos_t *pos)
{
@@ -377,7 +383,7 @@ int do_debug(__unused pos_t *pos, __unused char *arg)
not present. */
int do_help(__unused pos_t *pos, __unused char *arg)
{
register int i;
int i;
int printed = 0;
for (i = 0; commands[i].name; i++) {
@@ -407,6 +413,23 @@ int do_help(__unused pos_t *pos, __unused char *arg)
return 0;
}
int do_depth(__unused pos_t *pos, char *arg)
{
depth = atoi(arg);
printf("depth = %d\n", depth);
return 1;
}
int do_search(pos_t *pos, __unused char *arg)
{
printf("++++++++\nnegamax=%d\n", negamax(pos, depth, pos->turn==WHITE? 1:-1));
printf("best=");
move_print(0, pos->bestmove, 0);
printf("score=%d\n", pos->bestmove->negamax);
return 1;
}
#ifdef BIN_brchess
/** main()
* options:
@@ -430,7 +453,7 @@ int main(int ac, char **av)
moves_pool_init();
pos_pool_init();
pos = pos_get();
debug_init(1, stderr);
debug_init(1, stderr, true);
while ((opt = getopt(ac, av, "d:f:")) != -1) {
switch (opt) {

View File

@@ -112,5 +112,6 @@ typedef s32 eval_t;
typedef struct piece_list_s piece_list_t;
typedef struct board_s board_t;
typedef struct pos_s pos_t;
typedef struct move_s move_t;
#endif

View File

@@ -98,7 +98,7 @@ int main(int ac, char**av)
pos_t *pos;
eval_t res;
debug_init(5, stderr);
debug_init(5, stderr, true);
piece_pool_init();
moves_pool_init();

View File

@@ -179,7 +179,7 @@ int main(int ac, char**av)
{
pos_t *pos;
debug_init(5, stderr);
debug_init(5, stderr, true);
piece_pool_init();
pos_pool_init();
pos = pos_get();

View File

@@ -73,18 +73,19 @@ void moves_pool_stats()
* M_PR_NCAPT: print move if non capture
* M_PR_NUM: print also move number
* M_PR_LONG: print long notation
* M_PR_NL: print a newline after move
*
* @return: 0 if nothing printed, 1 otherwise
*/
int move_print(int movenum, move_t *move, move_flags_t flags)
{
if (flags & M_PR_CAPT && !(move->flags & M_CAPTURE)) {
if ((flags & M_PR_CAPT) && !(move->flags & M_CAPTURE)) {
# ifdef DEBUG_MOVE
log_i(9, "skipping capture & %#04x\n", move->flags);
# endif
return 0;
}
if (flags & M_PR_NCAPT && move->flags & M_CAPTURE) {
if ((flags & M_PR_NCAPT) && (move->flags & M_CAPTURE)) {
# ifdef DEBUG_MOVE
log_i(9, "skipping !capture & %#04x\n", move->flags);
# endif
@@ -119,6 +120,8 @@ int move_print(int movenum, move_t *move, move_flags_t flags)
end:
printf(" ");
}
if (flags & M_PR_NL)
printf("\n");
return 1;
}
@@ -660,9 +663,10 @@ void moves_gen_all(pos_t *pos)
{
moves_gen(pos, OPPONENT(pos->turn), false, false);
moves_gen(pos, pos->turn, true, true);
moves_gen_king_moves(pos, OPPONENT(pos->turn), true);
moves_gen_king_moves(pos, OPPONENT(pos->turn), false);
}
/**
* move_do() - execute move in a duplicated position.
* @pos: &pos_t struct on which move will be applied
@@ -672,13 +676,12 @@ void moves_gen_all(pos_t *pos)
pos_t *move_do(pos_t *pos, move_t *move)
{
# ifdef DEBUG_MOVE
log_f(3, "++++++++++");
move_print(0, move, 0);
log(3, "\n");
printf("++++++++++ ");
move_print(0, move, M_PR_NL | M_PR_LONG | M_PR_NUM);
# endif
pos_t *new = pos_dup(pos);
piece_t piece = move->piece;
piece_t piece = PIECE(move->piece), newpiece = piece, captured = move->capture;
int color = COLOR(piece);
square_t from = move->from, to = move->to;
@@ -692,7 +695,7 @@ pos_t *move_do(pos_t *pos, move_t *move)
piece_del(&new->board[to].s_piece->list);
new->board[to].piece = 0;
new->occupied[OPPONENT(color)] ^= SQ88_2_BB(to);
new->bb[OPPONENT(color)][PIECETOBB(piece)] ^= SQ88_2_BB(to);
new->bb[OPPONENT(color)][PIECETOBB(captured)] ^= SQ88_2_BB(to);
} else {
uchar ep_file = F88(pos->en_passant);
square_t ep_grab = color == WHITE ? SQ88(ep_file, 4): SQ88(ep_file, 3);
@@ -700,7 +703,7 @@ pos_t *move_do(pos_t *pos, move_t *move)
piece_del(&new->board[ep_grab].s_piece->list);
new->board[ep_grab].piece = 0;
new->occupied[OPPONENT(color)] ^= SQ88_2_BB(ep_grab);
new->bb[OPPONENT(color)][PIECETOBB(piece)] ^= SQ88_2_BB(ep_grab);
new->bb[OPPONENT(color)][BB_PAWN] ^= SQ88_2_BB(ep_grab);
}
} else if (move->flags & M_CASTLE_Q) {
@@ -729,21 +732,25 @@ pos_t *move_do(pos_t *pos, move_t *move)
new->board[rook_from].s_piece = NULL;
}
new->board[to] = new->board[from];
/* fix dest square */
new->board[to].s_piece->square = to;
if (move->flags & M_PROMOTION) {
log(2, "promotion to %s\n", P_SYM(move->piece));
log(2, "promotion to %s\n", P_SYM(move->promotion));
printf("newpiece=%#x p=%#x\n", move->promotion, PIECE(move->promotion));
newpiece = PIECE(move->promotion);
new->board[to].piece = move->promotion;
new->board[to].s_piece->square = to;
new->board[to].s_piece->piece = move->promotion;
} else {
new->board[to] = new->board[from];
/* fix dest square */
new->board[to].s_piece->square = to;
}
/* replace old occupied bitboard by new one */
new->occupied[color] ^= SQ88_2_BB(from);
new->occupied[color] |= SQ88_2_BB(to);
new->bb[color][PIECETOBB(piece)] ^= SQ88_2_BB(from);
new->bb[color][PIECETOBB(piece)] |= SQ88_2_BB(to);
new->bb[color][PIECETOBB(newpiece)] |= SQ88_2_BB(to);
if (move->flags & M_PROMOTION) {
printf("color=%d bbpiece=%d\n", color, PIECETOBB(newpiece));
bitboard_print(new->bb[color][PIECETOBB(newpiece)]);
}
/* always make "from" square empty */
new->board[from].piece = 0;
@@ -765,7 +772,7 @@ int main(int ac, char**av)
{
pos_t *pos;
debug_init(5, stderr);
debug_init(5, stderr, true);
piece_pool_init();
moves_pool_init();
pos_pool_init();

View File

@@ -35,6 +35,7 @@ typedef unsigned char move_flags_t;
#define M_PR_CAPT 0x01
#define M_PR_NCAPT 0x02
#define M_PR_NUM 0x04
#define M_PR_NL 0x08
#define M_PR_SEPARATE 0x40 /* separate captures */
#define M_PR_LONG 0x80
@@ -44,6 +45,7 @@ typedef struct move_s {
piece_t capture; /* captured piece */
piece_t promotion; /* promoted piece */
move_flags_t flags;
eval_t negamax;
struct list_head list; /* next move */
} move_t;
@@ -65,4 +67,4 @@ void moves_gen_all(pos_t *pos);
pos_t *move_do(pos_t *pos, move_t *move);
void move_undo(pos_t *pos, move_t *move);
#endif /* MODE_H */
#endif /* MOVE_H */

View File

@@ -122,7 +122,7 @@ int main(int ac, char**av)
{
pos_t *pos;
printf("zobi\n");fflush(stdout);
debug_init(6, stderr);
debug_init(6, stderr, true);
log_f(5, "kfsjdhg\n");
pos_pool_init();
pos = pos_get();

View File

@@ -54,6 +54,10 @@ inline void bitboard_print2(bitboard_t bb1, bitboard_t bb2)
BYTE2BIN(bb2>>i));
}
/**
* pos_pieces_print() - Print position pieces
* @pos: &position
*/
void pos_pieces_print(pos_t *pos)
{
printf("White pieces (%d): \t", popcount64(pos->occupied[WHITE]));
@@ -62,10 +66,22 @@ void pos_pieces_print(pos_t *pos)
piece_list_print(&pos->pieces[BLACK]);
}
/* void pos_print - Print position on stdout.
* @pos: Position address (pos_t * )
*
* Return: None.
/**
* pos_bitboards_print() - Print position bitboards
* @pos: &position
*/
void pos_bitboards_print(pos_t *pos)
{
printf("Bitboards occupied :\n");
bitboard_print2(pos->occupied[WHITE], pos->occupied[BLACK]);
printf("Bitboards controlled :\n");
bitboard_print2(pos->controlled[WHITE], pos->controlled[BLACK]);
}
/**
* pos_print() - Print position on stdout.
* @pos: &position
*/
void pos_print(pos_t *pos)
{
@@ -119,10 +135,54 @@ void pos_print(pos_t *pos)
popcount64(pos->controlled[BLACK]));
printf("Mobility: W:%u B:%u\n", pos->mobility[WHITE],
pos->mobility[BLACK]);
printf("Bitboards occupied :\n");
bitboard_print2(pos->occupied[WHITE], pos->occupied[BLACK]);
printf("Bitboards controlled :\n");
bitboard_print2(pos->controlled[WHITE], pos->controlled[BLACK]);
}
/**
* pos_check() - extensive position consistenci check.
* @pos: &position
*/
void pos_check(pos_t *pos)
{
int rank, file;
piece_t piece;
board_t *board = pos->board;
piece_list_t *wk = list_first_entry(&pos->pieces[WHITE], piece_list_t, list),
*bk = list_first_entry(&pos->pieces[BLACK], piece_list_t, list);
/* check that board and bitboard reflect same information */
for (rank = 7; rank >= 0; --rank) {
for (file = 0; file < 8; ++file) {
piece_list_t *ppiece;
printf("checking %c%c ", file+'a', rank+'1');
piece = board[SQ88(file, rank)].piece;
ppiece= board[SQ88(file, rank)].s_piece;
printf("piece=%s ", P_CSYM(piece));
if (ppiece)
printf("ppiece=%s/sq=%#x ", P_CSYM(ppiece->piece), ppiece->square);
switch(PIECE(piece)) {
case PAWN:
printf("pawn" );
break;
case KNIGHT:
printf("knight ");
break;
case BISHOP:
printf("bishop ");
break;
case ROOK:
printf("rook ");
break;
case QUEEN:
printf("queen ");
break;
case KING:
printf("king ");
break;
}
printf("\n");
}
}
}
pos_t *pos_clear(pos_t *pos)
@@ -203,7 +263,7 @@ pos_t *pos_get()
* @pos: &position to duplicate.
*
* New position is the same as source one, with duplicated pieces list
* and empty moves list.
* and empty moves list and NULL bestmove.
*
* @return: The new position.
*
@@ -219,10 +279,10 @@ pos_t *pos_dup(pos_t *pos)
if (new) {
board = new->board;
*new = *pos;
for (int color=0; color<2; ++color) {
for (int color = 0; color < 2; ++color) {
INIT_LIST_HEAD(&new->pieces[color]);
INIT_LIST_HEAD(&new->moves[color]);
new->bestmove = NULL;
/* duplicate piece list */
piece_list = &pos->pieces[color]; /* white/black piece list */

View File

@@ -28,6 +28,7 @@ typedef struct pos_s {
u16 clock_50;
u16 curmove;
eval_t eval;
move_t *bestmove;
board_t board[BOARDSIZE];
square_t en_passant;
@@ -43,6 +44,7 @@ typedef struct pos_s {
void bitboard_print(bitboard_t bb);
void bitboard_print2(bitboard_t bb1, bitboard_t bb2);
void pos_pieces_print(pos_t *pos);
void pos_bitboards_print(pos_t *pos);
void pos_print(pos_t *pos);
pos_t *pos_clear(pos_t *pos);
void pos_del(pos_t *pos);
@@ -52,5 +54,6 @@ pool_t *pos_pool_init();
void pos_pool_stats();
pos_t *pos_get();
pos_t *pos_dup(pos_t *pos);
void pos_check(pos_t *pos);
#endif /* POSITION_H */

View File

@@ -24,28 +24,41 @@
* negamax() - the negamax tree.
*
*/
eval_t negamax(pos_t *pos, int depth)
eval_t negamax(pos_t *pos, int depth, int color)
{
move_t *move, *bestmove;
move_t *move, bestmove;
pos_t *newpos;
eval_t best = EVAL_MIN, score;
printf("depth=%d\n", depth);
moves_gen_all(pos);
if (depth == 0)
return eval(pos) * pos->turn == WHITE? 1: -1;
//pos_check(pos);
if (depth == 0) {
score = eval(pos);
printf("evalnega=%d turn=%d color=%d", score, pos->turn, color);
score *= color;
printf(" --> evalnega=%d\n", score);
return score;
}
moves_print(pos, 0);
list_for_each_entry(move, &pos->moves[pos->turn], list) {
newpos = move_do(pos, move);
score = -negamax(newpos, depth - 1 );
if(score > best) {
score = -negamax(newpos, depth - 1, -color);
move->negamax = score;
printf("move=");
move_print(0, move, 0);
printf("score=%d\n", score);
if (score > best) {
best = score;
bestmove = move;
pos->bestmove = move;
# ifdef DEBUG_SEARCH
log_f(2, "depth=%d best move=", best);
move_print(0, bestmove, M_PR_LONG);
log_f(2, " eval=%d\n", best);
printf("depth=%d best move=", depth);
move_print(0, &bestmove, 0);
printf(" eval=%d\n", best);
# endif
}
move_undo(newpos, move);
}
return best;
}

View File

@@ -20,6 +20,6 @@
#define EVAL_MIN INT_MIN
#define EVAL_MAX INT_MAX
eval_t negamax(pos_t *pos, int depth);
eval_t negamax(pos_t *pos, int depth, int color);
#endif /* SEARCH_H */