Пример #1
0
int __generateSimpleMove(ChessMoveGenerator* self, ChessPiece* piece, 
    int dRank, int dFile, int validate){
    //returns 1 if the move was succesfull, 
    //0 if it failed because of check, 
    //and -1 if it failed because it was out of bounds/blocked
    ChessPiece* capture;
    int rank, file;
    location_t to;
    move_t move;
    rank = GET_RANK(piece->location)+dRank;
    file = GET_FILE(piece->location)+dFile;
    //if the move is in the board (0<=rank<8)&&(0<=file<8)
    if(((rank&7)==rank) && ((file&7)==file)){
        to = RANK_FILE(rank,file);
        move = NEW_MOVE(piece->location, to);
        capture = self->board->squares[to];
        if((capture!=NULL) && ((capture->color) != (self->toPlay)))
            move|=CAPTURE_MOVE_FLAG;
        else if(capture!=NULL)
            return -1; //the same color
        ChessBoard_makeMove(self->board, move);
        if(__finalizeAndUndo(self, validate)) return 1;
        else return 0;
    }
    return -1;
}
Пример #2
0
char __getChar(ChessBoard* self, location_t loc){
    assert(self!=NULL);
    assert(0<=loc);
    assert(loc<64);
    ChessPiece* piece = self->squares[loc];
    if(piece==NULL)
        return ((GET_RANK(loc)^GET_FILE(loc))%2)?' ':'+';
    return __getPieceChar(piece);
}
Пример #3
0
void __generatePawnMoves(ChessMoveGenerator* self){
    int i, rank, file;
    assert(self!=NULL);
    assert(self->curSet!=NULL);
    int size = self->curSet->piecesCounts[PAWN_INDEX];
    int pawnDirection = self->toPlay==WHITE?1:-1;
    int pawnHomeRank = self->toPlay==WHITE?1:6;
    int lastRank = self->toPlay==WHITE?6:1;
    ChessPiece* pawn;
    move_t move;
    location_t to;
    //since the order of the pawns might change in the set
    //durring operations, we must store a local copy
    ChessPiece** pawns = (ChessPiece**)malloc(
        sizeof(ChessPiece*)*size);
    memcpy(pawns, self->curSet->piecesByType[PAWN_INDEX], 
        sizeof(ChessPiece*)*size);
    for(i=0;i<size;i++){
        pawn = pawns[i];
        rank = GET_RANK(pawn->location);
        file = GET_FILE(pawn->location);
        //try to move forward
        to = RANK_FILE(rank+pawnDirection, file);
        if(self->board->squares[to]==NULL){
            move = NEW_MOVE(pawn->location,to);
            if(rank==lastRank){
                //generate promotions
                __generatePawnPromotions(self, move);
            }
            else{
                //generate regular forward push
                ChessBoard_makeMove(self->board, move);
                if((__finalizeAndUndo(self, 1)||self->inCheck)
                        && pawnHomeRank==rank){
                    to = RANK_FILE(rank+pawnDirection*2, file);
                    if(self->board->squares[to]==NULL){
                        move = NEW_MOVE(pawn->location,to);
                        move|=DOUBLE_PAWN_PUSH_MOVE;
                        ChessBoard_makeMove(self->board, move);
                        __finalizeAndUndo(self, self->inCheck);
                    }
                }
            }
        }
        if(file>0){//try to capture left
            __generatePawnCapture(self, rank, file, pawnDirection, -1,
                lastRank);
        }
        if(file<7){//try to capture right
            __generatePawnCapture(self, rank, file, pawnDirection, 1,
                lastRank);
        }
    }//end for 
    free(pawns);
}
Пример #4
0
//Initializes pawn eval masks
void Init_Pawn_Masks(void)
{
	int index,rank,file,rank_index,file_index;

	//Clear all masks;
	for (index = 0; index < 64; index++)
	{
		white_passed_masks[index] = 0;
		black_passed_masks[index] = 0;
		isolated_masks[index] = 0;
		doubled_masks[index] = 0;
	}

	//For each square on the board
	for (index = 0; index < 64; index++)
	{
		rank = GET_RANK(index);
		file = GET_FILE(index);
		for (rank_index = RANK_1; rank_index <= RANK_8; rank_index++)
		{
			for (file_index = FILE_A; file_index <= FILE_H; file_index++)
			{
				//white passed mask
				//If file is neighboring and space is above index
				if (abs(file - file_index) <= 1 && rank_index > rank)
				{
					SET_BIT(white_passed_masks[index], RANK_FILE_TO_SQUARE(rank_index, file_index));
				}

				//black passed mask
				//If file is neighboring and space is below index
				if (abs(file - file_index) <= 1 && rank_index < rank)
				{
					SET_BIT(black_passed_masks[index], RANK_FILE_TO_SQUARE(rank_index, file_index));
				}

				//isolated mask
				//If file is neighboring and space is not equal to index
				if (abs(file - file_index) <= 1 && (file != file_index || rank != rank_index))
				{
					SET_BIT(isolated_masks[index], RANK_FILE_TO_SQUARE(rank_index, file_index));
				}

				//Doubled mask
				//If file is the same and rank is different
				if (file == file_index && rank != rank_index)
				{
					SET_BIT(doubled_masks[index], RANK_FILE_TO_SQUARE(rank_index, file_index));
				}
			}
		}
	}

}
Пример #5
0
void __generateDirectionalMoves(ChessMoveGenerator* self, 
    ChessPiece* piece, int dRank, int dFile){
    ChessPiece* capture;
    int rank, file;
    rank = GET_RANK(piece->location)+dRank;
    file = GET_FILE(piece->location)+dFile;
    int validated = 0;
    location_t to;
    move_t move;
    //while inside the board (0<=rank<8 && 0<=file<8)
    while(((rank&7)==rank) && ((file&7)==file)){
        to = RANK_FILE(rank,file);
        capture = self->board->squares[to];
        if(capture==NULL){
            move = NEW_MOVE(piece->location, to);
            ChessBoard_makeMove(self->board, move);
            if(__finalizeAndUndo(self, (!validated)||self->inCheck)){
                if(self->inCheck)
                    break; //move blocks some directional check, 
                           //any further move in this direction 
                           //will not.
                validated = 1;
            }
            else if(!self->inCheck){
                break; //move puts you in check, any move in
                       //this direction will also put you in check
            }
        }
        else if(capture->color != self->toPlay){
            move = NEW_MOVE(piece->location, to)|CAPTURE_MOVE_FLAG;
            ChessBoard_makeMove(self->board, move);
            __finalizeAndUndo(self, self->inCheck||(!validated));
            break;
        }
        else break; //you hit your own piece
        rank+=dRank;
        file+=dFile;
    }
}
Пример #6
0
void ChessBoard_makeMove(ChessBoard* self, move_t move){
    //push the move onto the move stack
    GameInfo* info = (GameInfo*)self->extra;
    BoardBackup* backup = &(info->backups[info->movesCount]);
    backup->hash = self->hash;
    backup->flags = self->flags;
    backup->fiftyMoveCount = self->fiftyMoveCount;
    info->moves[info->movesCount++] = move;
    if(self->flags&TO_PLAY_FLAG) //black
        self->fiftyMoveCount++;
    __toggleToPlay(self);
    __clearEnPassantFlags(self);
    int meta = GET_META(move);
    location_t from = GET_FROM(move);
    location_t to = GET_TO(move);
    if((self->squares[from]->type==PAWN) || (meta&CAPTURE_MOVE_FLAG))
        self->fiftyMoveCount=0;
    int rank, file;
    //do special moves
    switch(meta){
    case DOUBLE_PAWN_PUSH_MOVE:
        __setEnPassantFlags(self, GET_FILE(to));
        break;
    case KING_CASTLE_MOVE:
    case QUEEN_CASTLE_MOVE:
        rank = GET_RANK(from);
        if(meta==KING_CASTLE_MOVE)
            __movePieceByLoc(self, 
                RANK_FILE(rank, 7), RANK_FILE(rank, 5));
        else
            __movePieceByLoc(self, 
                RANK_FILE(rank, 0), RANK_FILE(rank, 3));
        if(rank==0){//white
            __unsetCastleFlag(self, WHITE_KING_CASTLE_FLAG);
            __unsetCastleFlag(self, WHITE_QUEEN_CASTLE_FLAG);
        }
        else{//black
            __unsetCastleFlag(self, BLACK_KING_CASTLE_FLAG);
            __unsetCastleFlag(self, BLACK_QUEEN_CASTLE_FLAG);
        }
        break;
    case EN_PASSANT_MOVE:
        rank = GET_RANK(from);
        file = GET_FILE(to);
        __capturePiece(self, 
            self->squares[RANK_FILE(rank,file)]);
        break;
    default:
        if(meta&CAPTURE_MOVE_FLAG){
            ChessPiece* captured = self->squares[to];
            __capturePiece(self, captured);
            if(captured->type==ROOK){
                switch(to){
                case WHITE_QUEEN_ROOK_START:
                    __unsetCastleFlag(self, WHITE_QUEEN_CASTLE_FLAG);
                    break;
                case WHITE_KING_ROOK_START:
                    __unsetCastleFlag(self, WHITE_KING_CASTLE_FLAG);
                    break;
                case BLACK_QUEEN_ROOK_START:
                    __unsetCastleFlag(self, BLACK_QUEEN_CASTLE_FLAG);
                    break;
                case BLACK_KING_ROOK_START:
                    __unsetCastleFlag(self, BLACK_KING_CASTLE_FLAG);
                    break;
                }
            }
        }
        if(meta&PROMOTION_MOVE_FLAG){
            ChessPiece* piece = self->squares[from];
            __removePiece(self, piece);
            switch(meta&PROMOTION_MASK){
            case QUEEN_PROMOTION:
                piece->type=QUEEN;
                break;
            case ROOK_PROMOTION:
                piece->type=ROOK;
                break;
            case KNIGHT_PROMOTION:
                piece->type=KNIGHT;
                break;
            case BISHOP_PROMOTION:
                piece->type=BISHOP;
                break;
            default:
                assert(0);
            }
            __addPiece(self, piece);
        }
    }
    if(meta==0 || meta==CAPTURE_MOVE_FLAG){
        switch(from){
        case WHITE_QUEEN_ROOK_START:
            __unsetCastleFlag(self, WHITE_QUEEN_CASTLE_FLAG);
            break;
        case WHITE_KING_ROOK_START:
            __unsetCastleFlag(self, WHITE_KING_CASTLE_FLAG);
            break;
        case WHITE_KING_START:
            __unsetCastleFlag(self, WHITE_QUEEN_CASTLE_FLAG);
            __unsetCastleFlag(self, WHITE_KING_CASTLE_FLAG);
            break;
        case BLACK_QUEEN_ROOK_START:
            __unsetCastleFlag(self, BLACK_QUEEN_CASTLE_FLAG);
            break;
        case BLACK_KING_ROOK_START:
            __unsetCastleFlag(self, BLACK_KING_CASTLE_FLAG);
            break;
        case BLACK_KING_START:
            __unsetCastleFlag(self, BLACK_QUEEN_CASTLE_FLAG);
            __unsetCastleFlag(self, BLACK_KING_CASTLE_FLAG);
            break;
        }
    }
    __movePieceByLoc(self, from, to);
}
Пример #7
0
void toAlgebraicNotation(move_t move, ChessBoard* board, char* out, int* outSize){
    location_t from = GET_FROM(move);
    location_t to = GET_TO(move);
    int meta = GET_META(move);
    int i = 0;
    ChessBoard_makeMove(board, move);
    int isInCheck = ChessBoard_testForCheck(board);
    ChessMoveGenerator* gen = ChessMoveGenerator_new(board);
    ChessMoveGenerator_generateMoves(gen, isInCheck, NULL);
    int isInCheckmate = isInCheck&&(gen->nextCount==0);
    ChessBoard_unmakeMove(board);
    ChessMoveGenerator_generateMoves(gen, ChessBoard_testForCheck(board), NULL);

    if(meta==KING_CASTLE_MOVE){
        char* notation = "O-O";
        for(i = 0; i < 3; i++)
            out[i] = notation[i];
    }
    else if(meta==QUEEN_CASTLE_MOVE){
        char* notation = "O-O-O";
        for(i = 0; i < 5; i++)
            out[i] = notation[i];
    }
    else{
        //write piece indicator
        ChessPiece* piece = board->squares[from];
        if(piece->type==KING)
            out[i++] = 'K';
        else{
            //for each other move,
            //check to see if there are multiple pieces
            //of this piece's type that can move to the 'to' square.
            int j;
            move_t otherMoves[20];
            int otherMovesCount = 0;
            move_t otherMove;
            for(j = 0; j < gen->nextCount; j++){
                otherMove = gen->next[j];
                if((GET_TO(otherMove)==to) && 
                    (GET_FROM(otherMove)!=from) &&
                    (board->squares[GET_FROM(otherMove)]->type==
                    piece->type)){
                    if(piece->type==PAWN &&
                        (move&CAPTURE_MOVE_FLAG)!=
                        (otherMove&CAPTURE_MOVE_FLAG))
                        continue;
                    if(otherMove==move)
                        continue;
                    otherMoves[otherMovesCount++] = otherMove;
                }
            }
            //note if there are multiple moves 
            //from the same rank or file
            int sameRank = 0, sameFile = 0;
            for(j = 0; j < otherMovesCount; j++){
                otherMove = otherMoves[j];
                if(GET_RANK(from)==GET_RANK(GET_FROM(otherMove)))
                    sameRank = 1;
                if(GET_FILE(from)==GET_FILE(GET_FROM(otherMove)))
                    sameFile = 1;
            }
            
            if(piece->type!=PAWN)
                out[i++] = __pieceTypeToChar(piece->type);
            else if(meta&CAPTURE_MOVE_FLAG)
                out[i++] = __fileToChar(GET_FILE(from));
            if(piece->type!=PAWN && otherMovesCount){
                if(!sameFile)
                    out[i++] = __fileToChar(GET_FILE(from));
                else if(!sameRank)
                    out[i++] = __rankToChar(GET_RANK(from));
                else{
                    out[i++] = __fileToChar(GET_FILE(from));
                    out[i++] = __rankToChar(GET_RANK(from));
                }
            }
        }
        //if capture
        if(meta&CAPTURE_MOVE_FLAG)
            out[i++] = 'x';
        //write destination
        out[i++] = __fileToChar(GET_FILE(to));
        out[i++] = __rankToChar(GET_RANK(to));
        if(meta&PROMOTION_MOVE_FLAG){
            out[i++] = '=';
            switch(meta&PROMOTION_MASK){
                case KNIGHT_PROMOTION:
                    out[i++] = 'N';
                    break;
                case BISHOP_PROMOTION:
                    out[i++] = 'B';
                    break;
                case ROOK_PROMOTION:
                    out[i++] = 'R';
                    break;
                case QUEEN_PROMOTION:
                    out[i++] = 'Q';
                    break;
                default:
                    assert(0);
            }
        }
    }
    if(isInCheckmate)
        out[i++] = '#';
    else if(isInCheck)
        out[i++] = '+';
    out[i] = '\0';
    (*outSize) = i;

    ChessMoveGenerator_delete(gen);
}
Пример #8
0
int __testForCheck(ChessBoard* board, color_e color){
    GameInfo* info = (GameInfo*)board->extra;
    ChessPieceSet* pieces = info->pieceSets[color];
    ChessPieceSet* opPieces = info->pieceSets[OTHER_COLOR(color)];
    ChessPiece* king = pieces->piecesByType[TYPE_TO_INT(KING)][0];
    int kingRank, kingFile;
    kingRank = GET_RANK(king->location);
    kingFile = GET_FILE(king->location);
    //test for check by a pawn
    if((color==WHITE && kingRank<6) || (color==BLACK && kingRank>1)){
        int opPawnDirection = color==WHITE?-1:1;
        int pawnRank = kingRank-opPawnDirection;
        ChessPiece* pawn;
        if(kingFile>0){
            pawn = board->squares[RANK_FILE(pawnRank, kingFile-1)];
            if((pawn!=NULL) && (pawn->type==PAWN) && 
                (pawn->color!=color)){
                return 1;
            }
        }
        if(kingFile<7){
            pawn = board->squares[RANK_FILE(pawnRank, kingFile+1)];
            if((pawn!=NULL) && (pawn->type==PAWN) && 
                (pawn->color!=color)){
                return 1;
            }
        }
    }
    //test for check by knight
    int i, rankDelta, fileDelta, rank, file;
    int size = opPieces->piecesCounts[KNIGHT_INDEX];
    ChessPiece* knight;
    for(i=0; i<size; i++){
        knight = opPieces->piecesByType[KNIGHT_INDEX][i];
        rankDelta = kingRank-GET_RANK(knight->location);
        fileDelta = kingFile-GET_FILE(knight->location);
        if((rankDelta*rankDelta+fileDelta*fileDelta)==5)
            return 1;
    }
    //test for check by bishop
    size = opPieces->piecesCounts[BISHOP_INDEX];
    ChessPiece* bishop;
    for(i=0; i<size; i++){
        bishop = opPieces->piecesByType[BISHOP_INDEX][i];
        rankDelta = kingRank-GET_RANK(bishop->location);
        fileDelta = kingFile-GET_FILE(bishop->location);
        if(rankDelta*rankDelta == fileDelta*fileDelta){
            //the king is on a diagonal with this opposing bishop
            //check every square inbetween to see if the bishop 
            //is blocked 
            assert(rankDelta!=0);
            rankDelta = rankDelta>0?1:-1;
            fileDelta = fileDelta>0?1:-1;
            rank = GET_RANK(bishop->location)+rankDelta;
            file = GET_FILE(bishop->location)+fileDelta;
            while(rank!=kingRank){
                if(board->squares[RANK_FILE(rank,file)]!=NULL)
                    break;
                rank+=rankDelta;
                file+=fileDelta;
            }
            if(rank==kingRank)
                return 1;
        }
    }
    //test for check by rook
    size = opPieces->piecesCounts[TYPE_TO_INT(ROOK)];
    ChessPiece* rook;
    for(i=0; i<size; i++){
        rook = opPieces->piecesByType[TYPE_TO_INT(ROOK)][i];
        rankDelta = kingRank-GET_RANK(rook->location);
        fileDelta = kingFile-GET_FILE(rook->location);
        if((rankDelta == 0)||(fileDelta == 0)){
            //the king is on a rank or a file with this opposing rook 
            //check every square inbetween to see if the rook 
            //is blocked 
            if(fileDelta!=0) fileDelta = fileDelta>0?1:-1;
            if(rankDelta!=0) rankDelta = rankDelta>0?1:-1;
            rank = GET_RANK(rook->location)+rankDelta;
            file = GET_FILE(rook->location)+fileDelta;
            while(rank!=kingRank || file!=kingFile){
                if(board->squares[RANK_FILE(rank,file)]!=NULL)
                    break;
                rank+=rankDelta;
                file+=fileDelta;
            }
            if(rank==kingRank && file==kingFile){
                return 1;
            }
        }
    }
    //test for check by queen
    size = opPieces->piecesCounts[TYPE_TO_INT(QUEEN)];
    ChessPiece* queen;
    for(i=0; i<size; i++){
        queen = opPieces->piecesByType[TYPE_TO_INT(QUEEN)][i];
        rankDelta = kingRank-GET_RANK(queen->location);
        fileDelta = kingFile-GET_FILE(queen->location);
        if((rankDelta*rankDelta == fileDelta*fileDelta)||
            (rankDelta == 0)||(fileDelta == 0)){
            //the king is on a diagonal, rank or file with 
            //this opposing queen, check every square
            //inbetween to see if the queen is blocked 
            if(fileDelta!=0) fileDelta = fileDelta>0?1:-1;
            if(rankDelta!=0) rankDelta = rankDelta>0?1:-1;
            rank = GET_RANK(queen->location)+rankDelta;
            file = GET_FILE(queen->location)+fileDelta;
            while(rank!=kingRank || file!=kingFile){
                if(board->squares[RANK_FILE(rank,file)]!=NULL){
                    break;
                }
                rank+=rankDelta;
                file+=fileDelta;
            }
            if(rank==kingRank && file==kingFile){
                return 1;
            }
        }
    }
    //test for check by other king
    //for hypothetical moves that are blocked
    //by the opposing king
    ChessPiece* opKing = opPieces->piecesByType[TYPE_TO_INT(KING)][0];
    rankDelta = kingRank-GET_RANK(opKing->location);
    fileDelta = kingFile-GET_FILE(opKing->location);
    if((rankDelta*rankDelta+fileDelta*fileDelta)<=2){
        return 1;
    }
    //Otherwise, the king is not in check
    return 0;
}
Пример #9
0
//Looks at pawn shielding around each king and returns white - black score
int Get_King_Safety_Score(BOARD_STRUCT *board)
{
	int white_score = 0;
	int black_score = 0;

	U64 temp = board->piece_bitboards[wK];
	int white_king_square = pop_1st_bit(&temp);
	temp = board->piece_bitboards[bK];
	int black_king_square = pop_1st_bit(&temp);

	//White king on kingside
	if (GET_FILE(white_king_square) > FILE_E && GET_RANK(white_king_square) == RANK_1) {

		if (board->board_array[F2] == wP)  white_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[F3] == wP)  white_score += PAWN_SHIELD_SCORE / 2;

		if (board->board_array[G2] == wP)  white_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[G3] == wP)  white_score += PAWN_SHIELD_SCORE / 2;

		if (board->board_array[H2] == wP)  white_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[H3] == wP)  white_score += PAWN_SHIELD_SCORE / 2;
	}
	else if (GET_FILE(white_king_square) < FILE_D && GET_RANK(white_king_square) == RANK_1) {

		if (board->board_array[A2] == wP)  white_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[A3] == wP)  white_score += PAWN_SHIELD_SCORE / 2;

		if (board->board_array[B2] == wP)  white_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[B3] == wP)  white_score += PAWN_SHIELD_SCORE / 2;

		if (board->board_array[C2] == wP)  white_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[C3] == wP)  white_score += PAWN_SHIELD_SCORE / 2;
	}
	

	//Black king on kingside
	if (GET_FILE(black_king_square) > FILE_E && GET_RANK(black_king_square) == RANK_8) {

		if (board->board_array[F7] == bP)  black_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[F6] == bP)  black_score += PAWN_SHIELD_SCORE / 2;

		if (board->board_array[G7] == bP)  black_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[G6] == bP)  black_score += PAWN_SHIELD_SCORE / 2;

		if (board->board_array[H7] == bP)  black_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[H6] == bP)  black_score += PAWN_SHIELD_SCORE / 2;
	}
	else if (GET_FILE(black_king_square) < FILE_D && GET_RANK(black_king_square) == RANK_8) {

		if (board->board_array[A7] == bP)  black_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[A6] == bP)  black_score += PAWN_SHIELD_SCORE / 2;

		if (board->board_array[B7] == bP)  black_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[B6] == bP)  black_score += PAWN_SHIELD_SCORE / 2;

		if (board->board_array[C7] == bP)  black_score += PAWN_SHIELD_SCORE;
		else if (board->board_array[C6] == bP)  black_score += PAWN_SHIELD_SCORE / 2;
	}

	return white_score - black_score;

}