/// <summary> /// Find the best move for a player using a specific method /// </summary> /// <param name="board"> Board</param> /// <param name="searchMode"> Search mode</param> /// <param name="ePlayer"> Player making the move</param> /// <param name="dispatcher"> Dispatcher of the main thread if function is called on a background thread</param> /// <param name="actionFoundMove"> Action to call with the found move</param> /// <param name="cookie"> Cookie to pass to the action</param> private void FindBestMove <T>(ChessBoard board, SearchMode searchMode, ChessBoard.PlayerE ePlayer, Dispatcher dispatcher, Action <T, MoveExt> actionFoundMove, T cookie) { bool bRetVal = false; List <Move> moveList; MoveExt moveExt; Move move; int[] arrIndex; int iSwapIndex; int iTmp; int iPermCount; int iCacheHit; int iMaxDepth; Random rnd; ChessBoard.PosInfoS posInfo; moveList = board.EnumMoveList(ePlayer, true /*bMoveList*/, out posInfo); arrIndex = new int[moveList.Count]; for (int iIndex = 0; iIndex < moveList.Count; iIndex++) { arrIndex[iIndex] = iIndex; } if (searchMode.m_eRandomMode != SearchMode.RandomModeE.Off) { rnd = (searchMode.m_eRandomMode == SearchMode.RandomModeE.OnRepetitive) ? m_rndRep : m_rnd; for (int iIndex = 0; iIndex < moveList.Count; iIndex++) { iSwapIndex = rnd.Next(moveList.Count); iTmp = arrIndex[iIndex]; arrIndex[iIndex] = arrIndex[iSwapIndex]; arrIndex[iSwapIndex] = iTmp; } } move.StartPos = 0; move.EndPos = 0; move.OriginalPiece = ChessBoard.PieceE.None; move.Type = Move.TypeE.Normal; bRetVal = FindBestMove(board, searchMode, ePlayer, moveList, arrIndex, posInfo, ref move, out iPermCount, out iCacheHit, out iMaxDepth); moveExt = new MoveExt(move, "", iPermCount, iMaxDepth, iMaxDepth, 0); m_searchEngineWorking = null; if (dispatcher != null) { dispatcher.Invoke(actionFoundMove, cookie, moveExt); } else { actionFoundMove(cookie, moveExt); } }
/// <summary> /// Add a move to the stack. All redo move are discarded /// </summary> /// <param name="move"> New move</param> public void AddMove(MoveExt move) { int iCount; int iPos; iCount = Count; iPos = m_iPosInList + 1; while (iCount != iPos) { m_listMovePos.RemoveAt(--iCount); } m_listMovePos.Add(move); m_iPosInList = iPos; }
/// <summary> /// Gets the description of a move /// </summary> /// <param name="move"> Move to describe</param> /// <returns> /// Move description /// </returns> private string GetMoveDesc(MoveExt move) { string strRetVal; if (m_eDisplayMode == DisplayModeE.MovePos) { strRetVal = ChessBoard.GetHumanPos(move); } else { strRetVal = PgnUtil.GetPGNMoveFromMove(m_chessCtl.Board, move, false); if ((move.Move.Type & Move.TypeE.MoveFromBook) == Move.TypeE.MoveFromBook) { strRetVal = "(" + strRetVal + ")"; } } return(strRetVal); }
/// <summary> /// Gets a PGN move from a MovePosS structure and a chessboard. /// </summary> /// <param name="chessBoard"> Chessboard before the move has been done.</param> /// <param name="move"> Move to convert</param> /// <param name="bIncludeEnding"> true to include ending</param> /// <returns> /// PGN move /// </returns> public static string GetPGNMoveFromMove(ChessBoard chessBoard, MoveExt move, bool bIncludeEnding) { string strRetVal; string strStartPos; ChessBoard.PieceE ePiece; PGNAmbiguity eAmbiguity; ChessBoard.PlayerE ePlayerToMove; if (move.Move.Type == Move.TypeE.Castle) { strRetVal = (move.Move.EndPos == 1 || move.Move.EndPos == 57) ? "O-O" : "O-O-O"; } else { ePiece = chessBoard[move.Move.StartPos] & ChessBoard.PieceE.PieceMask; ePlayerToMove = chessBoard.CurrentPlayer; eAmbiguity = FindMoveAmbiguity(chessBoard, move.Move, ePlayerToMove); switch (ePiece) { case ChessBoard.PieceE.King: strRetVal = "K"; break; case ChessBoard.PieceE.Queen: strRetVal = "Q"; break; case ChessBoard.PieceE.Rook: strRetVal = "R"; break; case ChessBoard.PieceE.Bishop: strRetVal = "B"; break; case ChessBoard.PieceE.Knight: strRetVal = "N"; break; case ChessBoard.PieceE.Pawn: strRetVal = ""; break; default: strRetVal = ""; break; } strStartPos = GetPGNSquareID(move.Move.StartPos); if ((eAmbiguity & PGNAmbiguity.ColMustBeSpecify) == PGNAmbiguity.ColMustBeSpecify) { strRetVal += strStartPos[0]; } if ((eAmbiguity & PGNAmbiguity.RowMustBeSpecify) == PGNAmbiguity.RowMustBeSpecify) { strRetVal += strStartPos[1]; } if ((move.Move.Type & Move.TypeE.PieceEaten) == Move.TypeE.PieceEaten) { if (ePiece == ChessBoard.PieceE.Pawn && (eAmbiguity & PGNAmbiguity.ColMustBeSpecify) == (PGNAmbiguity)0 && (eAmbiguity & PGNAmbiguity.RowMustBeSpecify) == (PGNAmbiguity)0) { strRetVal += strStartPos[0]; } strRetVal += 'x'; } strRetVal += GetPGNSquareID(move.Move.EndPos); switch (move.Move.Type & Move.TypeE.MoveTypeMask) { case Move.TypeE.PawnPromotionToQueen: strRetVal += "=Q"; break; case Move.TypeE.PawnPromotionToRook: strRetVal += "=R"; break; case Move.TypeE.PawnPromotionToBishop: strRetVal += "=B"; break; case Move.TypeE.PawnPromotionToKnight: strRetVal += "=N"; break; case Move.TypeE.PawnPromotionToPawn: strRetVal += "=P"; break; default: break; } } chessBoard.DoMoveNoLog(move.Move); switch (chessBoard.GetCurrentResult()) { case ChessBoard.GameResultE.OnGoing: break; case ChessBoard.GameResultE.Check: strRetVal += "+"; break; case ChessBoard.GameResultE.Mate: strRetVal += "#"; if (bIncludeEnding) { if (chessBoard.CurrentPlayer == ChessBoard.PlayerE.Black) { strRetVal += " 1-0"; } else { strRetVal += " 0-1"; } } break; case ChessBoard.GameResultE.ThreeFoldRepeat: case ChessBoard.GameResultE.FiftyRuleRepeat: case ChessBoard.GameResultE.TieNoMove: case ChessBoard.GameResultE.TieNoMatePossible: if (bIncludeEnding) { strRetVal += " 1/2-1/2"; } break; default: break; } chessBoard.UndoMoveNoLog(move.Move); return(strRetVal); }