dummy eval func (pieces + square control), bit ops, shorter int types

This commit is contained in:
2021-11-09 20:57:18 +01:00
parent e55c2e9cbe
commit 5623dc78a5
11 changed files with 386 additions and 29 deletions

View File

@@ -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 $@

View File

@@ -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
View 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
View 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 */

View File

@@ -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
View 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
View 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 */

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;