//********************************************************* // /// <summary> /// Do the move (without log) /// </summary> /// <param name="movePos"> Move to do</param> /// <returns> /// NoRepeat No repetition /// ThreeFoldRepeat Three times the same board /// FiftyRuleRepeat Fifty moves without pawn move or piece eaten /// </returns> // //********************************************************* public RepeatResultE DoMoveNoLog(MovePosS movePos) { RepeatResultE eRetVal; PieceE ePiece; PieceE eOldPiece; int iOldPiecePos; int iDelta; bool bPawnMoveOrPieceEaten; m_stackPossibleEnPassantAt.Push(m_iPossibleEnPassantAt); m_iPossibleEnPassantAt = 0; ePiece = m_pBoard[movePos.StartPos]; bPawnMoveOrPieceEaten = ((ePiece & PieceE.PieceMask) == PieceE.Pawn) | ((movePos.Type & MoveTypeE.PieceEaten) == MoveTypeE.PieceEaten); switch(movePos.Type & MoveTypeE.MoveTypeMask) { case MoveTypeE.Castle: UpdatePackedBoardAndZobristKey(movePos.EndPos, ePiece, movePos.StartPos, PieceE.None); m_pBoard[movePos.EndPos] = ePiece; m_pBoard[movePos.StartPos] = PieceE.None; eOldPiece = PieceE.None; if ((ePiece & PieceE.Black) != 0) { if (movePos.EndPos == 57) { UpdatePackedBoardAndZobristKey(58, m_pBoard[56], 56, PieceE.None); m_pBoard[58] = m_pBoard[56]; m_pBoard[56] = PieceE.None; } else { UpdatePackedBoardAndZobristKey(60, m_pBoard[63], 63, PieceE.None); m_pBoard[60] = m_pBoard[63]; m_pBoard[63] = PieceE.None; } m_bBlackCastle = true; m_iBlackKingPos = movePos.EndPos; } else { if (movePos.EndPos == 1) { UpdatePackedBoardAndZobristKey(2, m_pBoard[0], 0, PieceE.None); m_pBoard[2] = m_pBoard[0]; m_pBoard[0] = PieceE.None; } else { UpdatePackedBoardAndZobristKey(4, m_pBoard[7], 7, PieceE.None); m_pBoard[4] = m_pBoard[7]; m_pBoard[7] = PieceE.None; } m_bWhiteCastle = true; m_iWhiteKingPos = movePos.EndPos; } break; case MoveTypeE.EnPassant: UpdatePackedBoardAndZobristKey(movePos.EndPos, ePiece, movePos.StartPos, PieceE.None); m_pBoard[movePos.EndPos] = ePiece; m_pBoard[movePos.StartPos] = PieceE.None; iOldPiecePos = (movePos.StartPos & 56) + (movePos.EndPos & 7); eOldPiece = m_pBoard[iOldPiecePos]; UpdatePackedBoardAndZobristKey(iOldPiecePos, PieceE.None); m_pBoard[iOldPiecePos] = PieceE.None; m_piPiecesCount[(int)eOldPiece]--; break; default: // Normal // PawnPromotionTo??? eOldPiece = m_pBoard[movePos.EndPos]; switch(movePos.Type & MoveTypeE.MoveTypeMask) { case MoveTypeE.PawnPromotionToQueen: m_piPiecesCount[(int)ePiece]--; ePiece = PieceE.Queen | (ePiece & PieceE.Black); m_piPiecesCount[(int)ePiece]++; break; case MoveTypeE.PawnPromotionToRook: m_piPiecesCount[(int)ePiece]--; ePiece = PieceE.Rook | (ePiece & PieceE.Black); m_piPiecesCount[(int)ePiece]++; break; case MoveTypeE.PawnPromotionToBishop: m_piPiecesCount[(int)ePiece]--; ePiece = PieceE.Bishop | (ePiece & PieceE.Black); m_piPiecesCount[(int)ePiece]++; break; case MoveTypeE.PawnPromotionToKnight: m_piPiecesCount[(int)ePiece]--; ePiece = PieceE.Knight | (ePiece & PieceE.Black); m_piPiecesCount[(int)ePiece]++; break; case MoveTypeE.PawnPromotionToPawn: default: break; } UpdatePackedBoardAndZobristKey(movePos.EndPos, ePiece, movePos.StartPos, PieceE.None); m_pBoard[movePos.EndPos] = ePiece; m_pBoard[movePos.StartPos] = PieceE.None; m_piPiecesCount[(int)eOldPiece]--; switch(ePiece) { case PieceE.King | PieceE.Black: m_iBlackKingPos = movePos.EndPos; if (movePos.StartPos == 59) { m_iBlackKingMoveCount++; } break; case PieceE.King: m_iWhiteKingPos = movePos.EndPos; if (movePos.StartPos == 3) { m_iWhiteKingMoveCount++; } break; case PieceE.Rook | PieceE.Black: if (movePos.StartPos == 56) { m_iLBlackRookMoveCount++; } else if (movePos.StartPos == 63) { m_iRBlackRookMoveCount++; } break; case PieceE.Rook: if (movePos.StartPos == 0) { m_iLWhiteRookMoveCount++; } else if (movePos.StartPos == 7) { m_iRWhiteRookMoveCount++; } break; case PieceE.Pawn: case PieceE.Pawn | PieceE.Black: iDelta = movePos.StartPos - movePos.EndPos; if (iDelta == -16 || iDelta == 16) { m_iPossibleEnPassantAt = movePos.EndPos; } break; } break; } m_moveHistory.UpdateCurrentPackedBoard(ComputeBoardExtraInfo(PlayerColorE.White, false)); eRetVal = m_moveHistory.AddCurrentPackedBoard(m_i64ZobristKey, bPawnMoveOrPieceEaten); m_eNextMoveColor = (m_eNextMoveColor == PlayerColorE.White) ? PlayerColorE.Black : PlayerColorE.White; return(eRetVal); }
//********************************************************* // /// <summary> /// Find a move from the opening book /// </summary> /// <param name="searchMode"> Search mode</param> /// <param name="ePlayerColor"> Color doing the move</param> /// <param name="arrPrevMove"> Previous move</param> /// <param name="move"> Found move</param> /// <returns> /// true if succeed, false if no move found in book /// </returns> // //********************************************************* public bool FindBookMove(SearchEngine.SearchMode searchMode, PlayerColorE ePlayerColor, MovePosS[] arrPrevMove, out ChessBoard.MovePosS move) { bool bRetVal; int iMove; Random rnd; if (searchMode.m_eRandomMode == SearchEngine.SearchMode.RandomModeE.Off) { rnd = null; } else if (searchMode.m_eRandomMode == SearchEngine.SearchMode.RandomModeE.OnRepetitive) { rnd = m_rndRep; } else { rnd = m_rnd; } move.OriginalPiece = PieceE.None; move.StartPos = 255; move.EndPos = 255; move.Type = ChessBoard.MoveTypeE.Normal; iMove = m_book.FindMoveInBook(arrPrevMove, rnd); if (iMove == -1) { bRetVal = false; } else { move = FindIfValid(ePlayerColor, iMove & 255, iMove >> 8); move.Type |= MoveTypeE.MoveFromBook; bRetVal = (move.StartPos != 255); } return(bRetVal); }
//********************************************************* // /// <summary> /// Do the move /// </summary> /// <param name="movePos"> Move to do</param> /// <returns> /// NoRepeat No repetition /// ThreeFoldRepeat Three times the same board /// FiftyRuleRepeat Fifty moves without pawn move or piece eaten /// </returns> // //********************************************************* public MoveResultE DoMove(MovePosS movePos) { MoveResultE eRetVal; switch(DoMoveNoLog(movePos)) { case RepeatResultE.ThreeFoldRepeat: eRetVal = MoveResultE.ThreeFoldRepeat; break; case RepeatResultE.FiftyRuleRepeat: eRetVal = MoveResultE.FiftyRuleRepeat; break; default: eRetVal = CheckNextMove(); break; } m_moveStack.AddMove(movePos); return(eRetVal); }
//********************************************************* // /// <summary> /// Find the best move for a player using alpha-beta pruning or minmax search /// </summary> /// <param name="searchMode"> Search mode</param> /// <param name="ePlayerColor"> Color doing the move</param> /// <param name="moveBest"> Best move found</param> /// <param name="iPermCount"> Total permutation evaluated</param> /// <param name="iCacheHit"> Number of moves found in the translation table cache</param> /// <param name="iMaxDepth"> Maximum depth reached</param> /// <returns> /// true if a move has been found /// </returns> // //********************************************************* public bool FindBestMove(SearchEngine.SearchMode searchMode, PlayerColorE ePlayerColor, out MovePosS moveBest, out int iPermCount, out int iCacheHit, out int iMaxDepth) { bool bRetVal; bool bUseAlphaBeta; SearchEngine searchEngine; bUseAlphaBeta = ((searchMode.m_eOption & SearchEngine.SearchMode.OptionE.UseAlphaBeta) != 0); searchEngine = bUseAlphaBeta ? (SearchEngine)m_searchEngineAlphaBeta : (SearchEngine)m_searchEngineMinMax; bRetVal = searchEngine.FindBestMove(this, searchMode, ePlayerColor, out moveBest, out iPermCount, out iCacheHit, out iMaxDepth); return(bRetVal); }
//********************************************************* // /// <summary> /// Undo a move (without no log) /// </summary> /// <param name="movePos"> Move to undo</param> // //********************************************************* public void UndoMoveNoLog(MovePosS movePos) { PieceE ePiece; PieceE eOriginalPiece; int iOldPiecePos; m_moveHistory.RemoveLastMove(m_i64ZobristKey); ePiece = m_pBoard[movePos.EndPos]; switch(movePos.Type & MoveTypeE.MoveTypeMask) { case MoveTypeE.Castle: UpdatePackedBoardAndZobristKey(movePos.StartPos, ePiece, movePos.EndPos, PieceE.None); m_pBoard[movePos.StartPos] = ePiece; m_pBoard[movePos.EndPos] = PieceE.None; if ((ePiece & PieceE.Black) != 0) { if (movePos.EndPos == 57) { UpdatePackedBoardAndZobristKey(56, m_pBoard[58], 58, PieceE.None); m_pBoard[56] = m_pBoard[58]; m_pBoard[58] = PieceE.None; } else { UpdatePackedBoardAndZobristKey(63, m_pBoard[60], 60, PieceE.None); m_pBoard[63] = m_pBoard[60]; m_pBoard[60] = PieceE.None; } m_bBlackCastle = false; m_iBlackKingPos = movePos.StartPos; } else { if (movePos.EndPos == 1) { UpdatePackedBoardAndZobristKey(0, m_pBoard[2], 2, PieceE.None); m_pBoard[0] = m_pBoard[2]; m_pBoard[2] = PieceE.None; } else { UpdatePackedBoardAndZobristKey(7, m_pBoard[4], 4, PieceE.None); m_pBoard[7] = m_pBoard[4]; m_pBoard[4] = PieceE.None; } m_bWhiteCastle = false; m_iWhiteKingPos = movePos.StartPos; } break; case MoveTypeE.EnPassant: UpdatePackedBoardAndZobristKey(movePos.StartPos, ePiece, movePos.EndPos, PieceE.None); m_pBoard[movePos.StartPos] = ePiece; m_pBoard[movePos.EndPos] = PieceE.None; eOriginalPiece = PieceE.Pawn | (((ePiece & PieceE.Black) == 0) ? PieceE.Black : PieceE.White); iOldPiecePos = (movePos.StartPos & 56) + (movePos.EndPos & 7); UpdatePackedBoardAndZobristKey(iOldPiecePos, eOriginalPiece); m_pBoard[iOldPiecePos] = eOriginalPiece; m_piPiecesCount[(int)eOriginalPiece]++; break; default: // Normal // PawnPromotionTo??? eOriginalPiece = movePos.OriginalPiece; switch(movePos.Type & MoveTypeE.MoveTypeMask) { case MoveTypeE.PawnPromotionToQueen: case MoveTypeE.PawnPromotionToRook: case MoveTypeE.PawnPromotionToBishop: case MoveTypeE.PawnPromotionToKnight: m_piPiecesCount[(int)ePiece]--; ePiece = PieceE.Pawn | (ePiece & PieceE.Black); m_piPiecesCount[(int)ePiece]++; break; case MoveTypeE.PawnPromotionToPawn: default: break; } UpdatePackedBoardAndZobristKey(movePos.StartPos, ePiece, movePos.EndPos, eOriginalPiece); m_pBoard[movePos.StartPos] = ePiece; m_pBoard[movePos.EndPos] = eOriginalPiece; m_piPiecesCount[(int)eOriginalPiece]++; switch(ePiece) { case PieceE.King | PieceE.Black: m_iBlackKingPos = movePos.StartPos; if (movePos.StartPos == 59) { m_iBlackKingMoveCount--; } break; case PieceE.King: m_iWhiteKingPos = movePos.StartPos; if (movePos.StartPos == 3) { m_iWhiteKingMoveCount--; } break; case PieceE.Rook | PieceE.Black: if (movePos.StartPos == 56) { m_iLBlackRookMoveCount--; } else if (movePos.StartPos == 63) { m_iRBlackRookMoveCount--; } break; case PieceE.Rook: if (movePos.StartPos == 0) { m_iLWhiteRookMoveCount--; } else if (movePos.StartPos == 7) { m_iRWhiteRookMoveCount--; } break; } break; } m_iPossibleEnPassantAt = m_stackPossibleEnPassantAt.Pop(); m_eNextMoveColor = (m_eNextMoveColor == PlayerColorE.White) ? PlayerColorE.Black : PlayerColorE.White; }