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

