inline void bishop_move(struct position *pos, struct move_array *m, unsigned char bishops) { uint64_t bishop_pos = pos->pieces[bishops]; uint64_t moves; unsigned char index_from, index_to; for (int i = 0; i < 10; i++) { // up to 10 bishops of same color on the board, (for loop for compiler loop unrolling) if ((index_from = ffsll(bishop_pos)) != 0) { index_from--; moves = BishopMoves[index_from][magictransform((pos->allpieces & BishopMasks[index_from]), BishopMagic[index_from], BishopMagicSize [index_from])] & ~pos-> sumpieces[bishops & COLOR]; for (int i = 0; i < 14; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_move(m, index_from, index_to, bishops, find_piece(pos, index_to)); moves &= notlinboard[index_to]; } else { break; } } bishop_pos &= notlinboard[index_from]; } else { break; } } }
int count_query(int a, int b){ view_query(a,b); int L=0, cnt=0; ci_iter it1, it2; if (ci.count(a)){ it1 = ci.lower_bound(a); L = it1->second.pos; } else { int L1,R1; it1 = find_piece(ci, N, a, L1, R1); for (int i=L1; i<R1; i++) if (arr[i] >= a && arr[i] < b) cnt++; L = R1; it1++; } assert(it1 != ci.end()); it1++; if (ci.count(b)){ it2 = ci.lower_bound(b); } else { int L2, R2; it2 = find_piece(ci, N, b, L2, R2); for (int i=L2; i<R2; i++) if (arr[i] >= a && arr[i] < b) cnt++; assert(it1 != it2); it2--; } while (true){ cnt += it1->second.prev_pos() - L; L = it1->second.pos; if (it1 == it2) break; it1++; } return cnt; }
inline void king_move(struct position *pos, struct move_array *m, unsigned char king) { unsigned char from = ffsll(pos->pieces[king]) - 1; uint64_t moves = kingmoves[from] & ~pos->sumpieces[king & COLOR]; unsigned char index; for (int i = 0; i < 8; i++) { if ((index = ffsll(moves)) != 0) { index--; add_move(m, from, index, king, find_piece(pos, index)); moves &= notlinboard[index]; } else { break; } } }
/* This function exists for disambiguation purposes. * Piece 'piece' from coords (previous_x, previous_y) didn't move. Instead we'll * move the same type of piece from coords (new_x, new_y). The question is: * Does after this move our king will be save? */ bool is_king_defended_after_move(char piece, char new_x, signed char new_y, char previous_x, signed char previous_y, const char (*Board)[8]) { char king = (piece >= 'A' && piece <= 'Z' ? 'K' : 'k'); // white king can't be under attack after white's move char (*new_board)[8] = (char (*)[8])malloc(8 * 8 * sizeof(char)); memcpy(new_board, Board, 8 * 8 * sizeof(char)); new_board[8 - previous_y][previous_x - 'a'] = piece; new_board[8 - new_y][new_x - 'a'] = ' '; struct piece king_placement; if (find_piece(king, &king_placement, (const char (*)[8])new_board)) if (is_piece_attacked(king, king_placement.alphabetical, king_placement.numerical, (const char (*)[8])new_board, 1) == 0) { free(new_board); return 1; } free(new_board); return 0; }
bool in_check(bool is_white) { char tc, fc; int tr, fr; if (!find_piece(is_white ? 'K' : 'k', tc, tr)) return false; for (int i = 0; i < SZ; i++) { for (int j = 0; j < SZ; j++) { fc = int_to_char(j); fr = i + 1; if (iscol(fc, fr, !is_white)) { switch (toupper(bd[i][j])) { case 'P': break; case 'N': if (KNCHK) return true; break; case 'B': if (BSCHK) return true; break; case 'R': if (RKCHK) return true; break; case 'Q': if (QNCHK) return true; break; case 'K': if (KGCHK) return true; default: break; } } } } return false; }
inline void knight_move(struct position *pos, struct move_array *m, unsigned char knights) { uint64_t knight_pos = pos->pieces[knights]; uint64_t moves; unsigned char index_from, index_to; for (int i = 0; i < 10; i++) { // can have up to 10 knights of same color on the board, (for loop for compiler loop unrolling) if ((index_from = ffsll(knight_pos)) != 0) { index_from--; moves = knightmoves[index_from] & ~pos->sumpieces[knights & COLOR]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_move(m, index_from, index_to, knights, find_piece(pos, index_to)); moves &= notlinboard[index_to]; } else { break; } } knight_pos &= notlinboard[index_from]; } else { break; } } }
bool king_in_checkmate( game_board_data * board, int piece ) { int x = 0, y = 0, dx, dy, sk = 0; if( piece != WHITE_KING && piece != BLACK_KING ) return false; if( !find_piece( board, &x, &y, piece ) ) return false; if( x < 0 || y < 0 || x > 7 || y > 7 ) return false; if( !king_in_check( board, board->board[x][y] ) ) return false; dx = x + 1; dy = y + 1; if( dx < 8 && dy < 8 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return false; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x - 1; dy = y + 1; if( dx >= 0 && dy < 8 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return false; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x + 1; dy = y - 1; if( dx < 8 && dy >= 0 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return false; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x - 1; dy = y - 1; if( dx >= 0 && dy >= 0 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return false; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x; dy = y + 1; if( dy < 8 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return false; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x; dy = y - 1; if( dy >= 0 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return false; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x + 1; dy = y; if( dx < 8 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return false; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x - 1; dy = y; if( dx >= 0 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return false; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } return true; }
bool king_in_check( game_board_data * board, int piece ) { int x = 0, y = 0, l, m; if( piece != WHITE_KING && piece != BLACK_KING ) return false; if( !find_piece( board, &x, &y, piece ) ) return false; if( x < 0 || y < 0 || x > 7 || y > 7 ) return false; /* * pawns */ if( IS_WHITE( piece ) && x < 7 && ( ( y > 0 && IS_BLACK( board->board[x + 1][y - 1] ) ) || ( y < 7 && IS_BLACK( board->board[x + 1][y + 1] ) ) ) ) return true; else if( IS_BLACK( piece ) && x > 0 && ( ( y > 0 && IS_WHITE( board->board[x - 1][y - 1] ) ) || ( y < 7 && IS_WHITE( board->board[x - 1][y + 1] ) ) ) ) return true; /* * knights */ if( x - 2 >= 0 && y - 1 >= 0 && ( ( board->board[x - 2][y - 1] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x - 2][y - 1] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return true; if( x - 2 >= 0 && y + 1 < 8 && ( ( board->board[x - 2][y + 1] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x - 2][y + 1] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return true; if( x - 1 >= 0 && y - 2 >= 0 && ( ( board->board[x - 1][y - 2] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x - 1][y - 2] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return true; if( x - 1 >= 0 && y + 2 < 8 && ( ( board->board[x - 1][y + 2] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x - 1][y + 2] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return true; if( x + 1 < 8 && y - 2 >= 0 && ( ( board->board[x + 1][y - 2] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x + 1][y - 2] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return true; if( x + 1 < 8 && y + 2 < 8 && ( ( board->board[x + 1][y + 2] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x + 1][y + 2] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return true; if( x + 2 < 8 && y - 1 >= 0 && ( ( board->board[x + 2][y - 1] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x + 2][y - 1] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return true; if( x + 2 < 8 && y + 1 < 8 && ( ( board->board[x + 2][y + 1] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x + 2][y + 1] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return true; /* * horizontal/vertical long distance */ for( l = x + 1; l < 8; ++l ) if( board->board[l][y] != NO_PIECE ) { if( SAME_COLOR( x, y, l, y ) ) break; if( board->board[l][y] == BLACK_QUEEN || board->board[l][y] == WHITE_QUEEN || board->board[l][y] == BLACK_ROOK || board->board[l][y] == WHITE_ROOK ) return true; break; } for( l = x - 1; l >= 0; --l ) if( board->board[l][y] != NO_PIECE ) { if( SAME_COLOR( x, y, l, y ) ) break; if( board->board[l][y] == BLACK_QUEEN || board->board[l][y] == WHITE_QUEEN || board->board[l][y] == BLACK_ROOK || board->board[l][y] == WHITE_ROOK ) return true; break; } for( m = y + 1; m < 8; ++m ) if( board->board[x][m] != NO_PIECE ) { if( SAME_COLOR( x, y, x, m ) ) break; if( board->board[x][m] == BLACK_QUEEN || board->board[x][m] == WHITE_QUEEN || board->board[x][m] == BLACK_ROOK || board->board[x][m] == WHITE_ROOK ) return true; break; } for( m = y - 1; m >= 0; --m ) if( board->board[x][m] != NO_PIECE ) { if( SAME_COLOR( x, y, x, m ) ) break; if( board->board[x][m] == BLACK_QUEEN || board->board[x][m] == WHITE_QUEEN || board->board[x][m] == BLACK_ROOK || board->board[x][m] == WHITE_ROOK ) return true; break; } /* * diagonal long distance */ for( l = x + 1, m = y + 1; l < 8 && m < 8; ++l, ++m ) if( board->board[l][m] != NO_PIECE ) { if( SAME_COLOR( x, y, l, m ) ) break; if( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN || board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP ) return true; break; } for( l = x - 1, m = y + 1; l >= 0 && m < 8; --l, ++m ) if( board->board[l][m] != NO_PIECE ) { if( SAME_COLOR( x, y, l, m ) ) break; if( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN || board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP ) return true; break; } for( l = x + 1, m = y - 1; l < 8 && m >= 0; ++l, --m ) if( board->board[l][m] != NO_PIECE ) { if( SAME_COLOR( x, y, l, m ) ) break; if( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN || board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP ) return true; break; } for( l = x - 1, m = y - 1; l >= 0 && m >= 0; --l, --m ) if( board->board[l][m] != NO_PIECE ) { if( SAME_COLOR( x, y, l, m ) ) break; if( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN || board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP ) return true; break; } return false; }
inline void pawn_move(struct position *pos, struct move_array *m, unsigned char pawns) { uint64_t pawn_pos = pos->pieces[pawns]; uint64_t moves; unsigned char index_to; switch (pawns & COLOR) { case WHITE: // nonpromotion forward moves moves = moveN(pawn_pos) & ~pos->allpieces & ~rank[7]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_move(m, index_to + S, index_to, pawns, nopiece_n); moves &= notlinboard[index_to]; } else { break; } } // forward 2 moves pawn_pos = pos->pieces[pawns]; moves = moveN(moveN(pawn_pos) & ~pos->allpieces) & ~pos->allpieces & rank[3]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_move_forward2(m, index_to + S + S, index_to, pawns, nopiece_n); moves &= notlinboard[index_to]; } else { break; } } // nonpromotion attack west moves pawn_pos = pos->pieces[pawns]; moves = moveNW(pawn_pos) & (pos->bpieces | ep_squares[1][pos->ep]) & ~file[7] & ~rank[7]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_move(m, index_to + SE, index_to, pawns, find_piece_ep(pos, index_to)); moves &= notlinboard[index_to]; } else { break; } } // nonpromotion attack east moves pawn_pos = pos->pieces[pawns]; moves = moveNE(pawn_pos) & (pos->bpieces | ep_squares[1][pos->ep]) & ~file[0] & ~rank[7]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_move(m, index_to + SW, index_to, pawns, find_piece_ep(pos, index_to)); moves &= notlinboard[index_to]; } else { break; } } pawn_pos = pos->pieces[pawns]; if ((pawn_pos & rank[6]) == 0) { // no promotion possibilities return; } else { // promotion forward moves moves = moveN(pawn_pos) & ~pos->allpieces & rank[7]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_promotion_move(m, index_to + S, index_to, pawns, nopiece_n); moves &= notlinboard[index_to]; } else { break; } } // promotion attack west moves pawn_pos = pos->pieces[pawns]; moves = moveNW(pawn_pos) & pos->bpieces & ~file[7] & rank[7]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_promotion_move(m, index_to + SE, index_to, pawns, find_piece(pos, index_to)); moves &= notlinboard[index_to]; } else { break; } } // promotion attack east moves pawn_pos = pos->pieces[pawns]; moves = moveNE(pawn_pos) & pos->bpieces & ~file[0] & rank[7]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_promotion_move(m, index_to + SW, index_to, pawns, find_piece(pos, index_to)); moves &= notlinboard[index_to]; } else { break; } } } break; default: // black // nonpromotion forward moves moves = moveS(pawn_pos) & ~pos->allpieces & ~rank[0]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_move(m, index_to + N, index_to, pawns, nopiece_n); moves &= notlinboard[index_to]; } else { break; } } // forward 2 moves pawn_pos = pos->pieces[pawns]; moves = moveS(moveS(pawn_pos) & ~pos->allpieces) & ~pos->allpieces & rank[4]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_move_forward2(m, index_to + N + N, index_to, pawns, nopiece_n); moves &= notlinboard[index_to]; } else { break; } } // nonpromotion attack west moves pawn_pos = pos->pieces[pawns]; moves = moveSW(pawn_pos) & (pos->wpieces | ep_squares[0][pos->ep]) & ~file[7] & ~rank[0]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_move(m, index_to + NE, index_to, pawns, find_piece_ep(pos, index_to)); moves &= notlinboard[index_to]; } else { break; } } // nonpromotion attack east moves pawn_pos = pos->pieces[pawns]; moves = moveSE(pawn_pos) & (pos->wpieces | ep_squares[0][pos->ep]) & ~file[0] & ~rank[0]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_move(m, index_to + NW, index_to, pawns, find_piece_ep(pos, index_to)); moves &= notlinboard[index_to]; } else { break; } } pawn_pos = pos->pieces[pawns]; if ((pawn_pos & rank[1]) == 0) { // no promotion possibilities return; } else { // promotion forward moves moves = moveS(pawn_pos) & ~pos->allpieces & rank[0]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_promotion_move(m, index_to + N, index_to, pawns, nopiece_n); moves &= notlinboard[index_to]; } else { break; } } // promotion attack west moves pawn_pos = pos->pieces[pawns]; moves = moveSW(pawn_pos) & pos->wpieces & ~file[7] & rank[0]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_promotion_move(m, index_to + NE, index_to, pawns, find_piece(pos, index_to)); moves &= notlinboard[index_to]; } else { break; } } // promotion attack east moves pawn_pos = pos->pieces[pawns]; moves = moveSE(pawn_pos) & pos->wpieces & ~file[0] & rank[0]; for (int i = 0; i < 8; i++) { if ((index_to = ffsll(moves)) != 0) { index_to--; add_promotion_move(m, index_to + NW, index_to, pawns, find_piece(pos, index_to)); moves &= notlinboard[index_to]; } else { break; } } } break; } }
/* * Controlla se il re sia in possibile scacco matto * (TT) Purtroppo questa parte è parziale, visto che si potrebbe coprire lo scacco con * uno spostamento di un'altro pezzo, bisogna vedere in gioco come si comporta */ static bool king_in_possible_checkmate( CHESSBOARD_DATA *board, const int piece, const int color ) { int x = 0; int y = 0; int direction; if ( !board ) { send_log( NULL, LOG_BUG, "king_in_possible_checkmate: board passata è NULL" ); return FALSE; } if ( piece < 0 || piece >= PIECE_NONE ) { send_log( NULL, LOG_BUG, "king_in_possible_checkmate: pezzo passato errato: %d", piece ); return FALSE; } if ( color < 0 || color >= COLOR_NONE ) { send_log( NULL, LOG_BUG, "king_in_possibile_checkmate: color passato è errato: %d", color ); return FALSE; } if ( piece != PIECE_KING ) return FALSE; /* Cercando il re nella scacchiera ritorna le coordinate del pezzo */ if ( !find_piece(board, &x, &y, piece) ) return FALSE; if ( x < 0 || y < 0 || x >= 8 || y >= 8 ) { send_log( NULL, LOG_BUG, "king_in_possible_checkmate: coordinate del pezzo %s errate: x=%d y=%d", table_pieces[piece].name, x, y ); return FALSE; } if ( king_in_check(board, board->piece[x][y], board->color[x][y]) == 0 ) return FALSE; for ( direction = 0; direction < 8; direction++ ) { int dirx = 0; int diry = 0; int sk = -1; int skc = -1; bool incheck = FALSE; switch ( direction ) { case 0: dirx = x + 1; diry = y + 1; case 1: dirx = x - 1; diry = y + 1; case 2: dirx = x + 1; diry = y - 1; case 3: dirx = x - 1; diry = y - 1; case 4: dirx = x; diry = y + 1; case 5: dirx = x; diry = y - 1; case 6: dirx = x + 1; diry = y; case 7: dirx = x - 1; diry = y; } if ( dirx < 0 ) continue; if ( dirx >= 8 ) continue; if ( diry < 0 ) continue; if ( diry >= 8 ) continue; if ( board->piece[dirx][diry] == PIECE_NONE ) { sk = board->piece[dirx][diry] = board->piece[x][y]; skc = board->color[dirx][diry] = board->color[x][y]; board->piece[x][y] = PIECE_NONE; board->color[x][y] = COLOR_NONE; if ( king_in_check(board, sk, skc) == 0 ) incheck = TRUE; board->piece[x][y] = sk; board->color[x][y] = skc; board->piece[dirx][diry] = PIECE_NONE; board->color[dirx][diry] = COLOR_NONE; if ( incheck ) return FALSE; } } return TRUE; }
void naive_random_crack(){ value_type x = arr[rr.nextInt(N)]; int L,R; find_piece(ci, N, x,L,R); n_touched += R-L; add_crack(ci, N, x, partition(arr, x,L,R)); }
/* * check if the color-king is checked (assuming there is a king on the board) */ int is_king_checked(int color, char board[BOARD_SIZE][BOARD_SIZE]) { char piece = (color == BLACK) ? BLACK_K : WHITE_K; cord c = find_piece(piece, board); return is_cord_checked(c, color, board); }
int main(int argc, char *argv[]) { const char *const Help = "fens2pgn - converts multiple FENs into single PGN file\n" "Syntax: fens2pgn [arguments] [output file] [input file]\n" "Arguments:\n" " -f force validity of every chess move\n" " -o take next argument as output file\n" " -q quiet - doesn't print informations to stderr\n" " -v verbose - notify of every skipped FEN\n" " -h, --help print this help text\n" " -u, --usage short usage information\n" " -V, --version display program version"; if (argc < 2) { puts(Help); return 0; } struct { bool validate; bool quiet; bool verbose; char *read_from_file; char *write_to_file; } parameters = {0, 0, 0, NULL, NULL}; const struct option long_options[] = { {"help", 0, NULL, 'h'}, {"usage", 0, NULL, 'u'}, {"version", 0, NULL, 'V'}, {NULL, 0, NULL, 0} }; for (int option, long_option_index; (option = getopt_long(argc, argv, "fho:quvV", long_options, &long_option_index)) != -1;) switch (option) { case 'f': parameters.validate = 1; break; case 'h': puts(Help); return 0; case 'o': parameters.write_to_file = optarg; break; case 'q': parameters.quiet = 1; parameters.verbose = 0; break; case 'u': puts("Syntax: fens2pgn [-fqv] [-o OUTPUT_FILE] [INPUT_FILE]\n" " [-h|--help] [-u|--usage] [-V|--version]"); return 0; case 'v': parameters.quiet = 0; parameters.verbose = 1; break; case 'V': puts("fens2pgn " VERSION "\n" "Copyright (C) 2015 Paweł Zacharek"); return 0; default: return EINVAL; } if (optind == argc - 1) // 1 unknown parameter (input file name) parameters.read_from_file = argv[optind]; else if (optind != argc) { // more unknown parameters fputs("Invalid argument(s) found.\n", stderr); return EINVAL; } FILE *input = (parameters.read_from_file == NULL ? stdin : fopen(parameters.read_from_file, "r")); FILE *output = (parameters.write_to_file == NULL ? stdout : fopen(parameters.write_to_file, "w")); if (input == NULL) { fprintf(stderr, "Can't open file \"%.255s\" for reading.\n", parameters.read_from_file); return ENOENT; } if (output == NULL) { fprintf(stderr, "Can't open file \"%.255s\" for writing.\n", parameters.read_from_file); return EACCES; } char fen_buffer[MAX_FEN_LENGHT + 1], fen_placement_buffer[MAX_PLACEMENT_LENGHT + 1]; char store_space[STORE_SPACE_SIZE], store_move[STORE_MOVE_SIZE]; char board_buffer_1[8][8], board_buffer_2[8][8]; char (*board_1)[8] = board_buffer_1, (*board_2)[8] = board_buffer_2; int fen_number = 0, move_number = 1, number_of_characters_in_line = 0; struct field distinctions[4], *field, *previous_field; struct piece king_placement; signed char number_of_differences; char control_character, whose_move = 'w', castling_prospects[4 + 1] = "KQkq", en_passant_field[2 + 1] = "-"; char control_string[8 + 1], result[7 + 1]; // to store respectively "Result \"" and "1/2-1/2" result[0] = '\0'; bool metadata_included = 0, fens_are_incomplete = 0, first_move_number_already_written = 0, move_is_invalid = 0; // beginning of METADATA section fscanf(input, " %c", &control_character); while (control_character == '[') { metadata_included = 1; putc('[', output); if (fscanf(input, "%8[^\n]", control_string) == 1) { if (strncmp(control_string, "Result \"", 8) == 0 && fscanf(input, "%7[-01/2*]", result) == 1) fprintf(output, "%s%s", control_string, result); else fputs(control_string, output); } for (int character; (character = getc(input)) != EOF;) { putc(character, output); if (character == '\n') break; } fscanf(input, " %c", &control_character); } ungetc(control_character, input); // beginning of GAME section if (fscanf(input, "%" STR(MAX_FEN_LENGHT) "[-0-9a-h/rnqkpRNBQKP w]", fen_buffer) != 1) { // reading the first FEN fputs("No valid FEN found.\n", stderr); return EILSEQ; } ++fen_number; sscanf(fen_buffer, "%" STR(MAX_PLACEMENT_LENGHT) "[1-8/rnbqkpRNBQKP]", fen_placement_buffer); if (strncmp(fen_buffer, "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", 56) != 0) { // it isn't classical complete FEN if (sscanf(fen_buffer, "%*[1-8/rnbqkpRNBQKP] %c %4s %2s %*d %d", &whose_move, castling_prospects, en_passant_field, &move_number) != 4) { // FENs are incomplete fens_are_incomplete = 1; if (parameters.quiet != 1) fputs("FENs considered incomplete.\n", stderr); // not corrupts redirected output whose_move = 'w'; strcpy(castling_prospects, "KQkq"); strcpy(en_passant_field, "-"); move_number = 1; } if (fens_are_incomplete == 0 || strncmp(fen_buffer, "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", 43) != 0) // starting position isn't classical fprintf(output, "[SetUp \"1\"]\n[FEN \"%s\"]\n", fen_buffer); } if (metadata_included == 1) putc('\n', output); if (fen2board(fen_placement_buffer, board_1, parameters.validate) == 0) { fputs("There are more than 2 kings or invalid pieces on the first board. Terminating.\n", stderr); return 0; } for (;;) { if (fscanf(input, " %" STR(MAX_FEN_LENGHT) "[-0-9a-h/rnqkpRNBQKP w]", fen_buffer) != 1) break; ++fen_number; sscanf(fen_buffer, "%" STR(MAX_PLACEMENT_LENGHT) "[1-8/rnbqkpRNBQKP]", fen_placement_buffer); if (fen2board(fen_placement_buffer, board_2, parameters.validate) == 0) { fprintf(stderr, "There are more than 2 kings or invalid pieces on board nr %d. Terminating.\n", fen_number); return 0; } number_of_differences = compare_boards((const char (*)[8])board_1, (const char (*)[8])board_2, distinctions); if (number_of_differences < 2) { if (parameters.verbose == 1) fprintf(stderr, "Skipped \"%s\" (%d%s FEN).\n", fen_buffer, fen_number, Ordinal_Number_Suffix(fen_number)); continue; } if (number_of_differences > 4) { fprintf(stderr, "Can't compare \"%s\" (%d%s FEN) with the previous one.\n", fen_buffer, fen_number, Ordinal_Number_Suffix(fen_number)); return EILSEQ; } switch (number_of_differences) { case 2: // ordinary move or capture if (distinctions[0].piece_after != ' ') { field = &distinctions[0]; previous_field = &distinctions[1]; } else { // it means that (distinctions[1].piece_after != ' ') field = &distinctions[1]; previous_field = &distinctions[0]; } switch (what_to_write((const char (*)[8])board_2, (const struct field *)field, (const struct field *)previous_field, en_passant_field, parameters.validate, whose_move, castling_prospects)) { case PAWN_MOVE: snprintf(store_move, STORE_MOVE_SIZE, "%c%hhd", field->alphabetical, field->numerical); break; case PAWN_CAPTURE: snprintf(store_move, STORE_MOVE_SIZE, "%cx%c%hhd", previous_field->alphabetical, field->alphabetical, field->numerical); break; case PAWN_PROMOTION: snprintf(store_move, STORE_MOVE_SIZE, "%c%hhd=%c", field->alphabetical, field->numerical, toupper(field->piece_after)); break; case PAWN_CAPTURE_PROMOTION: snprintf(store_move, STORE_MOVE_SIZE, "%cx%c%hhd=%c", previous_field->alphabetical, field->alphabetical, field->numerical, toupper(field->piece_after)); break; case PIECE_MOVE: snprintf(store_move, STORE_MOVE_SIZE, field->piece_before != ' ' ? "%cx%c%hhd" : "%c%c%hhd", toupper(field->piece_after), field->alphabetical, field->numerical); break; case DIS_LINE: case DIS_WHICHEVER: snprintf(store_move, STORE_MOVE_SIZE, field->piece_before != ' ' ? "%c%cx%c%hhd" : "%c%c%c%hhd", toupper(field->piece_after), previous_field->alphabetical, field->alphabetical, field->numerical); break; case DIS_COLUMN: snprintf(store_move, STORE_MOVE_SIZE, field->piece_before != ' ' ? "%c%hhdx%c%hhd" : "%c%hhd%c%hhd", toupper(field->piece_after), previous_field->numerical, field->alphabetical, field->numerical); break; case DIS_BOTH: snprintf(store_move, STORE_MOVE_SIZE, field->piece_before != ' ' ? "%c%c%hhdx%c%hhd" : "%c%c%hhd%c%hhd", toupper(field->piece_after), previous_field->alphabetical, previous_field->numerical, field->alphabetical, field->numerical); break; case INVALID_MOVE: move_is_invalid = 1; break; } break; case 3: // en passant capture if (parameters.validate != 1) { if (whose_move == 'w') snprintf(store_move, STORE_MOVE_SIZE, "%cx%c%hhd", distinctions[0].alphabetical == distinctions[2].alphabetical ? distinctions[1].alphabetical : distinctions[2].alphabetical, distinctions[0].alphabetical, distinctions[0].numerical); else snprintf(store_move, STORE_MOVE_SIZE, "%cx%c%hhd", distinctions[0].alphabetical == distinctions[2].alphabetical ? distinctions[1].alphabetical : distinctions[0].alphabetical, distinctions[2].alphabetical, distinctions[2].numerical); } else { char all_fields[6 + 1]; snprintf(all_fields, sizeof all_fields, "%c%c%c%c%c%c", distinctions[0].piece_before, distinctions[0].piece_after, distinctions[1].piece_before, distinctions[1].piece_after, distinctions[2].piece_before, distinctions[2].piece_after); if (whose_move == 'w' && en_passant_field[0] == distinctions[0].alphabetical && en_passant_field[1] - '0' == distinctions[0].numerical && distinctions[0].numerical == distinctions[2].numerical + 1 && distinctions[1].alphabetical == distinctions[2].alphabetical - 1 && ( distinctions[0].alphabetical == distinctions[2].alphabetical && memcmp(all_fields, " PP p ", 6) == 0 || distinctions[0].alphabetical != distinctions[2].alphabetical && memcmp(all_fields, " Pp P ", 6) == 0 )) snprintf(store_move, STORE_MOVE_SIZE, "%cx%c%hhd", distinctions[0].alphabetical == distinctions[2].alphabetical ? distinctions[1].alphabetical : distinctions[2].alphabetical, distinctions[0].alphabetical, distinctions[0].numerical); else if (whose_move == 'b' && en_passant_field[0] == distinctions[2].alphabetical && en_passant_field[1] - '0' == distinctions[2].numerical && distinctions[0].numerical == distinctions[2].numerical + 1 && distinctions[0].alphabetical == distinctions[1].alphabetical - 1 && ( distinctions[0].alphabetical == distinctions[2].alphabetical && memcmp(all_fields, "P p p", 6) == 0 || distinctions[0].alphabetical != distinctions[2].alphabetical && memcmp(all_fields, "p P p", 6) == 0 )) snprintf(store_move, STORE_MOVE_SIZE, "%cx%c%hhd", distinctions[0].alphabetical == distinctions[2].alphabetical ? distinctions[1].alphabetical : distinctions[0].alphabetical, distinctions[2].alphabetical, distinctions[2].numerical); else move_is_invalid = 1; } break; case 4: // castling if (parameters.validate != 1) snprintf(store_move, STORE_MOVE_SIZE, distinctions[0].alphabetical == 'a' ? "O-O-O" : "O-O"); else { if (distinctions[0].alphabetical == 'a' && is_king_checked_while_castling(distinctions[3].piece_before, distinctions[3].alphabetical, distinctions[3].numerical, (const char (*)[8])board_1, (const char (*)[8])board_2, -1) == 0 && ( whose_move == 'w' && strchr(castling_prospects, 'Q') != NULL && memcmp(&board_1[8 - 1][0], "R K", 5) == 0 && memcmp(&board_2[8 - 1][0], " KR ", 5) == 0 || whose_move == 'b' && strchr(castling_prospects, 'q') != NULL && memcmp(&board_1[8 - 8][0], "r k", 5) == 0 && memcmp(&board_2[8 - 8][0], " kr ", 5) == 0 )) snprintf(store_move, STORE_MOVE_SIZE, "O-O-O"); else if (distinctions[3].alphabetical == 'h' && is_king_checked_while_castling(distinctions[0].piece_before, distinctions[0].alphabetical, distinctions[0].numerical, (const char (*)[8])board_1, (const char (*)[8])board_2, 1) == 0 && ( whose_move == 'w' && strchr(castling_prospects, 'K') != NULL && memcmp(&board_1[8 - 1][4], "K R", 4) == 0 && memcmp(&board_2[8 - 1][0], " RK ", 4) == 0 || whose_move == 'b' && strchr(castling_prospects, 'k') != NULL && memcmp(&board_1[8 - 8][4], "k r", 4) == 0 && memcmp(&board_2[8 - 8][0], " rk ", 4) == 0 )) snprintf(store_move, STORE_MOVE_SIZE, "O-O"); else move_is_invalid = 1; } break; } if (parameters.validate == 1 && move_is_invalid == 1) { move_is_invalid = 0; if (parameters.quiet != 1) fprintf(stderr, "Skipped \"%s\" (%d%s FEN) because the calculated move is invalid.\n", fen_buffer, fen_number, Ordinal_Number_Suffix(fen_number)); continue; } if (parameters.validate == 1 && find_piece(whose_move == 'w' ? 'K' : 'k', &king_placement, (const char (*)[8])board_2)) if (is_piece_attacked(king_placement.type, king_placement.alphabetical, king_placement.numerical, (const char (*)[8])board_2, 1)) { if (parameters.quiet != 1) fprintf(stderr, "Skipped \"%s\" (%d%s FEN) because we're still in check.\n", fen_buffer, fen_number, Ordinal_Number_Suffix(fen_number)); continue; } if (find_piece(whose_move == 'w' ? 'k' : 'K', &king_placement, (const char (*)[8])board_2)) if (is_piece_attacked(king_placement.type, king_placement.alphabetical, king_placement.numerical, (const char (*)[8])board_2, 1)) { // king is checked if (does_king_cannot_move((const struct piece *)&king_placement, board_2) && ( is_piece_attacked(king_placement.type, king_placement.alphabetical, king_placement.numerical, (const char (*)[8])board_2, 2) // double check || is_it_checkmate(king_placement.alphabetical, king_placement.numerical, (const char (*)[8])board_2, (const char *)en_passant_field) )) snprintf(store_move + strlen(store_move), STORE_MOVE_SIZE - strlen(store_move), "#"); else snprintf(store_move + strlen(store_move), STORE_MOVE_SIZE - strlen(store_move), "+"); } if (first_move_number_already_written == 1) strcpy(store_space, " "); if (whose_move == 'w' || first_move_number_already_written == 0) snprintf(store_space + (first_move_number_already_written ? 1 : 0), STORE_SPACE_SIZE - (first_move_number_already_written ? 1 : 0), "%d. ", move_number); number_of_characters_in_line += strlen(store_space) - 1; // we can omit trailing space if (number_of_characters_in_line >= 80) { store_space[0] = '\n'; number_of_characters_in_line = strlen(store_space) - 2; // the first space is also not included } number_of_characters_in_line += strlen(store_move) + 1; // add previously disregarded trailing space if (number_of_characters_in_line >= 80) { store_space[strlen(store_space) - 1] = '\n'; number_of_characters_in_line = strlen(store_move); // doesn't count trailing space of 'store_space' array } fprintf(output, "%s%s", store_space, store_move); first_move_number_already_written = 1; if (whose_move == 'b') ++move_number; whose_move = (whose_move == 'b' ? 'w' : 'b'); swap_pointers((void **)&board_1, (void **)&board_2); } if (result[0] != '\0') fprintf(output, "%c%s\n", number_of_characters_in_line + 1 + strlen(result) >= 80 ? '\n' : ' ', result); else fprintf(output, "%c*\n", number_of_characters_in_line + 2 >= 80 ? '\n' : ' '); fclose(input); fclose(output); return 0; }
static bool king_in_check( GAME_BOARD_DATA * board, int piece ) { int x = 0, y = 0, l, m; if ( piece != WHITE_KING && piece != BLACK_KING ) return FALSE; if ( !find_piece( board, &x, &y, piece ) ) return FALSE; if ( x < 0 || y < 0 || x > 7 || y > 7 ) return FALSE; /* * pawns */ if ( IS_WHITE( piece ) && x < 7 && ( ( y > 0 && IS_BLACK( board->board[x + 1][y - 1] ) ) || ( y < 7 && IS_BLACK( board->board[x + 1][y + 1] ) ) ) ) return TRUE; else if ( IS_BLACK( piece ) && x > 0 && ( ( y > 0 && IS_WHITE( board->board[x - 1][y - 1] ) ) || ( y < 7 && IS_WHITE( board->board[x - 1][y + 1] ) ) ) ) return TRUE; /* * knights */ if ( x - 2 >= 0 && y - 1 >= 0 && ( ( board->board[x - 2][y - 1] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x - 2][y - 1] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return TRUE; if ( x - 2 >= 0 && y + 1 < 8 && ( ( board->board[x - 2][y + 1] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x - 2][y + 1] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return TRUE; if ( x - 1 >= 0 && y - 2 >= 0 && ( ( board->board[x - 1][y - 2] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x - 1][y - 2] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return TRUE; if ( x - 1 >= 0 && y + 2 < 8 && ( ( board->board[x - 1][y + 2] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x - 1][y + 2] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return TRUE; if ( x + 1 < 8 && y - 2 >= 0 && ( ( board->board[x + 1][y - 2] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x + 1][y - 2] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return TRUE; if ( x + 1 < 8 && y + 2 < 8 && ( ( board->board[x + 1][y + 2] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x + 1][y + 2] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return TRUE; if ( x + 2 < 8 && y - 1 >= 0 && ( ( board->board[x + 2][y - 1] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x + 2][y - 1] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return TRUE; if ( x + 2 < 8 && y + 1 < 8 && ( ( board->board[x + 2][y + 1] == BLACK_KNIGHT && IS_WHITE( board->board[x][y] ) ) || ( board->board[x + 2][y + 1] == WHITE_KNIGHT && IS_BLACK( board->board[x][y] ) ) ) ) return TRUE; /* * horizontal/vertical long distance */ for ( l = x + 1; l < 8; l++ ) if ( board->board[l][y] != NO_PIECE ) { if ( SAME_COLOR( x, y, l, y ) ) break; if ( board->board[l][y] == BLACK_QUEEN || board->board[l][y] == WHITE_QUEEN || board->board[l][y] == BLACK_ROOK || board->board[l][y] == WHITE_ROOK ) return TRUE; break; } for ( l = x - 1; l >= 0; l-- ) if ( board->board[l][y] != NO_PIECE ) { if ( SAME_COLOR( x, y, l, y ) ) break; if ( board->board[l][y] == BLACK_QUEEN || board->board[l][y] == WHITE_QUEEN || board->board[l][y] == BLACK_ROOK || board->board[l][y] == WHITE_ROOK ) return TRUE; break; } for ( m = y + 1; m < 8; m++ ) if ( board->board[x][m] != NO_PIECE ) { if ( SAME_COLOR( x, y, x, m ) ) break; if ( board->board[x][m] == BLACK_QUEEN || board->board[x][m] == WHITE_QUEEN || board->board[x][m] == BLACK_ROOK || board->board[x][m] == WHITE_ROOK ) return TRUE; break; } for ( m = y - 1; m >= 0; m-- ) if ( board->board[x][m] != NO_PIECE ) { if ( SAME_COLOR( x, y, x, m ) ) break; if ( board->board[x][m] == BLACK_QUEEN || board->board[x][m] == WHITE_QUEEN || board->board[x][m] == BLACK_ROOK || board->board[x][m] == WHITE_ROOK ) return TRUE; break; } /* * diagonal long distance */ for ( l = x + 1, m = y + 1; l < 8 && m < 8; l++, m++ ) if ( board->board[l][m] != NO_PIECE ) { if ( SAME_COLOR( x, y, l, m ) ) break; if ( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN || board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP ) return TRUE; break; } for ( l = x - 1, m = y + 1; l >= 0 && m < 8; l--, m++ ) if ( board->board[l][m] != NO_PIECE ) { if ( SAME_COLOR( x, y, l, m ) ) break; if ( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN || board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP ) return TRUE; break; } for ( l = x + 1, m = y - 1; l < 8 && m >= 0; l++, m-- ) if ( board->board[l][m] != NO_PIECE ) { if ( SAME_COLOR( x, y, l, m ) ) break; if ( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN || board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP ) return TRUE; break; } for ( l = x - 1, m = y - 1; l >= 0 && m >= 0; l--, m-- ) if ( board->board[l][m] != NO_PIECE ) { if ( SAME_COLOR( x, y, l, m ) ) break; if ( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN || board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP ) return TRUE; break; } return FALSE; }
int ddr_find(value_type v){ int L,R; find_piece(ci, N, v, L,R); n_touched += R - L; return targeted_random_crack3(ci,v,arr,N,L,R,CRACK_AT); }
static bool king_in_checkmate( GAME_BOARD_DATA * board, int piece ) { int x = 0, y = 0, dx, dy, sk = 0; if ( piece != WHITE_KING && piece != BLACK_KING ) return FALSE; if ( !find_piece( board, &x, &y, piece ) ) return FALSE; if ( x < 0 || y < 0 || x > 7 || y > 7 ) return FALSE; if ( !king_in_check( board, board->board[x][y] ) ) return FALSE; dx = x + 1; dy = y + 1; if ( dx < 8 && dy < 8 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if ( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return FALSE; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x - 1; dy = y + 1; if ( dx >= 0 && dy < 8 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if ( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return FALSE; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x + 1; dy = y - 1; if ( dx < 8 && dy >= 0 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if ( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return FALSE; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x - 1; dy = y - 1; if ( dx >= 0 && dy >= 0 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if ( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return FALSE; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x; dy = y + 1; if ( dy < 8 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if ( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return FALSE; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x; dy = y - 1; if ( dy >= 0 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if ( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return FALSE; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x + 1; dy = y; if ( dx < 8 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if ( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return FALSE; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } dx = x - 1; dy = y; if ( dx >= 0 && board->board[dx][dy] == NO_PIECE ) { sk = board->board[dx][dy] = board->board[x][y]; board->board[x][y] = NO_PIECE; if ( !king_in_check( board, sk ) ) { board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; return FALSE; } board->board[x][y] = sk; board->board[dx][dy] = NO_PIECE; } return TRUE; }
/* * Controlla se il re è sotto scacco * Ritorna il numero di pezzi che tengono sotto scacco il re */ int king_in_check( CHESSBOARD_DATA *board, const int piece, const int color ) { int x = 0; int y = 0; int direction; int count = 0; /* conta quante volte contemporaneamente il re è sotto scacco */ if ( !board ) { send_log( NULL, LOG_BUG, "king_in_check: board passata è NULL" ); return 0; } if ( piece < 0 || piece >= PIECE_NONE ) { send_log( NULL, LOG_BUG, "king_in_check: pezzo passato errato: %d", piece ); return 0; } if ( color < 0 || color >= COLOR_NONE ) { send_log( NULL, LOG_BUG, "king_in_check: color passato errato: %d", color ); return 0; } if ( piece != PIECE_KING ) return 0; /* Cercando il pezzo nella scacchiera se lo trova imposta x e y con le coordinate del pezzo */ if ( !find_piece(board, &x, &y, piece) ) return 0; if ( x < 0 || y < 0 || x >= 8 || y >= 8 ) { send_log( NULL, LOG_BUG, "king_in_check: coordinate del pezzo %s errate: x=%d y=%d", table_pieces[piece].name, x, y ); return 0; } /* Pedoni - (??) ma qui se un cavallo si trova in posizione di scacco-pedone dà scacco anche lui?? manca il check che il tipo controllato sia un pedone secondo me */ if ( board->color[x][y] == COLOR_WHITE && x < 7 && ((y > 0 && board->color[x+1][y-1] == COLOR_BLACK) || (y < 7 && board->color[x+1][y+1] == COLOR_BLACK)) ) count++; else if ( board->color[x][y] == COLOR_BLACK && x > 0 && ((y > 0 && board->color[x-1][y-1] == COLOR_WHITE) || (y < 7 && board->color[x-1][y+1] == COLOR_WHITE)) ) count++; /* Cavallo - il cavallo può eseguire una mossa in 8 direzioni max */ for ( direction = 0; direction < 8; direction++ ) { int dirx = 0; int diry = 0; /* Imposta le direzioni per ogni tipo di mossa-direzione */ switch ( direction ) { case 0: dirx = x - 2; diry = y - 1; break; case 1: dirx = x - 2; diry = y + 1; break; case 2: dirx = x - 1; diry = y - 2; break; case 3: dirx = x - 1; diry = y + 2; break; case 4: dirx = x + 1; diry = y - 2; break; case 5: dirx = x + 1; diry = y + 2; break; case 6: dirx = x + 2; diry = y - 1; break; case 7: dirx = x + 2; diry = y + 1; break; } /* Se supera i limiti della scacchiera ignora la mossa */ if ( dirx < 0 ) continue; if ( dirx >= 8 ) continue; if ( diry < 0 ) continue; if ( diry >= 8 ) continue; /* Se nella direzione analizzata non ci sono pezzi ignora */ if ( board->piece[dirx][diry] == PIECE_NONE ) continue; /* Se il re e il cavallo hanno lo stesso colore ignora */ if ( SAME_COLOR(x, y, dirx, diry) ) continue; /* Se nella direzione analizza si trova un cavallo allora il re è sotto scacco */ if ( board->piece[x+dirx][y+diry] == PIECE_KNIGHT ) count++; } /* Alfiere, Torre, Regina - Controlla in una botta sola le 8 direzioni per i tre pezzi */ for ( direction = 0; direction < 8; direction++ ) { int len; /* lunghezza della ricerca nella direzione */ int dirx = 0; int diry = 0; /* E' come se partisse da nord e poi continua in senso orario, * quindi le direzioni in diagonale sono quelle dispari */ switch ( direction ) { case 0: dirx = 0; diry = 1; break; /* nord */ case 1: dirx = 1; diry = 1; break; /* nordest */ case 2: dirx = 1; diry = 0; break; /* est */ case 3: dirx = -1; diry = 1; break; /* sudest */ case 4: dirx = -1; diry = 0; break; /* sud */ case 5: dirx = -1; diry = -1; break; /* sudovest */ case 6: dirx = 0; diry = -1; break; /* ovest */ case 7: dirx = 1; diry = -1; break; /* nordovest */ } /* Aumenta poco a poco il raggio di controllo nella direzione */ for ( len = 1; len < 8; len++ ) { dirx = x + (dirx * len); diry = y + (diry * len); /* Se supera i limiti della scacchiera ignora la ricerca in quella direzione */ if ( dirx < 0 ) break; if ( dirx >= 8 ) break; if ( diry < 0 ) break; if ( diry >= 8 ) break; /* Se il re e il pezzo nella casella controllata hanno lo stesso colore si ferma */ if ( SAME_COLOR(x, y, dirx, diry) ) break; /* La regina si muove in tutte le direzioni, quindi il re è sotto scacco */ if ( board->piece[dirx][diry] == PIECE_QUEEN ) count++; /* L'alfiere si muove nelle diagonali */ if ( board->piece[dirx][diry] == PIECE_BISHOP && (direction%2 == 1) ) count++; /* Mentre la torre nelle direzioni orizzonatali e verticali */ if ( board->piece[dirx][diry] == PIECE_BISHOP && (direction%2 == 0) ) count++; /* Se c'è qualche altro pezzo nel controllo della direzione si ferma */ if ( board->piece[dirx][diry] != PIECE_NONE ) break; } } return count; }