Code: Select all
#include <stdio.h>
#define START_POSITION "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
#define ROW(i) (((i) >> 4))
#define COL(i) (((i) & 7 ))
int color[128], piece[128], side, castle, ep, fifty;
int steps[43] = {
17, 15, 0,
-33, 33, -31, 31, -18, 18, -14, 14, 0,
-17, 17, -15, 15, 0,
-16, 16, -1, 1, 0,
-17, 17, -16, 16, -15, 15, -1, 1, 0,
0, 0, 1, 1, 1, 0,// piece + 31 -> slide
0, 3, 12, 17, 22, 22 // piece + 37 -> offset
};
void set_position(char *fen);
void print_position(void);
void movegen(void);
int search(int alpha,int beta,int depth) {
return 0;
}
int main() {
set_position("r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq -");
print_position();
movegen();
printf("\n");
return 0;
}
void set_position(char *fen) {
int row = 7, col = 0, sq = 0;
char sym[26] = ".2........5..1.043........";
for(sq = 0; sq <= 127; sq++) color[sq] = piece[sq] = 16;
side = castle = ep = fifty = -1;
while(!isspace(*fen)) {
sq = row * 16 + col;
if(*fen >= 'A' && *fen <= 'Z') {
color[sq] = 0; piece[sq] = (sym[*fen - 'A'] - '0'); col = col + 1;
} else if(*fen >= 'a' && *fen <= 'z') {
color[sq] = 1; piece[sq] = (sym[*fen - 'a'] - '0'); col = col + 1;
} else if(*fen >= '1' && *fen <= '8') {
col = col + (*fen - '0');
} else if(*fen == '/') {
row = row - 1; col = 0;
}
fen++;
}
do {fen++;} while(isspace(*fen));
switch(tolower(*fen)) { case 'w': side = 0; break; case 'b': side = 1; break; }
do {fen++;} while(isspace(*fen));
castle = 0;
while(*fen != '\0' && !isspace(*fen)) {
if(*fen == 'K') castle |= 1; if(*fen == 'Q') castle |= 2;
if(*fen == 'k') castle |= 4; if(*fen == 'q') castle |= 8;
fen++;
}
while(isspace(*fen)) fen++;
ep = -1; fifty = 0;
if(*fen != '\0' && *fen != '-') ep = (fen[1] - '1') * 16 + (fen[0] - 'a');
}
void print_position(void) {
int row, col, sq;
char piece_char[2][6] = {{'P','N','B','R','Q','K'},{'p','n','b','r','q','k'}};
printf("\nBoard:\n\n");
for(row = 7; row >= 0; row--) {
for(col = 0; col <= 7; col++) {
if(!col) printf("%c ",(row + '1'));
sq = row * 16 + col;
printf("%c%c ",
(color[sq] == 1 ? '-' : ' '),
((color[sq] & 16) ? '.' : piece_char[color[sq]][piece[sq]]));
}
printf("\n");
}
printf(" a b c d e f g h\n\n");
printf(" side : %3c\n",(!(side) ? 'w' : 'b'));
printf(" xside : %3c\n",(!(side ^ 1) ? 'w' : 'b'));
printf(" castle : %3d\n",castle);
printf(" ep : %3d\n",ep);
printf(" fifty : %3d\n",fifty);
}
void movegen(void) {
int sq, from, to, index, step, sign;
for(sq = 0;sq <= 63; sq++) {
from = sq + (sq & ~7);
if(color[from] == side) {
index = steps[37 + piece[from]];
if(!piece[from]) {
while(steps[index]) {
to = from + (((!side) ? 1 : -1) * steps[index]);
if(!(to & 0x88) && color[to] == (side ^ 1)) {
printf("%d %3d %3d cap\n",piece[from],from,to);
}
index++;
}
} else {
while(steps[index]) {
for(to = from + steps[index];!(to & 0x88);to += steps[index]) {
if(color[to] == side) break;
if(color[to] == (side ^ 1)) {
printf("%d %3d %3d cap\n",piece[from],from,to);
break;
}
printf("%d %3d %3d norm\n",piece[from],from,to);
if(!steps[31 + piece[from]]) break;
}
index++;
}
}
}
}
}
1. Is there any way to write minimal movegen()?
2. Is is_attacked () function is required? How castling is possible without is_attacked()?
3. What is the virgin bit in micromax?
I have seen micromax source code but i could understand at all
This is another experimental chess engine dy14g which is perft is working nicely How to implement minimal search with pv line.
Code: Select all
#include <stdio.h>
#include <sys/timeb.h>
#define START_POSITION "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
#define NAME "dy14g"
#define VERSION "0.2.0"
#define AUTHOR "Md Shahil Ahmed"
#define S(x,y) ((((x) * 8) + (y)))
#define R(x) (((x) / 8))
#define C(x) (((x) % 8))
#define M(x) ((x) + ((x) & ~7))
#define U(x) (((x) + ((x) & 7)) >> 1)
#define FROM(x) (((x) >> 6) & 63)
#define TO(x) ((x) & 63)
#define P(x) (((x) >> 12) & 7)
#define CAP(x) (((x) >> 15) & 7)
#define PROM(x) (((x) >> 18) & 7)
int color[64], piece[64], king[2], side, castle, ep, fifty;
char piece_char[2][6] = {{'P','N','B','R','Q','K'},{'p','n','b','r','q','k'}};
typedef struct {
int move;
int castle;
int ep;
int fifty;
} type_hist;
int dirs[34] = {
17, 15, 0, // 0 1 2
-17, -15, 0, // 3 4 5
33, 31, 14, -18, -33, -31, -14, 18, 0, // 6 7 8 9 10 11 12 13 14
17, 15, -17, -15, 0, // 15 16 17 18 19
16, -1, -16, 1, 0, // 20 21 22 23 24
17, 15, -17, -15, 16, -1, -16, 1, 0 // 25 26 27 28 29 30 31 32 33
};
int slide[6] = { 0, 0, 1, 1, 1, 0};
int idx_pawn[2] = { 0, 3};
int idx_piece[6] = { -1, 6, 15, 20, 25, 25};
int pawn_push[2] = { 8,-8};
int pawn_row_ep[2] = { 3, 4};
int pawn_row_promo[2] = { 7, 0};
int ply, hply;
int moves[16381];
int counter[512];
type_hist hist[1024];
int get_ms() {
struct timeb timebuffer;
ftime(&timebuffer);
return (timebuffer.time * 1000) + timebuffer.millitm;
}
char *sqstr(int sq) {
static char str_sq[2];
sprintf(str_sq,"xx");
if(!(M(sq) & 0x88)) sprintf(str_sq,"%c%c",(char)(C(sq) + 'a'),(char)(R(sq) + '1'));
str_sq[2] = 0;
return str_sq;
}
int strsq(char *str_sq) {
int sq = -1;
if(str_sq[0] >= 'a' && str_sq[0] <= 'h' && str_sq[1] >= '1' && str_sq[1] <= '8')
sq = S((int)(str_sq[1] - '1'),(int)((str_sq[0] - 'a')));
return sq;
}
char *movestr(int move) {
static char str_move[5];
int prom = PROM(move);
if(prom >= 1 && prom <= 4) {
sprintf(str_move,"%c%c%c%c%c",
C(FROM(move)) + 'a',R(FROM(move)) + '1',
C(TO(move)) + 'a',R(TO(move)) + '1',piece_char[1][prom]);
str_move[5] = 0;
} else {
sprintf(str_move,"%c%c%c%c",
C(FROM(move)) + 'a',R(FROM(move)) + '1',
C(TO(move)) + 'a',R(TO(move)) + '1');
str_move[4] = 0;
}
return str_move;
}
void set_position(char *fen) {
int r = 7, c = 0, sq = 0;
// "abcdefghijklmnopqrstuvwxyz"
char sym[26] = ".2........5..1.043........";
for(sq = 0; sq < 128; sq++) color[sq] = piece[sq] = 6;
king[0] = king[1] = side = castle = ep = fifty = -1;
memset(counter,0,sizeof(counter));
ply = hply = counter[0] = 0;
while(!isspace(*fen)) {
sq = ((r * 8) + c);
if(*fen >= 'A' && *fen <= 'Z') {
color[sq] = 0; piece[sq] = (sym[*fen - 'A'] - '0');
if(*fen == 'K') king[0] = sq;
c = c + 1;
} else if(*fen >= 'a' && *fen <= 'z') {
color[sq] = 1; piece[sq] = (sym[*fen - 'a'] - '0');
if(*fen == 'k') king[1] = sq;
c = c + 1;
} else if(*fen >= '1' && *fen <= '8') {
c = c + (*fen - '0');
} else if(*fen == '/') {
r = r - 1; c = 0;
}
fen++;
}
do { fen++; } while(isspace(*fen));
switch(tolower(*fen)) {
case 'w': side = 0; break;
case 'b': side = 1; break;
}
do { fen++; } while(isspace(*fen));
castle = 0;
while(*fen != '\0' && !isspace(*fen)) {
switch(*fen) {
case 'K': castle |= 1; break; case 'Q': castle |= 2; break;
case 'k': castle |= 4; break; case 'q': castle |= 8; break;
}
fen++;
}
while(isspace(*fen)) { fen++; }
ep = -1; fifty = 0;
if(*fen != '\0' && *fen != '-') ep = strsq(fen);
}
int isattacked(int sq,int s) {
int p, idx, to;
for(p = 0; p <= 5; p++) {
idx = idx_piece[p];
if(!p) idx = idx_pawn[(s ^ 1)];
while(dirs[idx]) {
to = sq;
while(1) {
to = M(to) + dirs[idx]; if(to & 0x88) break; to = U(to);
if(color[to] != 6) {
if(color[to] == s && piece[to] == p) return 1;
break;
}
if(!slide[p]) break;
}
idx = idx + 1;
}
}
return 0;
}
int incheck(int s) {
return isattacked(king[s],(s ^ 1));
}
void movegen() {
int c, p, idx, from, to, tmp, move;
counter[ply + 1] = counter[ply];
for(from = 0; from <= 63; from++) {
c = color[from], p = piece[from];
if(c == side) {
if(!p) {
for(idx = 0; idx <= 1; idx++) {
to = M(from) + dirs[idx_pawn[side] + idx];
if(!(to & 0x88)) {
to = U(to);
if(color[to] == (side ^ 1)) {
if(pawn_row_promo[side] == R(to)) {
move = ((4 << 18) | (piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
move = ((3 << 18) | (piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
move = ((2 << 18) | (piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
move = ((1 << 18) | (piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
} else {
move= ((piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
}
}
if(color[to] == 6 && ep != -1 && pawn_row_ep[(side ^ 1)] == R(from)) {
if(ep == to && color[to] == color[to + pawn_push[side]]) {
move= ((1 << 22) | (piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
}
}
}
}
to = from + pawn_push[side];
if(color[to] == 6) {
if(pawn_row_promo[side] == R(to)) {
move = ((4 << 18) | (piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
move = ((3 << 18) | (piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
move = ((2 << 18) | (piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
move = ((1 << 18) | (piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
} else {
move = ((piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
}
to = from + 2 * pawn_push[side];
if(pawn_row_ep[side] == R(to) && color[to] == 6) {
move = ((1 << 21) | (piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
}
}
} else {
idx = idx_piece[p];
while(dirs[idx]) {
to = from;
while(1) {
to = M(to) + dirs[idx];
if(to & 0x88) break; to = U(to);
if(color[to] == side) break;
if(color[to] == (side ^ 1)) {
move = ((piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
break;
}
move= ((piece[to] << 15) | (piece[from] << 12)| (from << 6) | to);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
if(!slide[p]) break;
}
idx = idx + 1;
}
}
}
}
if(!incheck(side)) {
if(side) {
if(castle & 4) {
if(color[61] == 6 && color[62] == 6) {
if(!isattacked(61,(side ^ 1)) && !isattacked(62,(side ^ 1))) {
move = ((1 << 23) | (piece[62] << 15) | (piece[60] << 12)| (60 << 6) | 62);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
}
}
}
if(castle & 8) {
if(color[59] == 6 && color[58] == 6 && color[57] == 6) {
if(!isattacked(59,(side ^ 1)) && !isattacked(58,(side ^ 1))) {
move = ((1 << 23) | (piece[58] << 15) | (piece[60] << 12)| (60 << 6) | 58);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
}
}
}
} else {
if(castle & 1) {
if(color[5] == 6 && color[6] == 6) {
if(!isattacked(5,(side ^ 1)) && !isattacked(6,(side ^ 1))) {
move = ((1 << 23) | (piece[6] << 15) | (piece[4] << 12)| (4 << 6) | 6);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
}
}
}
if(castle & 2) {
if(color[3] == 6 && color[2] == 6 && color[1] == 6) {
if(!isattacked(3,(side ^ 1)) && !isattacked(2,(side ^ 1))) {
move = ((1 << 23) | (piece[2] << 15) | (piece[4] << 12)| (4 << 6) | 2);
moves[counter[ply + 1]] = move; counter[ply + 1] += 1;
}
}
}
}
}
}
void unmake_move() {
if(hply <= 0) return;
ply = ply - 1; hply = hply - 1; side = (side ^ 1);
int move = hist[hply].move;
castle = hist[hply].castle;
ep = hist[hply].ep;
fifty = hist[hply].fifty;
int from = FROM(move), to = TO(move), cap = CAP(move), prom = PROM(move), p = P(move);
color[to] = piece[to] = 6;
if(cap != 6) {
color[to] = (side ^ 1); piece[to] = cap;
}
color[from] = side;
piece[from] = p;
if(move & (1 << 22)) {
color[to - pawn_push[side]] = (side ^ 1); piece[to - pawn_push[side]] = 0;
}
if(p == 5) {
king[side] = from;
if(move & (1 << 23)) {
switch(to) {
case 6: color[5] = piece[5] = 6; color[7] = 0; piece[7] = 3; break;
case 2: color[3] = piece[3] = 6; color[0] = 0; piece[0] = 3; break;
case 62: color[61] = piece[61] = 6; color[63] = 1; piece[63] = 3; break;
case 58: color[59] = piece[59] = 6; color[56] = 1; piece[56] = 3; break;
}
}
}
}
int make_move(int move) {
int from = FROM(move), to = TO(move), cap = CAP(move), prom = PROM(move), p = P(move);
hist[hply].move = move;
hist[hply].castle = castle;
hist[hply].ep = ep;
hist[hply].fifty = fifty;
switch (from)
{
case 7: castle &= (~1); break;
case 4: castle &= (~(1|2)); break;
case 0: castle &= (~2); break;
case 63: castle &= (~4); break;
case 60: castle &= (~(4|8)); break;
case 56: castle &= (~8); break;
}
switch (to)
{
case 7: castle &= (~1); break;
case 4: castle &= (~(1|2)); break;
case 0: castle &= (~2); break;
case 63: castle &= (~4); break;
case 60: castle &= (~(4|8)); break;
case 56: castle &= (~8); break;
}
fifty = fifty + 1;
ep = -1;
if(!p || cap != 6) fifty = 0;
color[to] = side; piece[to] = p;
color[from] = piece[from] = 6;
if(move & (1 << 21)) { ep = to - pawn_push[side]; }
if(move & (1 << 22)) { fifty = 0; color[to - pawn_push[side]] = piece[to - pawn_push[side]] = 6; }
if(prom >= 1 && prom <= 4) { color[to] = side; piece[to] = prom; }
if(p == 5) {
king[side] = to;
if(move & (1 << 23)) {
switch(to) {
case 6: color[7] = piece[7] = 6; color[5] = 0; piece[5] = 3; break;
case 2: color[0] = piece[0] = 6; color[3] = 0; piece[3] = 3; break;
case 62: color[63] = piece[63] = 6; color[61] = 1; piece[61] = 3; break;
case 58: color[56] = piece[56] = 6; color[59] = 1; piece[59] = 3; break;
}
}
}
ply = ply + 1; hply = hply + 1; side = (side ^ 1);
if(incheck(side ^ 1)) {
unmake_move();
return 0;
}
return 1;
}
void print_position(void) {
int r, c, sq;
printf("\nBoard\n\n");
printf(" a b c d e f g h");
printf("\n +----+----+----+----+----+----+----+----+\n");
for(r = 7; r >= 0; r--) {
for(c = 0; c <= 7; c++) {
if(!c) printf("%c",(r + '1'));
sq = S(r,c);
printf(" | %c%c",
(color[sq] == 1 ? '-' : ' '),
(color[sq] == 6 ? ' ' : piece_char[color[sq]][piece[sq]]));
}
printf(" | %c",(r + '1'));
printf("\n +----+----+----+----+----+----+----+----+\n");
}
printf(" a b c d e f g h\n\n");
printf(" king[white] : %3d %s\n",king[0],sqstr(king[0]));
printf(" king[black] : %3d %s\n",king[1],sqstr(king[1]));
printf(" side : %c in_check : %s\n",
(side ? 'b' : 'w'),(incheck(side) ? "True" : "False"));
printf(" xside : %c in_check : %s\n",
((side ^ 1) ? 'b' : 'w'),(incheck(side ^ 1) ? "True" : "False"));
printf(" castle : %3d %c%c%c%c\n",castle,
((castle & 1) ? 'K' : '-'),((castle & 2) ? 'Q' : '-'),
((castle & 4) ? 'k' : '-'),((castle & 8) ? 'q' : '-'));
printf(" ep : %3d %4s\n",ep,sqstr(ep));
printf(" fifty : %3d\n",fifty);
printf(" ply : %3d\n",ply);
printf(" hply : %3d\n",hply);
printf("\n");
}
unsigned long long perft(int depth) {
int i;
unsigned long long nodes = 0;
if(depth == 0) return 1;
movegen();
for(i = counter[ply]; i < counter[ply + 1]; i++) {
if(!make_move(moves[i])) continue;
nodes = nodes + perft(depth-1);
unmake_move();
}
return nodes;
}
void test(void) {
set_position(START_POSITION);
print_position();
//run_perft_test_data(4);
}
int main_loop(void) {
printf("%s %s by %s (Copyright 2021)\n\n",NAME,VERSION,AUTHOR);
test();
return 0;
}
int main(void) {
printf("\n");
main_loop();
printf("\n");
return 0;
}