dummy eval func (pieces + square control), bit ops, shorter int types
This commit is contained in:
16
Makefile
16
Makefile
@@ -22,11 +22,11 @@ CC=gcc
|
||||
|
||||
.SECONDEXPANSION:
|
||||
OBJ=$(addprefix $(OBJDIR)/,$(SRC_S:.c=.o))
|
||||
BIN=fen pool piece move debug
|
||||
BIN=fen pool piece move debug eval bits
|
||||
|
||||
CFLAGS += -std=gnu99
|
||||
|
||||
FLAGS += -O2
|
||||
CFLAGS += -O2
|
||||
CFLAGS += -g
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
@@ -41,8 +41,10 @@ CFLAGS += -DDEBUG # global
|
||||
CFLAGS += -DDEBUG_POOL # memory pools management
|
||||
CFLAGS += -DDEBUG_FEN # FEN decoding
|
||||
CFLAGS += -DDEBUG_MOVE # move generation
|
||||
CFLAGS += -DDEBUG_EVAL # eval functions
|
||||
CFLAGS += -DDEBUG_BITS # bits functions
|
||||
|
||||
#CFLAGS += -DDEBUG_MAINSLEEP # sleep 1 sec within main loop (SIGINTR test)
|
||||
#CFLAGS += -DDEBUG_EVAL # sleep 1 sec within main loop (SIGINTR test)
|
||||
#CFLAGS += -DDEBUG_EVAL2 # eval 2
|
||||
#CFLAGS += -DDEBUG_EVAL3 # eval 3
|
||||
#CFLAGS += -DDEBUG_MEM # malloc
|
||||
@@ -90,7 +92,7 @@ $(BIN): $$(subst $(OBJDIR)/$$@.o,,$(OBJ)) $(SRCDIR)/$$@.c
|
||||
# debug: $$(subst $(OBJDIR)/$$@.o,,$(OBJ)) $(SRCDIR)/$$@.c
|
||||
# $(CC) $(CFLAGS) $^ -o $@
|
||||
|
||||
.PHONY: bits
|
||||
bits: test/bits.c
|
||||
$(CC) $(CFLAGS) -S $^ -o $@.s
|
||||
$(CC) -DFOO $(CFLAGS) $^ -o $@
|
||||
#.PHONY: bits
|
||||
#bits2: src/bits.c
|
||||
# $(CC) $(CFLAGS) -S $^ -o $@.s
|
||||
# $(CC) $(CFLAGS) $^ -o $@
|
||||
|
19
make.deps
19
make.deps
@@ -1,10 +1,13 @@
|
||||
./obj/bits.o:: src/bits.c src/bits.h src/debug.h
|
||||
./obj/debug.o:: src/debug.c src/debug.h
|
||||
./obj/fen.o:: src/fen.c src/debug.h src/chessdefs.h src/position.h src/board.h \
|
||||
src/piece.h src/list.h src/pool.h src/fen.h
|
||||
./obj/move.o:: src/move.c src/chessdefs.h src/piece.h src/board.h src/position.h \
|
||||
src/list.h src/pool.h src/move.h src/debug.h
|
||||
./obj/piece.o:: src/piece.c src/chessdefs.h src/piece.h src/board.h \
|
||||
src/position.h src/list.h src/pool.h src/debug.h
|
||||
./obj/eval.o:: src/eval.c src/eval.h src/position.h src/chessdefs.h src/bits.h \
|
||||
src/debug.h src/board.h src/piece.h src/list.h src/pool.h
|
||||
./obj/fen.o:: src/fen.c src/debug.h src/chessdefs.h src/bits.h src/position.h \
|
||||
src/board.h src/piece.h src/list.h src/pool.h src/fen.h
|
||||
./obj/move.o:: src/move.c src/chessdefs.h src/bits.h src/debug.h src/piece.h \
|
||||
src/board.h src/position.h src/list.h src/pool.h src/move.h
|
||||
./obj/piece.o:: src/piece.c src/chessdefs.h src/bits.h src/debug.h src/piece.h \
|
||||
src/board.h src/position.h src/list.h src/pool.h
|
||||
./obj/pool.o:: src/pool.c src/list.h src/pool.h src/debug.h
|
||||
./obj/position.o:: src/position.c src/chessdefs.h src/position.h src/board.h \
|
||||
src/piece.h src/list.h src/pool.h src/fen.h
|
||||
./obj/position.o:: src/position.c src/chessdefs.h src/bits.h src/debug.h \
|
||||
src/position.h src/board.h src/piece.h src/list.h src/pool.h src/fen.h
|
||||
|
81
src/bits.c
Normal file
81
src/bits.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/* bits.c - bits.h tests
|
||||
*
|
||||
* Copyright (C) 2021 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.htmlL>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bits.h"
|
||||
|
||||
#ifdef BIN_bits
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static inline int _popcount64(u64 n)
|
||||
{
|
||||
int count = 0;
|
||||
while (n) {
|
||||
count++;
|
||||
n &= (n - 1);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static inline int _ctz64(u64 n)
|
||||
{
|
||||
return _popcount64((n & -n) - 1);
|
||||
}
|
||||
|
||||
static inline int _clz64(u64 n)
|
||||
{
|
||||
u64 r, q;
|
||||
|
||||
r = (n > 0xFFFFFFFF) << 5; n >>= r;
|
||||
q = (n > 0xFFFF) << 4; n >>= q; r |= q;
|
||||
q = (n > 0xFF ) << 3; n >>= q; r |= q;
|
||||
q = (n > 0xF ) << 2; n >>= q; r |= q;
|
||||
q = (n > 0x3 ) << 1; n >>= q; r |= q;
|
||||
r |= (n >> 1);
|
||||
return __WORDSIZE - r - 1;
|
||||
}
|
||||
|
||||
static inline int _ffs64(u64 n)
|
||||
{
|
||||
if (n == 0)
|
||||
return (0);
|
||||
|
||||
return _popcount64(n ^ ~-n);
|
||||
}
|
||||
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
u64 u = 123, _tmp;
|
||||
int curbit;
|
||||
int base = 10;
|
||||
debug_init(0);
|
||||
if (ac > 2)
|
||||
base = atoi(*(av+2));
|
||||
if (ac > 1) {
|
||||
u = strtoul(*(av+1), NULL, base);
|
||||
printf("base=%d input=%#lx\n", base, u);
|
||||
printf("popcount64(%lu) = %d/%d\n", u, popcount64(u), _popcount64(u));
|
||||
printf("ctz64(%lu) = %d/%d\n", u, ctz64(u), _ctz64(u));
|
||||
printf("clz64(%lu) = %d/%d\n", u, clz64(u), _clz64(u));
|
||||
printf("ffs64(%lu) = %d/%d\n", u, ffs64(u), _ffs64(u));
|
||||
printf("\n");
|
||||
|
||||
bit_for_each64(curbit, _tmp, u) {
|
||||
printf("loop: curbit=%d\n", curbit);
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* BIN_bits */
|
165
src/bits.h
Normal file
165
src/bits.h
Normal file
@@ -0,0 +1,165 @@
|
||||
/* bits.h - bits functions.
|
||||
*
|
||||
* Copyright (C) 2021 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.htmlL>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||
*
|
||||
*/
|
||||
#ifndef BITS_H
|
||||
#define BITS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* next include will define __WORDSIZE: 32 or 64
|
||||
*/
|
||||
#include <bits/wordsize.h>
|
||||
#include "debug.h"
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
/* no plan to support 32bits for now...
|
||||
*/
|
||||
#if __WORDSIZE != 64
|
||||
ERROR_64_BYTES_WORDSIZE_ONLY
|
||||
#endif
|
||||
|
||||
typedef uint64_t u64;
|
||||
typedef uint32_t u32;
|
||||
typedef uint16_t u16;
|
||||
typedef uint8_t u8;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
/* count trailing zeroes : 00101000 -> 3
|
||||
* ^^^
|
||||
*/
|
||||
static inline int ctz64(u64 n)
|
||||
{
|
||||
# if __has_builtin(__builtin_ctzl)
|
||||
# ifdef DEBUG_BITS
|
||||
log_f(1, "builtin ctzl.\n");
|
||||
# endif
|
||||
return __builtin_ctzl(n);
|
||||
|
||||
# elif __has_builtin(__builtin_clzl)
|
||||
# ifdef DEBUG_BITS
|
||||
log_f(1, "builtin clzl.\n");
|
||||
# endif
|
||||
return __WORDSIZE - (__builtin_clzl(n & -n) + 1);
|
||||
|
||||
# else
|
||||
# ifdef DEBUG_BITS
|
||||
log_f(1, "emulated.\n");
|
||||
# endif
|
||||
return popcount64((n & −n) − 1);
|
||||
# endif
|
||||
}
|
||||
|
||||
/* count leading zeroes : 00101000 -> 2
|
||||
* ^^
|
||||
*/
|
||||
static inline int clz64(u64 n)
|
||||
{
|
||||
# if __has_builtin(__builtin_clzl)
|
||||
# ifdef DEBUG_BITS
|
||||
log_f(1, "builtin.\n");
|
||||
# endif
|
||||
return __builtin_clzl(n);
|
||||
|
||||
# else
|
||||
# ifdef DEBUG_BITS
|
||||
log_f(1, "emulated.\n");
|
||||
# endif
|
||||
u64 r, q;
|
||||
|
||||
r = (n > 0xFFFFFFFF) << 5; n >>= r;
|
||||
q = (n > 0xFFFF) << 4; n >>= q; r |= q;
|
||||
q = (n > 0xFF ) << 3; n >>= q; r |= q;
|
||||
q = (n > 0xF ) << 2; n >>= q; r |= q;
|
||||
q = (n > 0x3 ) << 1; n >>= q; r |= q;
|
||||
r |= (n >> 1);
|
||||
return __WORDSIZE - r - 1;
|
||||
# endif
|
||||
}
|
||||
|
||||
/* find first set : 00101000 -> 4
|
||||
* ^
|
||||
*/
|
||||
static inline uint ffs64(u64 n)
|
||||
{
|
||||
# if __has_builtin(__builtin_ffsl)
|
||||
# ifdef DEBUG_BITS
|
||||
log_f(1, "builtin ffsl.\n");
|
||||
# endif
|
||||
return __builtin_ffsll(n);
|
||||
|
||||
# elif __has_builtin(__builtin_ctzl)
|
||||
# ifdef DEBUG_BITS
|
||||
log_f(1, "builtin ctzl.\n");
|
||||
# endif
|
||||
if (n == 0)
|
||||
return (0);
|
||||
return __builtin_ctzl(n) + 1;
|
||||
|
||||
# else
|
||||
# ifdef DEBUG_BITS
|
||||
log_f(1, "emulated.\n");
|
||||
# endif
|
||||
return popcount64(n ^ ~-n);
|
||||
# endif
|
||||
}
|
||||
|
||||
static inline int popcount64(u64 n)
|
||||
{
|
||||
# if __has_builtin(__builtin_popcountl)
|
||||
# ifdef DEBUG_BITS
|
||||
log_f(1, "builtin.\n");
|
||||
# endif
|
||||
return __builtin_popcountl(n);
|
||||
|
||||
# else
|
||||
# ifdef DEBUG_BITS
|
||||
log_f(1, "emulated.\n");
|
||||
# endif
|
||||
int count = 0;
|
||||
while (n) {
|
||||
count++;
|
||||
n &= (n - 1);
|
||||
}
|
||||
return count;
|
||||
# endif
|
||||
}
|
||||
|
||||
/** bit_for_each64 - iterate over an u64 bits
|
||||
* @pos: an int used as current bit
|
||||
* @tmp: a temp u64 used as temporary storage
|
||||
* @ul: the u64 to loop over
|
||||
*
|
||||
* Usage:
|
||||
* u64 u=139, _t; // u=b10001011
|
||||
* int cur;
|
||||
* bit_for_each64(cur, _t, u) {
|
||||
* printf("%d\n", cur);
|
||||
* }
|
||||
* This will display the position of each bit in u: 1, 2, 4, 8
|
||||
*
|
||||
* I should probably re-think the implementation...
|
||||
*/
|
||||
#define bit_for_each64(pos, tmp, ul) \
|
||||
for (tmp = ul, pos = ffs64(tmp); pos; tmp &= (tmp - 1), pos = ffs64(tmp))
|
||||
|
||||
/*
|
||||
U64 ls1b = x & -x; // isolate LS1B
|
||||
...
|
||||
x &= x-1; // reset LS1B
|
||||
}
|
||||
*/
|
||||
|
||||
#endif /* BITS_H */
|
@@ -14,11 +14,11 @@
|
||||
#ifndef CHESSDEFS_H
|
||||
#define CHESSDEFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bits.h"
|
||||
|
||||
/* piece_t bits structure
|
||||
*/
|
||||
typedef unsigned char piece_t;
|
||||
typedef u8 piece_t;
|
||||
|
||||
#define EMPTY 0
|
||||
|
||||
|
85
src/eval.c
Normal file
85
src/eval.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/* eval.c - static position evaluation.
|
||||
*
|
||||
* Copyright (C) 2021 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.htmlL>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "eval.h"
|
||||
#include "list.h"
|
||||
#include "debug.h"
|
||||
|
||||
eval_t eval(pos_t *pos)
|
||||
{
|
||||
eval_t eval[2] = {0}, res = 0;
|
||||
struct list_head *p_cur, *p_tmp, *list;
|
||||
piece_list_t *piece;
|
||||
|
||||
/* 1) pieces value
|
||||
*/
|
||||
for (int color=WHITE; color <=BLACK; ++color) {
|
||||
list = &pos->pieces[color];
|
||||
list_for_each_safe(p_cur, p_tmp, list) {
|
||||
piece = list_entry(p_cur, piece_list_t, list);
|
||||
eval[color] += piece->value;
|
||||
}
|
||||
}
|
||||
|
||||
res += eval[WHITE] - eval[BLACK];
|
||||
# ifdef DEBUG_EVAL
|
||||
log_f(2, "pieces: W:%lu B:%lu diff=%lu eval=\n", eval[WHITE], eval[BLACK],
|
||||
res);
|
||||
# endif
|
||||
|
||||
/* 2) square control
|
||||
*/
|
||||
eval[WHITE] = popcount64(pos->controlled[WHITE]);
|
||||
eval[BLACK] = popcount64(pos->controlled[BLACK]);
|
||||
res += eval[WHITE] - eval[BLACK];
|
||||
# ifdef DEBUG_EVAL
|
||||
log_f(2, "square control: W:%lu B:%lu eval=%lu\n", eval[WHITE], eval[BLACK],
|
||||
res);
|
||||
# endif
|
||||
|
||||
/* 3) mobility
|
||||
*/
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef BIN_eval
|
||||
#include "fen.h"
|
||||
#include "move.h"
|
||||
|
||||
int main(int ac, char**av)
|
||||
{
|
||||
pos_t *pos;
|
||||
|
||||
debug_init(2);
|
||||
piece_pool_init();
|
||||
moves_pool_init();
|
||||
pos = pos_create();
|
||||
|
||||
if (ac == 1) {
|
||||
pos_startpos(pos);
|
||||
} else {
|
||||
fen2pos(pos, av[1]);
|
||||
}
|
||||
|
||||
moves_gen(pos, WHITE);
|
||||
moves_gen(pos, BLACK);
|
||||
pos_print(pos);
|
||||
pos_pieces_print(pos);
|
||||
|
||||
printf("eval=%lu\n", eval(pos));
|
||||
}
|
||||
#endif
|
21
src/eval.h
Normal file
21
src/eval.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* eval.h - static position evaluation.
|
||||
*
|
||||
* Copyright (C) 2021 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.htmlL>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EVAL_H
|
||||
#define EVAL_H
|
||||
|
||||
#include "position.h"
|
||||
|
||||
eval_t eval(pos_t *pos);
|
||||
|
||||
#endif /* EVAL_H */
|
16
src/move.c
16
src/move.c
@@ -120,7 +120,7 @@ static move_t *move_add(pos_t *pos, piece_t piece, square_t from,
|
||||
move_t *move;
|
||||
|
||||
# ifdef DEBUG_MOVE
|
||||
log_i(2, "piece_color=%d turn=%d from=%c%c to=%c%c\n",
|
||||
log_i(3, "piece_color=%d turn=%d from=%c%c to=%c%c\n",
|
||||
COLOR(piece), pos->turn,
|
||||
FILE2C(GET_F(from)),
|
||||
RANK2C(GET_R(from)),
|
||||
@@ -141,7 +141,7 @@ static move_t *move_add(pos_t *pos, piece_t piece, square_t from,
|
||||
move->flags |= M_CAPTURE;
|
||||
list_add(&move->list, &pos->moves);
|
||||
# ifdef DEBUG_MOVE
|
||||
log_i(2, "added move from %c%c to %c%c\n",
|
||||
log_i(3, "added move from %c%c to %c%c\n",
|
||||
FILE2C(GET_F(move->from)),
|
||||
RANK2C(GET_R(move->from)),
|
||||
FILE2C(GET_F(move->to)),
|
||||
@@ -247,7 +247,7 @@ int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece)
|
||||
int two=0;
|
||||
for (new = square + dir * 15; two < 2; new = square + dir * 17, two++) {
|
||||
# ifdef DEBUG_MOVE
|
||||
log_i(3, "pawn capture %#04x %#04x\n", square, new);
|
||||
log_i(4, "pawn capture %#04x %#04x\n", square, new);
|
||||
# endif
|
||||
if (SQ88_NOK(new))
|
||||
continue;
|
||||
@@ -319,14 +319,14 @@ int pseudo_moves_gen(pos_t *pos, piece_list_t *ppiece)
|
||||
int count = 0;
|
||||
|
||||
# ifdef DEBUG_MOVE
|
||||
log_f(2, "pos:%p turn:%s piece:%d [%s %s] at %#04x[%c%c]\n",
|
||||
log_f(4, "pos:%p turn:%s piece:%d [%s %s] at %#04x[%c%c]\n",
|
||||
pos,
|
||||
pos->turn ==WHITE? "white": "black",
|
||||
piece,
|
||||
color==WHITE? "white": "black", P_NAME(piece),
|
||||
square,
|
||||
FILE2C(GET_F(square)), RANK2C(GET_R(square)));
|
||||
log_i(4, "vector=%ld ndirs=%d slide=%d\n", vector-vectors, ndirs, slide);
|
||||
log_i(5, "vector=%ld ndirs=%d slide=%d\n", vector-vectors, ndirs, slide);
|
||||
# endif
|
||||
|
||||
for (int curdir = 0; curdir < ndirs; ++curdir) {
|
||||
@@ -340,18 +340,18 @@ int pseudo_moves_gen(pos_t *pos, piece_list_t *ppiece)
|
||||
break;
|
||||
}
|
||||
# ifdef DEBUG_MOVE
|
||||
log_i(3, "trying %c%c\n", FILE2C(GET_F(new)), RANK2C(GET_R(new)));
|
||||
log_i(4, "trying %c%c\n", FILE2C(GET_F(new)), RANK2C(GET_R(new)));
|
||||
# endif
|
||||
|
||||
pos->controlled[color] |= (1ULL << BB(FILE88(new), RANK88(new)));
|
||||
if (board[new].piece) {
|
||||
# ifdef DEBUG_MOVE
|
||||
log_i(4, "color=%d color2=%d\n", color, COLOR(board[new].piece));
|
||||
log_i(5, "color=%d color2=%d\n", color, COLOR(board[new].piece));
|
||||
# endif
|
||||
/* own color on dest square */
|
||||
if (COLOR(board[new].piece) == color) {
|
||||
# ifdef DEBUG_MOVE
|
||||
log_i(3, "skipping %04x (same color piece)\n", new);
|
||||
log_i(5, "skipping %04x (same color piece)\n", new);
|
||||
# endif
|
||||
break;
|
||||
}
|
||||
|
@@ -74,7 +74,7 @@ piece_list_t *piece_add(pos_t *pos, piece_t piece, square_t square)
|
||||
# endif
|
||||
if ((new = pool_get(pieces_pool))) {
|
||||
list_add_tail(&new->list, &pos->pieces[color]);
|
||||
//color? &pos->pieces_black: &pos->pieces_white);
|
||||
//color? &pos->pieces_black: &pos->pieces_white);
|
||||
new->piece = piece;
|
||||
new->square = square;
|
||||
new->castle = 0;
|
||||
|
@@ -94,7 +94,7 @@ void *pool_get(pool_t *pool)
|
||||
void *cur;
|
||||
uint32_t i;
|
||||
# ifdef DEBUG_POOL
|
||||
log_f(2, "[%s]: growing pool from %u to %u elements.\n",
|
||||
log_f(1, "[%s]: growing pool from %u to %u elements.\n",
|
||||
pool->name,
|
||||
pool->allocated,
|
||||
pool->allocated + pool->growsize);
|
||||
|
@@ -22,8 +22,8 @@
|
||||
typedef struct pos_s {
|
||||
piece_t turn; /* we use only color bit */
|
||||
castle_t castle;
|
||||
short clock_50;
|
||||
short curmove;
|
||||
uint16_t clock_50;
|
||||
uint16_t curmove;
|
||||
eval_t eval;
|
||||
board_t *board;
|
||||
|
||||
|
Reference in New Issue
Block a user