//check void check(){ int t1=0,t2=0,i,j,x1,y1,z1=0,z2=0; checkm arr[30]; for(i=0;i<=7;i++){ for(j=0;j<=7;j++){ if(board[i][j]==-5){ y1=i; x1=j; break; } } } for(j=0;j<=7;j++){ for(i=0;i<=7;i++){ if (t1==1){ } if(board[j][i]>=9 && board[j][i]<=16){ flipturn(); t1 = pawn(j,i,y1,x1);flipturn(); //add position of pawn to a list if(t1==1){ arr[z1].y=j;arr[z1].x=i;arr[z1].piece=board[j][i];z1++; } } else if(board[j][i]==2 || board[j][i]==7){ t1 = horse(j,i,y1,x1); if(t1==1){ arr[z1].y=j;arr[z1].x=i;arr[z1].piece=board[j][i];z1++; } } else if(board[j][i]==4){ t1 = queen(j,i,y1,x1); if(t1==1){ arr[z1].y=j;arr[z1].x=i;arr[z1].piece=board[j][i];z1++; } } else if(board[j][i]==1 || board[j][i]==8){ t1 = rook(j,i,y1,x1); if(t1==1){ arr[z1].y=j;arr[z1].x=i;arr[z1].piece=board[j][i];z1++; } } else if(board[j][i]==3 || board[j][i]==6){ t1 = bishop(j,i,y1,x1); if(t1==1){ arr[z1].y=j;arr[z1].x=i;arr[z1].piece=board[j][i];z1++; } } } } if(z1!=0){ mvwprintw(chessboard,1,25,"Player 1 in CHECK");wrefresh(chessboard); if(turn!=0) checkmate(y1,x1,&arr,z1); else{ mvwprintw(chessboard,2,30," ");wrefresh(chessboard); } } z2=0; for(i=0;i<=7;i++){ for(j=0;j<=7;j++){ if(board[i][j]==5){ y1=i; x1=j; break; } } } for(j=0;j<=7;j++){ for(i=0;i<=7;i++){ if (t2==1){ } if(board[j][i]>=(-9) && board[j][i]<=(-16)){ flipturn(); t2 = pawn(j,i,y1,x1);flipturn(); if(t2==1){ arr[z2].y=j;arr[z2].x=i;arr[z2].piece=board[j][i];z2++; } } else if(board[j][i]==(-2) || board[j][i]==(-7)){ t2= horse(j,i,y1,x1); if(t2==1){ arr[z2].y=j;arr[z2].x=i;arr[z2].piece=board[j][i];z2++; } } else if(board[j][i]==(-4)){ t2 = queen(j,i,y1,x1); if(t2==1){ arr[z2].y=j;arr[z2].x=i;arr[z2].piece=board[j][i];z2++; } } else if(board[j][i]==(-1) || board[j][i]==(-8)){ t2 = rook(j,i,y1,x1); if(t2==1){ arr[z2].y=j;arr[z2].x=i;arr[z2].piece=board[j][i];z2++; } } else if(board[j][i]==(-3) || board[j][i]==(-6)){ t2 = bishop(j,i,y1,x1); if(t2==1){ arr[z2].y=j;arr[z2].x=i;arr[z2].piece=board[j][i];z2++; } } } } wrefresh(chessboard); if(z2!=0){ mvwprintw(chessboard,1,25,"Player 2 in CHECK");wrefresh(chessboard); if(turn==0) checkmate(y1,x1,&arr,z2); else{ mvwprintw(chessboard,2,30," ");wrefresh(chessboard); } } if(z1==0&&z2==0) mvwprintw(chessboard,2,25," ");wrefresh(chessboard); }
int friendlymove(int row,int col){ int t2,t1,j,i; if(turn!=0){ for(j=0;j<=7;j++){ for(i=0;i<=7;i++){ if (t2==1){ break; } if(board[j][i]>=(-9) && board[j][i]<=(-16)){ flipturn(); t2 = pawn(j,i,row,col); flipturn(); } else if(board[j][i]==(-2) || board[j][i]==(-7)){ t2= horse(j,i,row,col); } else if(board[j][i]==(-4)){ t2 = queen(j,i,row,col); } else if(board[j][i]==(-1) || board[j][i]==(-8)) t2 = rook(j,i,row,col); else if(board[j][i]==(-3) || board[j][i]==(-6)){ t2 = bishop(j,i,row,col); } } } if(t2==1) return 1; else return 0; } if(turn==0){ for(j=0;j<=7;j++){ for(i=0;i<=7;i++){ if (t2==1){ break; } if(board[j][i]>=(9) && board[j][i]<=(16)){ flipturn(); t2 = pawn(j,i,row,col); flipturn(); } else if(board[j][i]==(2) || board[j][i]==(7)) t2= horse(j,i,row,col); else if(board[j][i]==(4)){ t2 = queen(j,i,row,col); } else if(board[j][i]==(1) || board[j][i]==(8)) t2 = rook(j,i,row,col); else if(board[j][i]==(3) || board[j][i]==(6)){ t2 = bishop(j,i,row,col); } } } if(t2==1) return 1; else return 0; } }
bool whiteCheck() { int x, y; for (x = 0; x < 8; x++) { for (y = 0; y < 8; y++) if (table[x][y] == 'K') break; if (table[x][y] == 'K') break; } int i, j; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) if (table[i][j] == 'p' && blackPawn(i, j, x, y)) return true; else if (table[i][j] == 'n' && knight(i, j, x, y)) return true; else if (table[i][j] == 'b' && bishop(i, j, x, y)) return true; else if (table[i][j] == 'r' && rook(i, j, x, y)) return true; else if (table[i][j] == 'q' && queen(i, j, x, y)) return true; else if (table[i][j] == 'k' && king(i, j, x, y)) return true; return false; }
bool blackCheck() { int x, y; for (x = 0; x < 8; x++) { for (y = 0; y < 8; y++) if (table[x][y] == 'k') break; if (table[x][y] == 'k') break; } int i, j; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) if (table[i][j] == 'P' && whitePawn(i, j, x, y)) return true; else if (table[i][j] == 'N' && knight(i, j, x, y)) return true; else if (table[i][j] == 'B' && bishop(i, j, x, y)) return true; else if (table[i][j] == 'R' && rook(i, j, x, y)) return true; else if (table[i][j] == 'Q' && queen(i, j, x, y)) return true; else if (table[i][j] == 'K' && king(i, j, x, y)) return true; return false; }
// Parses Donna chess format string for one side. Besides [K]ing, [Q]ueen, [R]ook, // [B]ishop, and k[N]ight the following pseudo pieces could be specified: // // [M]ove: specifies the right to move along with the optional move number. // For example, "M42" for Black means the Black is making 42nd move. // Default value is "M1" for White. // // [C]astle: specifies castle right squares. For example, "Cg1" and "Cc8" encode // allowed kingside castle for White, and queenside castle for Black. // By default all castles are allowed, i.e. defult value is "Cc1,Cg1" // for White and "Cc8,Cg8" for Black. The actual castle rights are // checked during position setup to make sure they do not violate // chess rules. If castle rights are specified incorrectly they get // quietly ignored. // // [E]npassant: specifies en-passant square if any. For example, "Ed3" marks D3 // square as en-passant. Default value is no en-passant. // //------------------------------------------------------------------------------ Position *setup_side(Position *self, char *side, uint8 color) { char *buffer = (char *)calloc(strlen(side) + 1, 1); // strdup() the string so we could tokenize it. strcat(buffer, side); char *move = strtok(buffer, ","); while(move) { if (move[0] == 'M') { // TODO: parse move number. self->color = color; } else { int sq, size = strlen(move); assert(size == 2 || size == 3); // Don't panic. if (size == 2) { // Pawn, ex. "e4". sq = square(move[1] - '1', move[0] - 'a'); } else { // Piece, ex. "Qd1". sq = square(move[2] - '1', move[1] - 'a'); } switch(move[0]) { case 'K': self->pieces[sq] = king(color); break; case 'Q': self->pieces[sq] = queen(color); break; case 'R': self->pieces[sq] = rook(color); break; case 'B': self->pieces[sq] = bishop(color); break; case 'N': self->pieces[sq] = knight(color); break; case 'E': self->enpassant = (uint8)sq; break; case 'C': if (sq == C1 + (int)color || sq == C8 + (int)color) { self->castles |= castleQueenside[color]; } else if (sq == G1 + (int)color || sq == G8 + (int)color) { self->castles |= castleKingside[color]; } break; default: // When everything else fails, read the instructions. self->pieces[sq] = pawn(color); } } move = strtok(NULL, ","); // <-- Get next move token. } free(buffer); return self; }
void coins() // draw coins { for(int i=0;i<8;i++) for(int j=0;j<8;j++) { if(A[i][j].coin=='R') rook(A[i][j].x,A[i][j].y,A[i][j].color); if(A[i][j].coin=='H') knight(A[i][j].x,A[i][j].y,A[i][j].color); if(A[i][j].coin=='B') bishop(A[i][j].x,A[i][j].y,A[i][j].color); if(A[i][j].coin=='K') king(A[i][j].x,A[i][j].y,A[i][j].color); if(A[i][j].coin=='Q') queen(A[i][j].x,A[i][j].y,A[i][j].color); if(A[i][j].coin=='P') pawn(A[i][j].x,A[i][j].y,A[i][j].color); }}
//------------------------------------------------------------------------------ Score threats(uint8 color, Bitmask hisAttacks, Bitmask herAttacks) { Score score = {}; Position *p = eval.position; // Find weak enemy pieces: the ones under attack and not defended by // pawns (excluding a king). Bitmask weak = p->outposts[color^1] & hisAttacks & ~eval.attacks[pawn(color^1)]; weak &= ~p->outposts[king(color^1)]; if (weak) { // Threat bonus for strongest enemy piece attacked by our pawns, // knights, or bishops. Bitmask targets = weak & (eval.attacks[pawn(color)] | eval.attacks[knight(color)] | eval.attacks[bishop(color)]); if (targets) { Piece piece = strongest_piece(p, color^1, targets); score = add(score, bonusMinorThreat[kind(piece) / 2]); } // Threat bonus for strongest enemy piece attacked by our rooks // or queen. targets = weak & (eval.attacks[rook(color)] | eval.attacks[queen(color)]); if (targets) { Piece piece = strongest_piece(p, color^1, targets); score = add(score, bonusMajorThreat[kind(piece) / 2]); } // Extra bonus when attacking enemy pieces that are hanging. Side // having the right to move gets bigger bonus. int hanging = count(weak & ~herAttacks); if (hanging > 0) { if (p->color == color) { hanging++; } score = add(score, times(hangingAttack, hanging)); } } return score; }
bool queen(int i, int j, int x, int y) { return rook(i, j, x, y) || bishop(i, j, x, y); }
void main() { int gdriver = DETECT, gmode; initgraph(&gdriver, &gmode, "\\tc\\bgi"); cleardevice(); // char str[1]; str[1]='\0'; file.open("Info.TXT",ios::in|ios::binary); if(!file) cout<<"File couldnt be opened"; x=20; y=getmaxy()-70; settextstyle(2,0,5); setvalues(); board(); coins(); getch(); typeon(); getch(); cleardevice(); x=20; y=200; pic("ch pic"); typeon(); y+=20; typeon(); getch(); cleardevice(); pic("ch pic2"); x=20; y=200; typeon(); getch(); cleardevice(); king(getmaxx()/2-30,30,1); x=20; y=100; typeon(); getch(); cleardevice(); rook(getmaxx()/2-30,30,1); x=20; y=100; typeon(); getch(); cleardevice(); bishop(getmaxx()/2-30,30,1); x=20; y=100; typeon(); getch(); cleardevice(); queen(getmaxx()/2-30,30,1); x=20; y=100; typeon(); getch(); cleardevice(); knight(getmaxx()/2-30,30,1); x=20; y=100; typeon(); getch(); cleardevice(); pawn(getmaxx()/2-30,30,1); x=20; y=100; typeon(); getch(); cleardevice(); pic("ch pic3"); x=20; y=50; typeon(); getch(); file.close(); closegraph(); }
/*check where the king can move if the king can move to a place will he be in check? if yes continue to check other conditions else no checkmate*/ int checkmate(int row,int col,checkm arr[],int q) { int ccount,valid,i,j,x,y,z,t=0,possible=0,n=0; y=row-1; x=col-1; while(x<0){ x++; } while(y<0) y++; if(turn!=0){ while((y<=row+1)&&(x<=col+1)){ valid=king(row,col,y,x); if((turn!=0)&&board[y][x]<0 || (x==8 || y==8)){ valid=0; wprintw(menuwin," invalid turn 1");wrefresh(menuwin); } if(valid){ t=0; for(j=0;j<=7;j++){ for(i=0;i<=7;i++){ if(t==1){ break; } if(board[j][i]>=9 && board[j][i]<=16) t = pawn(j,i,y,x); else if(board[j][i]==2 || board[j][i]==7) t = horse(j,i,y,x); else if(board[j][i]==4) t = queen(j,i,y,x); else if(board[j][i]==1 || board[j][i]==8) t = rook(j,i,y,x); else if(board[j][i]==3 || board[j][i]==6) t = bishop(j,i,y,x); } } if(t==1){ ccount++; } else if(t==0){ possible++; } } else{ ccount++; } if(y==row+1){ x++; } if(y<row+1){ y++; } } if(possible!=0){ return; } for(z=0;z<q;z++) { x=arr[z].x;y=arr[z].y; switch(abs(arr[z].piece)) { case 9:case 10:case 11:case 12:case 13:case 14:case 15:case 16:break; case 4:if(arr[z].y-row==arr[z].x-col) goto c3; //go to bishop case if(arr[z].y==row||arr[z].x==col) //go to rook case case 1:case 8://rook if(row==arr[z].y) { for(i=arr[z].x+1;i<col;i++) { if(board[row][i]==0) { if(friendlymove(row,i)){ possible++;goto end;} } } for(i=arr[z].x-1;i>col;i--) { if(board[row][i]==0) { if(friendlymove(row,i)){ possible++;goto end;} } } } else if(col==arr[x].x) { for(i=arr[z].y+1;i<row;i++) { if(board[i][col]==0) { if(friendlymove(i,col)){ possible++;goto end;} } } for(i=arr[z].y-1;i>col;i--) { if(board[i][col]==0) { if(friendlymove(i,col)){ possible++;goto end;} } } } break; //generate mid way blocks and check if friendly piece can move in case 2:case 7://horse c3:case 3:case 6: //bishop if((x<col)&&(y<row)) { for(i=1;(i+x)<col;i++) { if(board[y+i][x+i]==0) { if(friendlymove(y+i,x+i)){ possible++;goto end;} } } } else if((x>col)&&(y>row)){ for(i=1;(x-i)>col;i++){ if(board[y-i][x-i]==0) if(friendlymove(y-i,x-i)){ possible++;goto end;} } } else if((x>col)&&(y<row)){ for(i=1;(x-i)>col;i++){ if(board[y+i][x-i]==0) if(friendlymove(y+i,x-i)){ possible++;goto end;} } } else if((x<col)&&(y>row)){ for(i=1;(y-i)>row;i++){ if(board[y-i][x+i]==0) if(friendlymove(y-i,x+i)){ possible++;goto end;} } } break; } } end:if(possible==0){ mvwprintw(chessboard,2,30," player 1 CHECKMATE");wrefresh(chessboard); } else{ mvwprintw(chessboard,2,30," ");wrefresh(chessboard); } } else if(turn==0){ while((y<=row+1)&&(x<=col+1)){ valid=king(row,col,y,x); if((turn==0)&&board[y][x]>0){ valid=0; } if(valid){ t=0; for(j=0;j<=7;j++){ for(i=0;i<=7;i++){ if(t==1) break; if(board[j][i]>=-9 && board[j][i]<=-16) t = pawn(j,i,y,x); else if(board[j][i]==-2 || board[j][i]==-7) t = horse(j,i,y,x); else if(board[j][i]==-4) t = queen(j,i,y,x); else if(board[j][i]==-1 || board[j][i]==-8) t = rook(j,i,y,x); else if(board[j][i]==-3 || board[j][i]==-6) t = bishop(j,i,y,x); } } if(t==1){ ccount++; } else if(t==0) { possible++; } } else { ccount++; } if(y==row+1){ x++; } if(y<row+1){ y++; } } if(possible!=0) return; for(z=0;z<=q;z++) { x=arr[z].x;y=arr[z].y; switch(arr[z].piece) { case -9:case -10:case -11:case -12:case -13:case -14:case -15:case -16:break; case -4:if(arr[z].y-row==arr[z].x-col) goto c4; //go to bishop case if(arr[z].y==row||arr[z].x==col) //go to rook case case -1:case -8://rook if(row==arr[z].y) { for(i=arr[z].x+1;i<col;i++){ if(board[row][i]==0){ if(friendlymove(row,i)){ possible++;goto end;} } } for(i=arr[z].x-1;i>col;i--) { if(board[row][i]==0) { if(friendlymove(row,i)){ possible++;goto end;} } } } else if(col==arr[x].x) { for(i=arr[z].y+1;i<row;i++) { if(board[i][col]==0) { if(friendlymove(i,col)){ possible++;goto end;} } } for(i=arr[z].y-1;i>col;i--) { if(board[i][col]==0) { if(friendlymove(i,col)){ possible++;goto end;} } } } break; //generate mid way blocks and check if friendly piece can move in case -2:case -7://horse c4:case -3:case -6: //bishop if((x<col)&&(y<row)) { for(i=1;(i+x)<col;i++) { if(board[y+i][x+i]==0) { if(friendlymove(y+i,x+i)){ possible++;goto end2;} } } } else if((x>col)&&(y>row)){ for(i=1;(x-i)>col;i++){ if(board[y-i][x-i]==0) if(friendlymove(y-i,x-i)){ possible++;goto end2;} } } else if((x>col)&&(y<row)){ for(i=1;(x-i)>col;i++){ if(board[y+i][x-i]==0) if(friendlymove(y+i,x-i)){ possible++;goto end2;} } } else if((x<col)&&(y>row)){ for(i=1;(y-i)>row;i++){ if(board[y-i][x+i]==0) if(friendlymove(y-i,x+i)){ possible++;goto end2;} } } break; } } end2:if(possible==0){ mvwprintw(chessboard,2,30," player 2 CHECKMATE");wrefresh(chessboard); } else{ mvwprintw(chessboard,2,30," ");wrefresh(chessboard); } } }
//during the game //when u get the coordinates of the click void game(int x, int y){ MEVENT ev; bpos *m; bool a; m=malloc(sizeof(bpos)); int b,c,fx,fy; if(board[x][y]==0) { wrongstart(); } else { if(turn==0) { if(board[x][y]<0) { wrongstart(); } } else if(turn!=0){ if(board[x][y]>0){ wrongstart(); } } } //then the user should click in the final position and we need to find the corresponding box c = wgetch(chessboard); c = wgetch(chessboard); wrefresh(menuwin); switch(c) { case KEY_MOUSE: if(getmouse(&ev) == OK){ if(ev.bstate & BUTTON1_PRESSED){ fy=ev.y;fx=ev.x; m=position(fx,fy); fy=m->col; fx=m->row; if(!((m->row+1)*(m->col+1))){ mvwprintw(menuwin,10,10,"not valid click again "); wrefresh(menuwin);return; } if((turn==0)&&(board[fx][fy]<0)){ mvwprintw(menuwin,2,6,"choose num 2 "); } else if((turn!=0)&&(board[fx][fy]>0)){ mvwprintw(menuwin,2,6,"choose num1"); } wrefresh(menuwin); switch(abs(board[x][y])) { case 9:case 10:case 11:case 12:case 13:case 14:case 15:case 16: b=pawn(x,y,fx,fy); break; case 2: case 7: b=horse(x,y,fx,fy); break; case 4: b=queen(x,y,fx,fy); break; case 3:case 6:b=bishop(x,y,fx,fy); break; case 1:case 8: b=rook(x,y,fx,fy); break; case 5: b=king(x,y,fx,fy); break; } if(b==1){ if((turn==0)&&board[x][y]<0) {return;} else if((turn!=0)&&board[x][y]>0) {return;} if((turn==0)&&board[fx][fy]>0) {return;} else if((turn!=0)&&board[fx][fy]<0) {return;} if((board[fx][fy]>0)&&(turn!=0)){ karr[count]=board[fx][fy];count++;printelement(); } else if((board[fx][fy]<0)&&(turn==0)){ karr[count]=board[fx][fy];count++;printelement(); } wrefresh(menuwin);move1.prevval=board[fx][fy]; move1.newval=board[x][y]; movepiece(x,y,fx,fy);wrefresh(menuwin); move1.srow=x;move1.scol=y;move1.erow=fx;move1.ecol=fy; push(&s,move1); flipturn();check(); display_menu(); } } } } }
int main(void){ int i, j; int game; char board[BOARD_SIZE][BOARD_SIZE+1]; char white[BOARD_SIZE+2+2][BOARD_SIZE+2+2]; char black[BOARD_SIZE+2+2][BOARD_SIZE+2+2]; char *pboard[BOARD_SIZE]; char *pblack[BOARD_SIZE+4]; char *pwhite[BOARD_SIZE+4]; int bk_row; int bk_col; int wk_row; int wk_col; #ifdef _DEBUG_ FILE *f; f = fopen("in.txt", "r"); #endif for(i=0; i<BOARD_SIZE; i++){ #ifdef _DEBUG_ fscanf(f, "%s", &board[i][0]); #else scanf("%s", &board[i][0]); #endif } for(i=0; i<BOARD_SIZE; i++)pboard[i] = &board[i][0]; for(i=0; i<BOARD_SIZE+4; i++){ pwhite[i] = &white[i][0]; pblack[i] = &black[i][0]; } game = 0; while(boardIsNotEmpty(&board[0][0])){ game++; memset(white, 0, sizeof(white)); memset(black, 0, sizeof(black)); for(i=0; i<BOARD_SIZE; i++){ for(j=0; j<BOARD_SIZE; j++){ if(board[i][j] == 'k'){ bk_row = i; bk_col = j; } if(board[i][j] == 'K'){ wk_row = i; wk_col = j; } } } for(i=0; i<BOARD_SIZE; i++){ for(j=0; j<BOARD_SIZE; j++){ switch(board[i][j]){ case('k'): king(pboard, i, j, pblack, BOARD_SIZE, 'K'); break; case('K'): king(pboard, i, j, pblack, BOARD_SIZE, 'k'); break; case('p'): black[2+i+1][2+j-1]++; black[2+i+1][2+j+1]++; break; case('P'): white[2+i-1][2+j-1]++; white[2+i-1][2+j+1]++; break; case('r'): rook(pboard, i, j, pblack, BOARD_SIZE, 'K'); break; case('R'): rook(pboard, i, j, pwhite, BOARD_SIZE, 'k'); break; case('b'): bishop(pboard, i, j, pblack, BOARD_SIZE, 'K'); break; case('B'): bishop(pboard, i, j, pwhite, BOARD_SIZE, 'k'); break; case('q'): rook(pboard, i, j, pblack, BOARD_SIZE, 'K'); bishop(pboard, i, j, pblack, BOARD_SIZE, 'K'); break; case('Q'): rook(pboard, i, j, pwhite, BOARD_SIZE, 'k'); bishop(pboard, i, j, pwhite, BOARD_SIZE, 'k'); break; case('n'): knight(i, j, pblack); break; case('N'): knight(i, j, pwhite); break; default: break; } } } #ifdef _DEBUG_ printf("---------------------\n"); printf("bk: %d %d wk: %d %d\n", bk_row, bk_col, wk_row, wk_col); for(i=0; i<BOARD_SIZE; i++){ for(j=0; j<BOARD_SIZE; j++){ printf("%01d", white[2+i][2+j]); } printf(" "); for(j=0; j<BOARD_SIZE; j++){ printf("%01d", black[2+i][2+j]); } printf(" "); for(j=0; j<BOARD_SIZE; j++){ printf("%c", board[i][j]); } printf("\n"); } printf("---------------------\n"); #endif if((white[2+bk_row][2+bk_col]==0)&&(black[2+wk_row][2+wk_col]==0)){ printf("Game #%d: no king is in check.\n", game); } if(white[2+bk_row][2+bk_col] != 0){ printf("Game #%d: black king is in check.\n", game); } if(black[2+wk_row][2+wk_col] != 0){ printf("Game #%d: white king is in check.\n", game); } for(i=0; i<BOARD_SIZE; i++){ #ifdef _DEBUG_ fscanf(f, "%s", &board[i][0]); #else scanf("%s", &board[i][0]); #endif } } return 0; }
// Decodes a string in long algebraic notation and returns a move. If the // notation is not recognized the move is returned as (Move)0. //------------------------------------------------------------------------------ Move new_move_from_string(Position *self, char *e2e4) { bool queen_side_castle = !strcmp(e2e4, "0-0-0"); bool king_side_castle = !strcmp(e2e4, "0-0") && !queen_side_castle; if (king_side_castle || queen_side_castle) { bool king_side_ok = false, queen_side_ok = false; can_castle(self, self->color, &king_side_ok, &queen_side_ok); if (king_side_castle && king_side_ok) { int from = self->king[self->color]; int to = G1 + self->color * A8; return validate(self, new_castle(self, from, to)); } if (queen_side_castle && queen_side_ok) { int from = self->king[self->color]; int to = C1 + self->color * A8; return validate(self, new_castle(self, from, to)); } return (Move)0; } char notation[strlen(e2e4)]; char *src = e2e4, *dst = notation; // Strip all optional characters. while (*src) { if (strchr("KkQqRrBbNn12345678acdefgh", *src)) { *dst++ = *src; } src++; } *dst = '\0'; if (strlen(notation) >= 4 && strlen(notation) <= 5) { // Validate optional piece character to make sure the actual piece it // represents is there. Piece piece = pawn(self->color); switch (notation[0]) { case 'K': piece = king(self->color); break; case 'Q': piece = queen(self->color); break; case 'R': piece = rook(self->color); break; case 'B': piece = bishop(self->color); break; case 'N': piece = knight(self->color); } int sq; if (is_pawn(piece)) { sq = square(notation[1] - '1', notation[0] - 'a'); } else { sq = square(notation[2] - '1', notation[1] - 'a'); } if (sq >= A1 && sq <= H8) { if (self->pieces[sq] == piece) { return validate(self, new_move_from_notation(self, is_pawn(piece) ? notation : notation + 1)); } } } return (Move)0; }
// Non-capturing checks. //------------------------------------------------------------------------------ MoveGen *generate_checks(MoveGen *self) { Position *p = self->p; int color = p->color, enemy = p->color ^ 1; int square = (int)p->king[enemy]; // Non-capturing Knight checks. Bitmask prohibit = maskNone; Bitmask checks = knightMoves[square]; Bitmask outposts = p->outposts[knight(color)]; while (any(outposts)) { int from = pop(&outposts); add_piece_move(self, from, knightMoves[from] & checks & ~p->board); } // Non-capturing Bishop or Queen checks. checks = targets_for(p, square, bishop(enemy)); outposts = p->outposts[bishop(color)] | p->outposts[queen(color)]; while (any(outposts)) { int from = pop(&outposts); Bitmask squares = targets_for(p, from, bishop(enemy)) & checks & ~p->outposts[enemy]; while (any(squares)) { int to = pop(&squares); Piece piece = p->pieces[to]; if (!piece) { // Empty square: simply move a bishop to check. append(self, new_move(p, from, to)); } else if (color(piece) == color && any(maskDiagonal[from][square])) { // Non-empty square occupied by friendly piece on the same // diagonal: moving the piece away causes discovered check. switch (kind(piece)) { case Pawn: // Block pawn promotions (since they are treated as // captures) and en-passant captures. prohibit = maskRank[0] | maskRank[7]; if (p->enpassant) { prohibit |= bit[p->enpassant]; } add_pawn_move(self, to, targets(p, to) & ~p->board & ~prohibit); break; case King: // Make sure the king steps out of attack diaginal. add_king_move(self, to, targets(p, to) & ~p->board & ~maskBlock[from][square]); break; default: add_piece_move(self, to, targets(p, to) & ~p->board); } } } if (is_queen(p->pieces[from])) { // Queen could move straight as a rook and check diagonally as a bishop // or move diagonally as a bishop and check straight as a rook. Bitmask squares = (targets_for(p, from, rook(color)) & checks) | (targets_for(p, from, bishop(color)) & targets_for(p, square, rook(color))); add_piece_move(self, from, squares & ~p->board); } } // Non-capturing Rook or Queen checks. checks = targets_for(p, square, rook(enemy)); outposts = p->outposts[rook(color)] | p->outposts[queen(color)]; while (any(outposts)) { int from = pop(&outposts); Bitmask squares = targets_for(p, from, rook(enemy)) & checks & ~p->outposts[enemy]; while (any(squares)) { int to = pop(&squares); Piece piece = p->pieces[to]; if (!piece) { // Empty square: simply move a rook to check. append(self, new_move(p, from, to)); } else if (color(piece) == color) { if (any(maskStraight[from][square])) { // Non-empty square occupied by friendly piece on the same // file or rank: moving the piece away causes discovered check. switch (kind(piece)) { case Pawn: // If pawn and rook share the same file then non-capturing // discovered check is not possible since the pawn is going // to stay on the same file no matter what. if (col(from) == col(to)) { continue; } // Block pawn promotions (since they are treated as captures) // and en-passant captures. prohibit = maskRank[0] | maskRank[7]; if (p->enpassant) { prohibit |= bit[p->enpassant]; } add_pawn_move(self, to, targets(p, to) & ~p->board & ~prohibit); break; case King: // Make sure the king steps out of attack file or rank. prohibit = maskNone; if (row(from) == row(square)) { prohibit = maskRank[row(from)]; } else { prohibit = maskFile[col(square)]; } add_king_move(self, to, targets(p, to) & ~p->board & ~prohibit); break; default: add_piece_move(self, to, targets(p, to) & ~p->board); } } } } } // Non-capturing Pawn checks. outposts = p->outposts[pawn(color)] & maskIsolated[col(square)]; while (any(outposts)) { int from = pop(&outposts); Bitmask target = maskPawn[color][square] & targets(p, from); if (any(target)) { append(self, new_pawn_move(p, from, pop(&target))); } } return self; }