/// <summary> /// Show the test result of a computer playing against a computer /// </summary> /// <param name="iGameCount"> Number of games played.</param> /// <param name="searchMode"> Search mode</param> /// <param name="stat"> Statistic.</param> /// <param name="iMethod1Win"> Number of games won by method #1</param> /// <param name="iMethod2Win"> Number of games won by method #2</param> private void TestShowResult(int iGameCount, SearchEngine.SearchMode searchMode, ComputerPlayingStat stat, int iMethod1Win, int iMethod2Win) { string strMsg; string strMethod1; string strMethod2; int iTimeMethod1; int iTimeMethod2; strMethod1 = searchMode.m_boardEvaluationWhite.Name; strMethod2 = searchMode.m_boardEvaluationBlack.Name; iTimeMethod1 = (stat.m_iMethod1MoveCount == 0) ? 0 : stat.m_timeSpanMethod1.Milliseconds / stat.m_iMethod1MoveCount; iTimeMethod2 = (stat.m_iMethod2MoveCount == 0) ? 0 : stat.m_timeSpanMethod2.Milliseconds / stat.m_iMethod2MoveCount; strMsg = iGameCount.ToString() + " game(s) played.\r\n" + iMethod1Win.ToString() + " win(s) for method #1 (" + strMethod1 + "). Average time = " + iMethod1Win.ToString() + " ms per move.\r\n" + iMethod2Win.ToString() + " win(s) for method #2 (" + strMethod2 + "). Average time = " + iMethod2Win.ToString() + " ms per move.\r\n" + (iGameCount - iMethod1Win - iMethod2Win).ToString() + " draw(s)."; MessageBox.Show(strMsg); }
/// <summary> /// Tests the computer playing against itself. Can be called asynchronously by a secondary thread. /// </summary> /// <param name="iGameCount"> Number of games to play.</param> /// <param name="searchMode"> Search mode</param> private void TestComputerAgainstComputerAsync(int iGameCount, SearchEngine.SearchMode searchMode) { int iCount; Func<ChessBoard.MovePosS,int,int,int,ComputerPlayingStat,bool> delPlayComputerMove = null; Action delResetBoard = null; Action delUnlockBoard; Action delSetPlayingMode; Action delShowResultDel; ChessBoard chessBoard; ChessBoard.MovePosS move; int iPermCount; int iCacheHit; int iMaxDepth; int iGameIndex; int iMethod1Win = 0; int iMethod2Win = 0; DateTime dateTime; bool bMoveFound; bool bMultipleThread; bool bEven; bool bEndOfGame; IBoardEvaluation boardEvaluation1; IBoardEvaluation boardEvaluation2; ComputerPlayingStat stat; stat = new ComputerPlayingStat(); bMultipleThread = (searchMode.m_eThreadingMode == SearchEngine.SearchMode.ThreadingModeE.DifferentThreadForSearch || searchMode.m_eThreadingMode == SearchEngine.SearchMode.ThreadingModeE.OnePerProcessorForSearch); boardEvaluation1 = searchMode.m_boardEvaluationWhite; boardEvaluation2 = searchMode.m_boardEvaluationBlack; if (bMultipleThread) { delPlayComputerMove = (a1, a2, a3, a4, a5) => PlayComputerMove(false, MessageModeE.Silent, a1, a2, a3, a4, a5); delResetBoard = () => ResetBoard(); } iGameIndex = 0; while (iGameIndex < iGameCount && !stat.m_bUserCancel) { bEven = ((iGameIndex & 1) == 0); searchMode.m_boardEvaluationWhite = bEven ? boardEvaluation1 : boardEvaluation2; searchMode.m_boardEvaluationBlack = bEven ? boardEvaluation2 : boardEvaluation1; if (bMultipleThread) { Dispatcher.Invoke(delResetBoard); } else { ResetBoard(); } iCount = 0; do { chessBoard = m_chessCtl.ChessBoard.Clone(); dateTime = DateTime.Now; bMoveFound = m_chessCtl.FindBestMove(searchMode, chessBoard, out move, out iPermCount, out iCacheHit, out iMaxDepth); if (bMoveFound) { if ((m_chessCtl.NextMoveColor == ChessBoard.PlayerColorE.White && bEven) || (m_chessCtl.NextMoveColor == ChessBoard.PlayerColorE.Black && !bEven)) { stat.m_timeSpanMethod1 += DateTime.Now - dateTime; stat.m_iMethod1MoveCount++; } else { stat.m_timeSpanMethod2 += DateTime.Now - dateTime; stat.m_iMethod2MoveCount++; } if (bMultipleThread) { bEndOfGame = (bool)Dispatcher.Invoke(delPlayComputerMove, new object[] { move, iPermCount, iMaxDepth, iCacheHit, stat } ); } else { bEndOfGame = PlayComputerMove(false, MessageModeE.Silent, move, iPermCount, iMaxDepth, iCacheHit, stat); } } else { bEndOfGame = true; } iCount++; } while (!bEndOfGame && PlayingMode == PlayingModeE.ComputerAgainstComputer && iCount < 250); if (PlayingMode != PlayingModeE.ComputerAgainstComputer) { stat.m_bUserCancel = true; } else if (iCount < 250) { if (stat.m_eResult == ChessBoard.MoveResultE.Mate) { if ((m_chessCtl.NextMoveColor == ChessBoard.PlayerColorE.Black && bEven) || (m_chessCtl.NextMoveColor == ChessBoard.PlayerColorE.White && !bEven)) { iMethod1Win++; } else { iMethod2Win++; } } } iGameIndex++; } searchMode.m_boardEvaluationWhite = boardEvaluation1; searchMode.m_boardEvaluationBlack = boardEvaluation2; if (bMultipleThread) { delSetPlayingMode = () => SetPlayingMode(PlayingModeE.PlayerAgainstPlayer); delUnlockBoard = () => UnlockBoard(); delShowResultDel = () => TestShowResult(iGameIndex, searchMode, stat, iMethod1Win, iMethod2Win); Dispatcher.Invoke(delShowResultDel); Dispatcher.Invoke(delSetPlayingMode); Dispatcher.Invoke(delUnlockBoard); } else { TestShowResult(iGameIndex, searchMode, stat, iMethod1Win, iMethod2Win); SetPlayingMode(PlayingModeE.PlayerAgainstPlayer); UnlockBoard(); } }
/// <summary> /// Play the computer move found by the search. /// </summary> /// <param name="bFlash"> true to flash moving position</param> /// <param name="eMessageMode"> Which message to show</param> /// <param name="move"> Best move</param> /// <param name="iPermCount"> Permutation count</param> /// <param name="iDepth"> Depth of the search</param> /// <param name="iCacheHit"> Number of moves found in the translation table cache</param> /// <param name="stat"> Playing stat. Can be null</param> /// <returns> /// true if end of game, false if not /// </returns> private bool PlayComputerMove(bool bFlash, MessageModeE eMessageMode, ChessBoard.MovePosS move, int iPermCount, int iDepth, int iCacheHit, ComputerPlayingStat stat) { bool bRetVal; ChessBoard.MoveResultE eResult; ChessBoard.PlayerColorE eColorToPlay; eColorToPlay = m_chessCtl.NextMoveColor; eResult = m_chessCtl.DoMove(move, bFlash, iPermCount, iDepth, iCacheHit); if (stat != null) { stat.m_eResult = eResult; } bRetVal = DisplayMessage(eResult, eMessageMode); return(bRetVal); }