inline void promoteMoveUndo(Position* position, const Move move, const guint promote){ guint from = moveGetFrom(move); guint to = moveGetTo(move); guint piece, pPiece, capture, color; if(to>a4){ color = White; piece = White_Pawn; pPiece = promote + White; } else{ color = Black; piece = Black_Pawn; pPiece = promote + Black; } guint64 bitFrom = 1ull<<from; guint64 bitTo = 1ull<<to; position->piece[color] ^= bitFrom | bitTo; position->piece[piece] ^= bitFrom; position->piece[pPiece] ^= bitTo; position->allPieces ^= bitFrom | bitTo; position->type[from] = piece; position->type[to] = Empty; capture = position->capture; if(capture != Empty){ position->type[to] = capture; position->piece[color^1] ^= bitTo; position->piece[capture] ^= bitTo; position->allPieces ^= bitTo; } }
inline void enPassantMoveUndo(Position* position, const Move move){ guint piece, capture, cSquare, color; guint from = moveGetFrom(move); guint to = moveGetTo(move); if(to < a4){ color = Black; piece = Black_Pawn; capture = White_Pawn; cSquare = to+8; } else{ color = White; piece = White_Pawn; capture = Black_Pawn; cSquare = to-8; } guint64 bitMove = 1ull<<from | 1ull<<to; guint64 bitCapture = 1ull<<cSquare; position->piece[color] ^= bitMove; position->piece[piece] ^= bitMove; position->piece[color^1] ^= bitCapture; position->piece[capture] ^= bitCapture; position->allPieces ^= bitMove | bitCapture; position->type[from] = piece; position->type[to] = Empty; position->type[cSquare] = capture; }
inline void enPassantMoveDo(Position* position, const Move move){ guint piece, capture, cSquare, color; guint from = moveGetFrom(move); guint to = moveGetTo(move); if(to < a4){ color = Black; piece = Black_Pawn; capture = White_Pawn; cSquare = to+8; } else{ color = White; piece = White_Pawn; capture = Black_Pawn; cSquare = to-8; } guint64 bitMove = 1ull<<from | 1ull<<to; guint64 bitCapture = 1ull<<cSquare; position->piece[color] ^= bitMove; position->piece[piece] ^= bitMove; position->piece[color^1] ^= bitCapture; position->piece[capture] ^= bitCapture; position->allPieces ^= bitMove | bitCapture; position->key ^= squareKey[piece][from] ^ squareKey[piece][to] ^ squareKey[capture][cSquare]; position->type[from] = Empty; position->type[to] = piece; position->type[cSquare] = Empty; position->pvt[Opening] += pvt[piece][to][Opening]-pvt[piece][from][Opening]-pvt[capture][cSquare][Opening]; position->pvt[Endgame] += pvt[piece][to][Endgame]-pvt[piece][from][Endgame]-pvt[capture][cSquare][Endgame]; position->material[color^1] -= Pawn_Value; position->staticMoves = 0; }
inline void normalMoveUndo(Position* position, const Move move){ guint from = moveGetFrom(move); guint to = moveGetTo(move); guint piece = position->type[to]; guint color = piece % 2; guint64 bitMove = 1ull << from | 1ull << to; position->piece[color] ^= bitMove; position->piece[piece] ^= bitMove; position->allPieces ^= bitMove; position->type[from] = piece; position->type[to] = Empty; }
inline void captureMoveUndo(Position* position, const Move move){ guint from = moveGetFrom(move); guint to = moveGetTo(move); guint piece = position->type[to]; guint capture = position->capture; guint color = piece % 2; guint64 bitTo = 1ull << to; guint64 bitMove = 1ull<<from | bitTo; position->piece[color] ^= bitMove; position->piece[piece] ^= bitMove; position->piece[color^1] ^= bitTo; position->piece[capture] ^= bitTo; position->allPieces ^= 1ull << from; position->type[from] = piece; position->type[to] = capture; }
inline void castleMoveUndo(Position* position, const Move move){ guint piece, rook, rFrom, rTo, color; guint from = moveGetFrom(move); guint to = moveGetTo(move); if(to < a4){ color = White; piece = White_King; rook = White_Rook; if(to > e1){ rFrom = h1; rTo = f1; } else{ rFrom = a1; rTo = d1; } } else{ color = Black; piece = Black_King; rook = Black_Rook; if(to > e8){ rFrom = h8; rTo = f8; } else{ rFrom = a8; rTo = d8; } } guint64 bitMove = 1ull<<from | 1ull<<to; guint64 bitRook = 1ull<<rFrom | 1ull<<rTo; position->piece[color] ^= bitMove | bitRook; position->piece[piece] ^= bitMove; position->piece[rook] ^= bitRook; position->allPieces ^= bitMove | bitRook; position->type[from] = piece; position->type[to] = Empty; position->type[rFrom] = rook; position->type[rTo] = Empty; }
gint threadSearch(Position* position, gint alpha, gint beta, gint depth, gint hight, const gboolean nullMove, const gboolean nodePV){ Moves moves; Move move, bestMove = Empty, hMove = Empty, pMove=Empty; gboolean extend=FALSE, endGamePhase; gint eval, tmpDepth, movesSearched = 0, pAlpha, pType; guint idleThreads; guint64 key = position->key, hData; HashData* hd; if(stopFlag == TRUE && !ponderSearch) return EVAL_DRAW; searchNodes++; /* Draw */ if(positionRepeat(position) >= 1 || position->staticMoves >= 100) return EVAL_DRAW; /* End game */ gint numberOfPieces = numberOfBits64(position->allPieces); if(numberOfPieces <= 5 && egbbIsLoaded()){ tmpDepth = (2 * iterativeDepth) / 3; if((numberOfPieces <= 4 || hight <= tmpDepth) && (hight >= tmpDepth || positionEvalEG(position))){ if(egbbProbe(position, &eval)){ if(eval < 0) return eval + hight * 40 + positionMaterial(position); if(eval > 0) return eval - hight * 40 + positionMaterial(position); return eval; } } } /* Mate distance pruning */ eval = -EVAL_MATE + hight; if(eval > alpha){ if(eval >= beta) return eval; alpha = eval; } eval = EVAL_MATE - hight; if(eval < beta){ if(eval <= alpha) return eval; beta = eval; } /* Hash */ if(hashFind(&hd,key,&hData)){ hMove = hashMove(hData); if(!nodePV && (gint)hashDepth(hData) >= depth){ if(hashFlag(hData) == EXACT) return hashEval(hData); else if(hashFlag(hData) == ALPHA && hashEval(hData) > alpha){ bestMove = hashMove(hData); alpha = hashEval(hData); if(alpha >= beta) return alpha; } else if(hashFlag(hData) == BETA && hashEval(hData) < beta){ beta = hashEval(hData); if(alpha >= beta) return beta; } } } /* Extension */ if(position->extend || (nodePV && passedPawnMove(position))){ depth ++; extend = TRUE; } /* Horizon */ if(depth < 1){ eval = quiescent(position,alpha,beta,hight+1,TRUE); return eval; } if(position->phase <= 7 && numberOfPieces <= 10) endGamePhase = TRUE; else endGamePhase = FALSE; /* Null move pruning */ if (!nodePV && nullMove && depth>2 && !extend && !endGamePhase){ if(depth > 6) tmpDepth = depth - 4; else tmpDepth = depth - 3; moveDo(position,Null_Move); eval = -threadSearch(position,-beta,-beta+1,tmpDepth,hight+1,FALSE,FALSE); moveUndo(position); if(eval >= beta){ hashWrite(hd,key,depth,eval,ALPHA,Empty); return eval; } } /* Internal Iterative Deepening */ tmpDepth = depth/2; if(nodePV && hMove == Empty && depth > 3 && tmpDepth >= (gint)hashDepth(hData)){ threadSearch(position,alpha, beta, tmpDepth, hight, FALSE,nodePV); if(hashFind2(hd,key,&hData)) hMove = hashMove(hData); } /* First move */ moves.state = START; if(hMove != Empty){ move = hMove; moveDo(position,move); } else move = nextMoveDo(position,&moves); if(move != Empty){ eval = -threadSearch(position, -beta, -alpha, depth-1, hight+1, TRUE,nodePV); if(eval > alpha){ if(eval >= beta){ moveUndo(position); if(moves.state == STATIC) history[moveGetFrom(move)][moveGetTo(move)] += 1<<depth; hashWrite(hd,key,depth,eval,ALPHA,move); return eval; } alpha = eval; bestMove = move; } moveUndo(position); movesSearched ++; } /* Parallel search*/ idleThreads = searchThreads; while(TRUE){ if(idleThreads > 0){ move = nextMoveDo(position,&moves); /* Last moves searched sequential */ if(move == Empty){ parallelStopFlag = TRUE; moves.size = moves.next = 0; while(idleThreads != searchThreads){ parallelSearchResult(&pMove,&pAlpha,&pType); idleThreads++; moves.move[moves.size] = pMove; moves.size ++; } parallelStopFlag = FALSE; moves.toSort = moves.size; break; } /* History pruning */ if(!nodePV && movesSearched >= HistoryFullDepthMoves && depth > HistoryReductionLimit && !extend && !position->extend){ idleThreads--; parallelSearch(position, move, -(alpha+1), -alpha, depth-2, hight+1,TRUE,HP,FALSE); moveUndo(position); movesSearched ++; } else{ /* PVS */ idleThreads--; parallelSearch(position, move, -(alpha+1), -alpha, depth-1, hight+1,TRUE,PVS,FALSE); moveUndo(position); movesSearched ++; } } else{ eval = -parallelSearchResult(&pMove,&pAlpha,&pType); idleThreads++; pAlpha = -pAlpha - 1; if(pType == HP && eval > pAlpha){ /* HP */ idleThreads--; moveDo(position,pMove); parallelSearch(position, pMove, -(pAlpha+1), -pAlpha, depth-1, hight+1,TRUE,PVS,FALSE); moveUndo(position); continue; } if(pType == PVS && eval > pAlpha && eval < beta){ /* PVS research */ idleThreads--; moveDo(position,pMove); parallelSearch(position, pMove, -beta, -pAlpha, depth-1, hight+1,TRUE,RPVS,nodePV); moveUndo(position); continue; } if(eval > alpha){ if(eval >= beta){ parallelSearchStop(idleThreads); if(moveGetType(pMove) == Normal) history[moveGetFrom(pMove)][moveGetTo(pMove)] += 1<<depth; hashWrite(hd,key,depth,eval,ALPHA,pMove); return eval; } alpha = eval; bestMove = pMove; } } } /* Last moves searched sequential */ move = nextMoveDo(position,&moves); while(move != Empty){ /* History pruning */ if(!nodePV && movesSearched >= HistoryFullDepthMoves && depth > HistoryReductionLimit && !extend && !position->extend){ eval = -threadSearch(position, -(alpha+1), -alpha, depth-2, hight+1, TRUE, FALSE); } else eval = alpha + 1; /* PVS */ if(eval > alpha){ eval = -threadSearch(position, -(alpha+1), -alpha, depth-1, hight+1, TRUE, FALSE); if(eval > alpha && eval < beta) eval = -threadSearch(position, -beta, -alpha, depth-1, hight+1, TRUE, nodePV); } moveUndo(position); if(eval > alpha){ if(eval >= beta){ if(moveGetType(pMove) == Normal) history[moveGetFrom(move)][moveGetTo(move)] += 1<<depth; hashWrite(hd,key,depth,eval,ALPHA,move); return eval; } alpha = eval; bestMove = move; } movesSearched ++; move = nextMoveDo(position,&moves); } /* Mate or pat */ if(movesSearched == 0){ if(position->inCheck == TRUE){ eval = -EVAL_MATE+hight; hashWrite(hd,key,depth,eval,EXACT,Empty); return eval; } else{ hashWrite(hd,key,depth,EVAL_DRAW,EXACT,Empty); return EVAL_DRAW; } } /* hash is update */ if(bestMove != Empty) hashWrite(hd,key,depth,alpha,EXACT,bestMove); else hashWrite(hd,key,depth,alpha,BETA,hMove); return alpha; }
inline void promoteMoveDo(Position* position, const Move move, const guint promote){ guint from = moveGetFrom(move); guint to = moveGetTo(move); guint piece, pPiece, capture, color; capture = position->type[to]; if(to>a4){ color = White; piece = White_Pawn; pPiece = promote + White; } else{ color = Black; piece = Black_Pawn; pPiece = promote + Black; } guint64 bitFrom = 1ull<<from; guint64 bitTo = 1ull<<to; position->piece[color] ^= bitFrom | bitTo; position->piece[piece] ^= bitFrom; position->piece[pPiece] ^= bitTo; position->allPieces ^= bitFrom | bitTo; position->key ^= squareKey[piece][from] ^ squareKey[pPiece][to]; position->type[from] = Empty; position->type[to] = pPiece; position->pvt[Opening] += pvt[pPiece][to][Opening] - pvt[piece][from][Opening]; position->pvt[Endgame] += pvt[pPiece][to][Endgame] - pvt[piece][from][Endgame]; position->material[color] += pieceValue[pPiece] - Pawn_Value; position->staticMoves = 0; position->phase += piecePhase[promote]; if(capture != Empty){ if(color == White){ if(position->castle & BLACK_CASTLE){ if(position->castle & BLACK_KING_CASTLE){ if(to == h8){ position->key ^= castleKey[Black_King_Castle]; position->castle &= ~BLACK_KING_CASTLE; } } if(position->castle & BLACK_QUEEN_CASTLE){ if(to == a8){ position->key ^= castleKey[Black_Queen_Castle]; position->castle &= ~BLACK_QUEEN_CASTLE; } } } } else{ if(position->castle & WHITE_CASTLE){ if(position->castle & WHITE_KING_CASTLE){ if(to == h1){ position->key ^= castleKey[White_King_Castle]; position->castle &= ~WHITE_KING_CASTLE; } } if(position->castle & WHITE_QUEEN_CASTLE){ if(to == a1){ position->key ^= castleKey[White_Queen_Castle]; position->castle &= ~WHITE_QUEEN_CASTLE; } } } } position->capture = capture; position->piece[color^1] ^= bitTo; position->piece[capture] ^= bitTo; position->allPieces ^= bitTo; position->key ^= squareKey[capture][to]; position->pvt[Opening] -= pvt[capture][to][Opening]; position->pvt[Endgame] -= pvt[capture][to][Endgame]; position->material[color^1] -= pieceValue[capture]; position->extend = TRUE; } }
inline gboolean castleMoveDo(Position* position, const Move move){ guint piece, rook, rFrom, rTo, color; guint from = moveGetFrom(move); guint to = moveGetTo(move); if(to < a4){ if(to > e1){ if(!whiteCastleKingSide(position)) return FALSE; rFrom = h1; rTo = f1; } else{ if(!whiteCastleQueenSide(position)) return FALSE; rFrom = a1; rTo = d1; } if(position->castle & WHITE_KING_CASTLE){ position->key^= castleKey[White_King_Castle]; position->castle &= ~WHITE_KING_CASTLE; } if(position->castle & WHITE_QUEEN_CASTLE){ position->key^= castleKey[White_Queen_Castle]; position->castle &= ~WHITE_QUEEN_CASTLE; } color = White; piece = White_King; rook = White_Rook; } else{ if(to > e8){ if(!blackCastleKingSide(position)) return FALSE; rFrom = h8; rTo = f8; } else{ if(!blackCastleQueenSide(position)) return FALSE; rFrom = a8; rTo = d8; } if(position->castle & BLACK_KING_CASTLE){ position->key^= castleKey[Black_King_Castle]; position->castle &= ~BLACK_KING_CASTLE; } if(position->castle & BLACK_QUEEN_CASTLE){ position->key^= castleKey[Black_Queen_Castle]; position->castle &= ~BLACK_QUEEN_CASTLE; } color = Black; piece = Black_King; rook = Black_Rook; } guint64 bitMove = 1ull<<from | 1ull<<to; guint64 bitRook = 1ull<<rFrom | 1ull<<rTo; position->piece[color] ^= bitMove | bitRook; position->piece[piece] ^= bitMove; position->piece[rook] ^= bitRook; position->allPieces ^= bitMove | bitRook; position->key^=squareKey[piece][from]^squareKey[piece][to]^squareKey[rook][rFrom]^squareKey[rook][rTo]; position->type[from] = Empty; position->type[to] = piece; position->type[rFrom] = Empty; position->type[rTo] = rook; position->pvt[Opening] += pvt[piece][to][Opening]-pvt[piece][from][Opening] + pvt[rook][rTo][Opening]-pvt[rook][rFrom][Opening]; position->pvt[Endgame] += pvt[piece][to][Endgame]-pvt[piece][from][Endgame] + pvt[rook][rTo][Endgame]-pvt[rook][rFrom][Endgame]; position->staticMoves = 0; return TRUE; }
inline void captureMoveDo(Position* position, const Move move){ guint from = moveGetFrom(move); guint to = moveGetTo(move); guint piece = position->type[from]; guint capture = position->type[to]; guint color = piece % 2; guint64 bitTo = 1ull << to; guint64 bitMove = 1ull<<from | bitTo; position->piece[color] ^= bitMove; position->piece[piece] ^= bitMove; position->piece[color^1] ^= bitTo; position->piece[capture] ^= bitTo; position->allPieces ^= 1ull<<from; position->key ^= squareKey[piece][from] ^ squareKey[piece][to] ^ squareKey[capture][to]; position->type[from] = Empty; position->type[to] = piece; position->pvt[Opening] += pvt[piece][to][Opening] - pvt[piece][from][Opening] - pvt[capture][to][Opening]; position->pvt[Endgame] += pvt[piece][to][Endgame] - pvt[piece][from][Endgame] - pvt[capture][to][Endgame]; position->material[color^1] -= pieceValue[capture]; position->staticMoves = 0; position->capture = capture; position->phase -= piecePhase[capture]; if(color == White){ if(piece == White_Pawn && to >= a7) position->extend = TRUE; if(position->castle & WHITE_CASTLE){ if(position->castle & WHITE_KING_CASTLE){ if(from == e1 || from == h1){ position->key ^= castleKey[White_King_Castle]; position->castle &= ~WHITE_KING_CASTLE; } } if(position->castle & WHITE_QUEEN_CASTLE){ if(from == e1 || from == a1){ position->key ^= castleKey[White_Queen_Castle]; position->castle &= ~WHITE_QUEEN_CASTLE; } } } if(position->castle & BLACK_CASTLE){ if(position->castle & BLACK_KING_CASTLE){ if(to == h8){ position->key ^= castleKey[Black_King_Castle]; position->castle &= ~BLACK_KING_CASTLE; } } if(position->castle & BLACK_QUEEN_CASTLE){ if(to == a8){ position->key ^= castleKey[Black_Queen_Castle]; position->castle &= ~BLACK_QUEEN_CASTLE; } } } } else{ if(piece == Black_Pawn && to <= h2) position->extend = TRUE; if(position->castle & BLACK_CASTLE){ if(position->castle & BLACK_KING_CASTLE){ if(from == e8 || from == h8){ position->key ^= castleKey[Black_King_Castle]; position->castle &= ~BLACK_KING_CASTLE; } } if(position->castle & BLACK_QUEEN_CASTLE){ if(from == e8 || from == a8){ position->key ^= castleKey[Black_Queen_Castle]; position->castle &= ~BLACK_QUEEN_CASTLE; } } } if(position->castle & WHITE_CASTLE){ if(position->castle & WHITE_KING_CASTLE){ if(to == h1){ position->key ^= castleKey[White_King_Castle]; position->castle &= ~WHITE_KING_CASTLE; } } if(position->castle & WHITE_QUEEN_CASTLE){ if(to == a1){ position->key ^= castleKey[White_Queen_Castle]; position->castle &= ~WHITE_QUEEN_CASTLE; } } } } }
inline void normalMoveDo(Position* position, const Move move){ guint from = moveGetFrom(move); guint to = moveGetTo(move); guint piece = position->type[from]; guint color = piece % 2; guint64 bitMove = 1ull << from | 1ull << to; position->piece[color] ^= bitMove; position->piece[piece] ^= bitMove; position->allPieces ^= bitMove; position->key ^= squareKey[piece][from] ^ squareKey[piece][to]; position->type[from] = Empty; position->type[to] = piece; position->pvt[Opening] += pvt[piece][to][Opening] - pvt[piece][from][Opening]; position->pvt[Endgame] += pvt[piece][to][Endgame] - pvt[piece][from][Endgame]; if(color == White){ if(piece == White_Pawn){ position->staticMoves = 0; if(to - from == 16 && (position->piece[Black_Pawn] & ((1ull<<(to+1)) | (1ull<<(to-1))))){ position->enPassant = to - 8; position->key ^= enPassantKey[file(position->enPassant)]; } if(to >= a7) position->extend = TRUE; } if(position->castle & WHITE_CASTLE){ if(position->castle & WHITE_KING_CASTLE){ if(from == e1 || from == h1){ position->key ^= castleKey[White_King_Castle]; position->castle &= ~WHITE_KING_CASTLE; } } if(position->castle & WHITE_QUEEN_CASTLE){ if(from == e1 || from == a1){ position->key ^= castleKey[White_Queen_Castle]; position->castle &= ~WHITE_QUEEN_CASTLE; } } } } else{ if(piece == Black_Pawn){ position->staticMoves = 0; if(from - to == 16 && (position->piece[White_Pawn] & ((1ull<<(to+1)) | (1ull<<(to-1))))){ position->enPassant = to + 8; position->key ^= enPassantKey[file(position->enPassant)]; } if(to <= h2) position->extend = TRUE; } if(position->castle & BLACK_CASTLE){ if(position->castle & BLACK_KING_CASTLE){ if(from == e8 || from == h8){ position->key ^= castleKey[Black_King_Castle]; position->castle &= ~BLACK_KING_CASTLE; } } if(position->castle & BLACK_QUEEN_CASTLE){ if(from == e8 || from == a8){ position->key ^= castleKey[Black_Queen_Castle]; position->castle &= ~BLACK_QUEEN_CASTLE; } } } } }