コード例 #1
0
ファイル: SearchEngine.cs プロジェクト: cyberdive/C-chess
 /// <summary>
 /// Debugging routine
 /// </summary>
 /// <param name="iDepth">       Actual search depth</param>
 /// <param name="ePlayerColor"> Color doing the move</param>
 /// <param name="move">         Move</param>
 /// <param name="iPts">         Points for this move</param>
 protected void TraceSearch(int iDepth, ChessBoard.PlayerE ePlayerColor, Move move, int iPts)
 {
     if (m_trace != null)
     {
         m_trace.TraceSearch(iDepth, ePlayerColor, move, iPts);
     }
 }
コード例 #2
0
ファイル: GameTimer.cs プロジェクト: cyberdive/C-chess
 /// <summary>
 /// Reset the timer of both player
 /// </summary>
 /// <param name="ePlayerColor"> Playing color</param>
 /// <param name="lWhiteTicks">  White Ticks</param>
 /// <param name="lBlackTicks">  Black Ticks</param>
 public void ResetTo(ChessBoard.PlayerE ePlayerColor, long lWhiteTicks, long lBlackTicks)
 {
     m_ePlayerColor          = ePlayerColor;
     m_timeSpanCommitedWhite = new TimeSpan(lWhiteTicks);
     m_timeSpanCommitedBlack = new TimeSpan(lBlackTicks);
     m_timerStart            = DateTime.Now;
 }
コード例 #3
0
ファイル: SearchEngine.cs プロジェクト: cyberdive/C-chess
 /// <summary>
 /// Find the best move using a specific search method
 /// </summary>
 /// <param name="chessBoard">       Chess board</param>
 /// <param name="searchMode">       Search mode</param>
 /// <param name="ePlayer">          Player doing the move</param>
 /// <param name="moveList">         Move list</param>
 /// <param name="arrIndex">         Order of evaluation of the moves</param>
 /// <param name="posInfo">          Position information</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 to use</param>
 /// <returns>
 /// true if a move has been found
 /// </returns>
 protected abstract bool FindBestMove(ChessBoard chessBoard,
                                      SearchMode searchMode,
                                      ChessBoard.PlayerE ePlayer,
                                      List <Move> moveList,
                                      int[]                  arrIndex,
                                      ChessBoard.PosInfoS posInfo,
                                      ref Move moveBest,
                                      out int iPermCount,
                                      out int iCacheHit,
                                      out int iMaxDepth);
コード例 #4
0
ファイル: SearchEngine.cs プロジェクト: cyberdive/C-chess
        /// <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);
            }
        }
コード例 #5
0
ファイル: Igra.cs プロジェクト: MilosMicin/ChessSharp
        protected Igrac PlayerE2Igrac(ChessBoard.PlayerE f)
        {
            switch (f)
            {
            case ChessBoard.PlayerE.Black:
                return(Igrac.Crni);

            default:
                return(Igrac.Beli);
            }
        }
コード例 #6
0
ファイル: SearchEngine.cs プロジェクト: cyberdive/C-chess
        /// <summary>
        /// Find the best move for the given player
        /// </summary>
        /// <param name="trace">            Trace object or null</param>
        /// <param name="rnd">              Random object</param>
        /// <param name="rndRep">           Repetitive random object</param>
        /// <param name="board">            Board</param>
        /// <param name="searchMode">       Search mode</param>
        /// <param name="ePlayer">          Player making the move</param>
        /// <param name="dispatcher">       Main thread dispatcher</param>
        /// <param name="actionMoveFound">  Action to execute when the find best move routine is done</param>
        /// <param name="cookie">           Cookie to pass to the actionMoveFound action</param>
        /// <returns>
        /// true if search has started, false if search engine is busy
        /// </returns>
        public static bool FindBestMove <T>(ITrace trace,
                                            Random rnd,
                                            Random rndRep,
                                            ChessBoard board,
                                            SearchMode searchMode,
                                            ChessBoard.PlayerE ePlayer,
                                            Dispatcher dispatcher,
                                            Action <T, MoveExt> actionMoveFound,
                                            T cookie)
        {
            bool         bRetVal;
            bool         bMultipleThread;
            SearchEngine searchEngine;

            if (IsSearchEngineBusy)
            {
                bRetVal = false;
            }
            else
            {
                bRetVal         = true;
                m_bCancelSearch = false;
                if (searchMode.m_eOption == SearchMode.OptionE.UseMinMax)
                {
                    searchEngine = new SearchEngineMinMax(trace, rnd, rndRep);
                }
                else
                {
                    searchEngine = new SearchEngineAlphaBeta(trace, rnd, rndRep);
                }
                bMultipleThread = (searchMode.m_eThreadingMode == SearchMode.ThreadingModeE.DifferentThreadForSearch ||
                                   searchMode.m_eThreadingMode == SearchMode.ThreadingModeE.OnePerProcessorForSearch);
                m_searchEngineWorking = searchEngine;
                if (bMultipleThread)
                {
                    Task.Factory.StartNew(() => searchEngine.FindBestMove(board,
                                                                          searchMode,
                                                                          ePlayer,
                                                                          dispatcher,
                                                                          actionMoveFound,
                                                                          cookie));
                }
                else
                {
                    searchEngine.FindBestMove(board,
                                              searchMode,
                                              ePlayer,
                                              null /*dispatcher*/,
                                              actionMoveFound,
                                              cookie);
                }
            }
            return(bRetVal);
        }
コード例 #7
0
 /// <summary>
 /// Create a new game using the specified list of moves
 /// </summary>
 /// <param name="chessBoardStarting">   Starting board or null if standard board</param>
 /// <param name="listMove">             List of moves</param>
 /// <param name="eNextMoveColor">       Color starting to play</param>
 /// <param name="strWhitePlayerName">   Name of the player playing white pieces</param>
 /// <param name="strBlackPlayerName">   Name of the player playing black pieces</param>
 /// <param name="eWhitePlayerType">     Type of player playing white pieces</param>
 /// <param name="eBlackPlayerType">     Type of player playing black pieces</param>
 /// <param name="spanPlayerWhite">      Timer for white</param>
 /// <param name="spanPlayerBlack">      Timer for black</param>
 public override void CreateGameFromMove(ChessBoard chessBoardStarting,
                                         List <MoveExt> listMove,
                                         ChessBoard.PlayerE eNextMoveColor,
                                         string strWhitePlayerName,
                                         string strBlackPlayerName,
                                         PlayerTypeE eWhitePlayerType,
                                         PlayerTypeE eBlackPlayerType,
                                         TimeSpan spanPlayerWhite,
                                         TimeSpan spanPlayerBlack)
 {
     base.CreateGameFromMove(chessBoardStarting,
                             listMove,
                             eNextMoveColor,
                             strWhitePlayerName,
                             strBlackPlayerName,
                             eWhitePlayerType,
                             eBlackPlayerType,
                             spanPlayerWhite,
                             spanPlayerBlack);
     if (eWhitePlayerType == PlayerTypeE.Program)
     {
         if (eBlackPlayerType == PlayerTypeE.Program)
         {
             Father.PlayingMode = MainWindow.PlayingModeE.ComputerPlayBoth;
         }
         else
         {
             Father.PlayingMode = MainWindow.PlayingModeE.ComputerPlayWhite;
         }
     }
     else if (eBlackPlayerType == PlayerTypeE.Program)
     {
         Father.PlayingMode = MainWindow.PlayingModeE.ComputerPlayBlack;
     }
     else
     {
         Father.PlayingMode = MainWindow.PlayingModeE.PlayerAgainstPlayer;
     }
     Father.SetCmdState();
 }
コード例 #8
0
        /// <summary>
        /// Find the best move for a player using minmax search
        /// </summary>
        /// <param name="board">        Chess board</param>
        /// <param name="searchMode">   Search mode</param>
        /// <param name="ePlayer">      Color doing the move</param>
        /// <param name="moveList">     Move list</param>
        /// <param name="arrIndex">     Order of evaluation of the moves</param>
        /// <param name="posInfo">      Information about pieces attacks</param>
        /// <param name="moveBest">     Best move found</param>
        /// <param name="iPermCount">   Nb of permutations evaluated</param>
        /// <param name="iCacheHit">    Nb of cache hit</param>
        /// <param name="iMaxDepth">    Maximum depth evaluated</param>
        /// <returns>
        /// true if a move has been found
        /// </returns>
        protected override bool FindBestMove(ChessBoard board,
                                             SearchMode searchMode,
                                             ChessBoard.PlayerE ePlayer,
                                             List <Move> moveList,
                                             int[]                  arrIndex,
                                             ChessBoard.PosInfoS posInfo,
                                             ref Move moveBest,
                                             out int iPermCount,
                                             out int iCacheHit,
                                             out int iMaxDepth)
        {
            bool     bRetVal = false;
            DateTime dtTimeOut;
            int      iDepth;
            int      iPermCountAtLevel;

            iPermCount = 0;
            iCacheHit  = 0;
            if (searchMode.m_iSearchDepth == 0)
            {
                dtTimeOut = DateTime.Now + TimeSpan.FromSeconds(searchMode.m_iTimeOutInSec);
                iDepth    = 0;
                do
                {
                    bRetVal     = FindBestMoveUsingMinMaxAtDepth(board, searchMode, ePlayer, moveList, arrIndex, iDepth + 1, ref moveBest, out iPermCountAtLevel);
                    iPermCount += iPermCountAtLevel;
                    iDepth++;
                } while (DateTime.Now < dtTimeOut);
                iMaxDepth = iDepth;
            }
            else
            {
                iMaxDepth = searchMode.m_iSearchDepth;
                bRetVal   = FindBestMoveUsingMinMaxAtDepth(board, searchMode, ePlayer, moveList, arrIndex, iMaxDepth, ref moveBest, out iPermCount);
            }
            return(bRetVal);
        }
コード例 #9
0
        /// <summary>
        /// Minimum/maximum depth first search
        /// </summary>
        /// <param name="board">            Chess board</param>
        /// <param name="searchMode">       Search mode</param>
        /// <param name="ePlayer">          Player doing the move</param>
        /// <param name="iDepth">           Actual search depth</param>
        /// <param name="iWhiteMoveCount">  Number of moves white can do</param>
        /// <param name="iBlackMoveCount">  Number of moves black can do</param>
        /// <param name="iPermCount">       Total permutation evaluated</param>
        /// <returns>
        /// Points to give for this move
        /// </returns>
        private int MinMax(ChessBoard board, SearchMode searchMode, ChessBoard.PlayerE ePlayer, int iDepth, int iWhiteMoveCount, int iBlackMoveCount, ref int iPermCount)
        {
            int         iRetVal;
            int         iMoveCount;
            int         iPts;
            List <Move> moveList;

            ChessBoard.RepeatResultE eResult;

            if (board.IsEnoughPieceForCheckMate())
            {
                if (iDepth == 0 || m_bCancelSearch)
                {
                    iRetVal = (ePlayer == ChessBoard.PlayerE.Black) ? -board.Points(searchMode, ePlayer, 0, iWhiteMoveCount - iBlackMoveCount, ChessBoard.s_posInfoNull, ChessBoard.s_posInfoNull) :
                              board.Points(searchMode, ePlayer, 0, iWhiteMoveCount - iBlackMoveCount, ChessBoard.s_posInfoNull, ChessBoard.s_posInfoNull);
                    iPermCount++;
                }
                else
                {
                    moveList   = board.EnumMoveList(ePlayer);
                    iMoveCount = moveList.Count;
                    if (ePlayer == ChessBoard.PlayerE.White)
                    {
                        iWhiteMoveCount = iMoveCount;
                    }
                    else
                    {
                        iBlackMoveCount = iMoveCount;
                    }
                    if (iMoveCount == 0)
                    {
                        if (board.IsCheck(ePlayer))
                        {
                            iRetVal = -1000000 - iDepth;
                        }
                        else
                        {
                            iRetVal = 0; // Draw
                        }
                    }
                    else
                    {
                        iRetVal = Int32.MinValue;
                        foreach (Move move in moveList)
                        {
                            eResult = board.DoMoveNoLog(move);
                            if (eResult == ChessBoard.RepeatResultE.NoRepeat)
                            {
                                iPts = -MinMax(board,
                                               searchMode,
                                               (ePlayer == ChessBoard.PlayerE.Black) ? ChessBoard.PlayerE.White : ChessBoard.PlayerE.Black,
                                               iDepth - 1,
                                               iWhiteMoveCount,
                                               iBlackMoveCount,
                                               ref iPermCount);
                            }
                            else
                            {
                                iPts = 0;
                            }
                            board.UndoMoveNoLog(move);
                            if (iPts > iRetVal)
                            {
                                iRetVal = iPts;
                            }
                        }
                    }
                }
            }
            else
            {
                iRetVal = 0;
            }
            return(iRetVal);
        }
コード例 #10
0
        /// <summary>
        /// Find the best move for a player using minmax search
        /// </summary>
        /// <param name="board">        Chess board</param>
        /// <param name="searchMode">   Search mode</param>
        /// <param name="ePlayer">      Color doing the move</param>
        /// <param name="moveList">     Move list</param>
        /// <param name="arrIndex">     Order of evaluation of the moves</param>
        /// <param name="iDepth">       Maximum depth</param>
        /// <param name="moveBest">     Best move found</param>
        /// <param name="iPermCount">   Total permutation evaluated</param>
        /// <returns>
        /// true if a move has been found
        /// </returns>
        private bool FindBestMoveUsingMinMaxAtDepth(ChessBoard board, SearchMode searchMode, ChessBoard.PlayerE ePlayer, List <Move> moveList, int[] arrIndex, int iDepth, ref Move moveBest, out int iPermCount)
        {
            bool bRetVal = false;
            Move move;
            int  iPts;
            int  iWhiteMoveCount;
            int  iBlackMoveCount;
            int  iBestPts;

            ChessBoard.RepeatResultE eResult;

            iPermCount = 0;
            iBestPts   = Int32.MinValue;
            if (ePlayer == ChessBoard.PlayerE.White)
            {
                iWhiteMoveCount = moveList.Count;
                iBlackMoveCount = 0;
            }
            else
            {
                iWhiteMoveCount = 0;
                iBlackMoveCount = moveList.Count;
            }
            foreach (int iIndex in arrIndex)
            {
                move    = moveList[iIndex];
                eResult = board.DoMoveNoLog(move);
                if (eResult == ChessBoard.RepeatResultE.NoRepeat)
                {
                    iPts = -MinMax(board,
                                   searchMode,
                                   (ePlayer == ChessBoard.PlayerE.Black) ? ChessBoard.PlayerE.White : ChessBoard.PlayerE.Black,
                                   iDepth - 1,
                                   iWhiteMoveCount,
                                   iBlackMoveCount,
                                   ref iPermCount);
                }
                else
                {
                    iPts = 0;
                }
                board.UndoMoveNoLog(move);
                if (iPts > iBestPts)
                {
                    TraceSearch(iDepth, ePlayer, move, iPts);
                    iBestPts = iPts;
                    moveBest = move;
                    bRetVal  = true;
                }
            }
            return(bRetVal);
        }
コード例 #11
0
        /// <summary>
        /// Find all moves which end to the same position which can create ambiguity
        /// </summary>
        /// <param name="chessBoard">   Chessboard before the move has been done.</param>
        /// <param name="move">         Move to convert</param>
        /// <param name="eMovePlayer">  Player making the move</param>
        /// <returns>
        /// PGN move
        /// </returns>
        private static PGNAmbiguity FindMoveAmbiguity(ChessBoard chessBoard, Move move, ChessBoard.PlayerE eMovePlayer)
        {
            PGNAmbiguity eRetVal = PGNAmbiguity.NotFound;

            ChessBoard.PieceE ePieceMove;
            List <Move>       moveList;

            moveList   = chessBoard.EnumMoveList(eMovePlayer);
            ePieceMove = chessBoard[move.StartPos];
            foreach (Move moveTest in moveList)
            {
                if (moveTest.EndPos == move.EndPos)
                {
                    if (moveTest.StartPos == move.StartPos)
                    {
                        if (moveTest.Type == move.Type)
                        {
                            eRetVal |= PGNAmbiguity.Found;
                        }
                    }
                    else
                    {
                        if (chessBoard[moveTest.StartPos] == ePieceMove)
                        {
                            if ((moveTest.StartPos & 7) != (move.StartPos & 7))
                            {
                                eRetVal |= PGNAmbiguity.ColMustBeSpecify;
                            }
                            else
                            {
                                eRetVal |= PGNAmbiguity.RowMustBeSpecify;
                            }
                        }
                    }
                }
            }
            return(eRetVal);
        }
コード例 #12
0
        /// <summary>
        /// Alpha Beta pruning function.
        /// </summary>
        /// <param name="board">            Chess board</param>
        /// <param name="ePlayer">          Color doing the move</param>
        /// <param name="iDepth">           Actual search depth</param>
        /// <param name="iAlpha">           Alpha limit</param>
        /// <param name="iBeta">            Beta limit</param>
        /// <param name="iWhiteMoveCount">  Number of moves white can do</param>
        /// <param name="iBlackMoveCount">  Number of moves black can do</param>
        /// <param name="abInfo">           Supplemental information</param>
        /// <returns>
        /// Points to give for this move or Int32.MinValue for timed out
        /// </returns>
        private int AlphaBeta(ChessBoard board,
                              ChessBoard.PlayerE ePlayer,
                              int iDepth,
                              int iAlpha,
                              int iBeta,
                              int iWhiteMoveCount,
                              int iBlackMoveCount,
                              AlphaBetaInfo abInfo)
        {
            int         iRetVal;
            List <Move> moveList;
            int         iPts;
            int         iMoveCount;

            ChessBoard.PosInfoS posInfo;
            TransEntryTypeE     eType = TransEntryTypeE.Alpha;

            ChessBoard.BoardStateMaskE eBoardExtraInfo;
            ChessBoard.RepeatResultE   eResult;

            if (abInfo.m_dtTimeOut != DateTime.MaxValue && DateTime.Now >= abInfo.m_dtTimeOut)
            {
                iRetVal = Int32.MinValue;   // Time out!
            }
            else if (board.IsEnoughPieceForCheckMate())
            {
                eBoardExtraInfo = board.ComputeBoardExtraInfo(ePlayer, true);
                iRetVal         = (abInfo.m_transTable != null) ? abInfo.m_transTable.ProbeEntry(board.CurrentZobristKey, eBoardExtraInfo, iDepth, iAlpha, iBeta) : Int32.MaxValue;
                if (iRetVal == Int32.MaxValue)
                {
                    if (iDepth == 0 || m_bCancelSearch)
                    {
                        iRetVal = board.Points(abInfo.m_searchMode, ePlayer, abInfo.m_iMaxDepth - iDepth, iWhiteMoveCount - iBlackMoveCount, abInfo.m_posInfoWhite, abInfo.m_posInfoBlack);
                        if (ePlayer == ChessBoard.PlayerE.Black)
                        {
                            iRetVal = -iRetVal;
                        }
                        abInfo.m_iPermCount++;
                        if (abInfo.m_transTable != null)
                        {
                            abInfo.m_transTable.RecordEntry(board.CurrentZobristKey, eBoardExtraInfo, iDepth, iRetVal, TransEntryTypeE.Exact);
                        }
                    }
                    else
                    {
                        moveList   = board.EnumMoveList(ePlayer, true, out posInfo);
                        iMoveCount = moveList.Count;
                        if (ePlayer == ChessBoard.PlayerE.White)
                        {
                            iWhiteMoveCount       = iMoveCount;
                            abInfo.m_posInfoWhite = posInfo;
                        }
                        else
                        {
                            iBlackMoveCount       = iMoveCount;
                            abInfo.m_posInfoBlack = posInfo;
                        }
                        if (iMoveCount == 0)
                        {
                            if (board.IsCheck(ePlayer))
                            {
                                iRetVal = -1000000 - iDepth;
                            }
                            else
                            {
                                iRetVal = 0;    // Draw
                            }
                            if (abInfo.m_transTable != null)
                            {
                                abInfo.m_transTable.RecordEntry(board.CurrentZobristKey, eBoardExtraInfo, iDepth, iRetVal, TransEntryTypeE.Exact);
                            }
                        }
                        else
                        {
                            iRetVal = iAlpha;
                            foreach (Move move in moveList)
                            {
                                eResult = board.DoMoveNoLog(move);
                                abInfo.m_arrMove[iDepth - 1] = move;
                                if (eResult == ChessBoard.RepeatResultE.NoRepeat)
                                {
                                    iPts = -AlphaBeta(board,
                                                      (ePlayer == ChessBoard.PlayerE.Black) ? ChessBoard.PlayerE.White : ChessBoard.PlayerE.Black,
                                                      iDepth - 1,
                                                      -iBeta,
                                                      -iRetVal,
                                                      iWhiteMoveCount,
                                                      iBlackMoveCount,
                                                      abInfo);
                                }
                                else
                                {
                                    iPts = 0;
                                }
                                board.UndoMoveNoLog(move);
                                if (iPts == Int32.MinValue)
                                {
                                    iRetVal = iPts;
                                    break;
                                }
                                else
                                {
                                    if (iPts > iRetVal)
                                    {
                                        iRetVal = iPts;
                                        eType   = TransEntryTypeE.Exact;
                                    }
                                    if (iRetVal >= iBeta)
                                    {
                                        iRetVal = iBeta;
                                        eType   = TransEntryTypeE.Beta;
                                        break;
                                    }
                                }
                            }
                            if (abInfo.m_transTable != null && iRetVal != Int32.MinValue)
                            {
                                abInfo.m_transTable.RecordEntry(board.CurrentZobristKey, eBoardExtraInfo, iDepth, iRetVal, eType);
                            }
                        }
                    }
                }
            }
            else
            {
                iRetVal = 0;
            }
            return(iRetVal);
        }
コード例 #13
0
        /// <summary>
        /// Find the best move for a player using alpha-beta
        /// </summary>
        /// <param name="board">        Chess board</param>
        /// <param name="searchMode">   Search mode</param>
        /// <param name="ePlayer">      Player doing the move</param>
        /// <param name="moveList">     Move list</param>
        /// <param name="arrIndex">     Order of evaluation of the moves</param>
        /// <param name="posInfo">      Information about pieces attacks</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 to use</param>
        /// <returns>
        /// true if a move has been found
        /// </returns>
        protected override bool FindBestMove(ChessBoard board,
                                             SearchMode searchMode,
                                             ChessBoard.PlayerE ePlayer,
                                             List <Move> moveList,
                                             int[]                  arrIndex,
                                             ChessBoard.PosInfoS posInfo,
                                             ref Move moveBest,
                                             out int iPermCount,
                                             out int iCacheHit,
                                             out int iMaxDepth)
        {
            bool bRetVal = false;
            bool bMultipleThread;
            bool bUseTransTable;

            ChessBoard[]             arrBoard;
            Task <AlphaBetaResult>[] taskArray;
            List <Move>[]            arrMoveList;
            AlphaBetaResult          alphaBetaRes;

            ChessBoard.PosInfoS posInfoWhite;
            ChessBoard.PosInfoS posInfoBlack;
            int iAlpha;
            int iBeta;
            int iThreadCount;

            //TODO Enable transposition table when bug on 3 repetition move draw will be found.
            if (ePlayer == ChessBoard.PlayerE.White)
            {
                posInfoWhite = posInfo;
                posInfoBlack = ChessBoard.s_posInfoNull;
            }
            else
            {
                posInfoWhite = ChessBoard.s_posInfoNull;
                posInfoBlack = posInfo;
            }
            searchMode.m_eOption &= ~SearchMode.OptionE.UseTransTable;
            bUseTransTable        = (searchMode.m_eOption.HasFlag(SearchMode.OptionE.UseTransTable));
            iCacheHit             = 0;
            iMaxDepth             = 0;
            iPermCount            = 0;
            iAlpha          = -10000000;
            iBeta           = +10000000;
            bMultipleThread = (searchMode.m_eThreadingMode == SearchMode.ThreadingModeE.OnePerProcessorForSearch);
            iThreadCount    = System.Environment.ProcessorCount;
            if (bMultipleThread && iThreadCount < 2)
            {
                bMultipleThread = false;    // No reason to go with multi-threading if only one processor
            }
            if (bMultipleThread)
            {
                arrBoard    = new ChessBoard[iThreadCount];
                arrMoveList = new List <Move> [iThreadCount];
                taskArray   = new Task <AlphaBetaResult> [iThreadCount];
                for (int iIndex = 0; iIndex < iThreadCount; iIndex++)
                {
                    arrBoard[iIndex]    = board.Clone();
                    arrMoveList[iIndex] = new List <Move>(moveList.Count / iThreadCount + 1);
                    for (int iStep = iIndex; iStep < moveList.Count; iStep += iThreadCount)
                    {
                        arrMoveList[iIndex].Add(moveList[arrIndex[iStep]]);
                    }
                }
                for (int iIndex = 0; iIndex < iThreadCount; iIndex++)
                {
                    taskArray[iIndex] = Task <AlphaBetaResult> .Factory.StartNew((param) => {
                        int iStep = (int)param;
                        return(FindBestMoveUsingAlphaBetaAsync(arrBoard[iStep],
                                                               searchMode,
                                                               ePlayer,
                                                               iStep,
                                                               arrMoveList[iStep],
                                                               posInfoWhite,
                                                               posInfoBlack,
                                                               moveList.Count,
                                                               iAlpha,
                                                               iBeta));
                    }, iIndex);
                }
                iMaxDepth = 999;
                for (int iStep = 0; iStep < iThreadCount; iStep++)
                {
                    alphaBetaRes = taskArray[iStep].Result;
                    if (alphaBetaRes.movePosBest.StartPos != 255)
                    {
                        iPermCount += alphaBetaRes.iPermCount;
                        iMaxDepth   = Math.Min(iMaxDepth, alphaBetaRes.iMaxDepth);
                        if (bUseTransTable)
                        {
                            iCacheHit += TransTable.GetTransTable(iStep).CacheHit;
                        }
                        if (alphaBetaRes.iPts > iAlpha)
                        {
                            iAlpha   = alphaBetaRes.iPts;
                            moveBest = alphaBetaRes.movePosBest;
                            bRetVal  = true;
                        }
                    }
                }
                if (iMaxDepth == 999)
                {
                    iMaxDepth = -1;
                }
            }
            else
            {
                ChessBoard  chessBoardTmp;
                List <Move> moveListTmp;

                chessBoardTmp = board.Clone();
                moveListTmp   = new List <Move>(moveList.Count);
                for (int iIndex = 0; iIndex < moveList.Count; iIndex++)
                {
                    moveListTmp.Add(moveList[arrIndex[iIndex]]);
                }
                alphaBetaRes = FindBestMoveUsingAlphaBetaAsync(chessBoardTmp,
                                                               searchMode,
                                                               ePlayer,
                                                               0,  // ThreadId
                                                               moveListTmp,
                                                               posInfoWhite,
                                                               posInfoBlack,
                                                               moveList.Count,
                                                               iAlpha,
                                                               iBeta);
                iPermCount = alphaBetaRes.iPermCount;
                iMaxDepth  = alphaBetaRes.iMaxDepth;
                if (alphaBetaRes.movePosBest.StartPos != 255)
                {
                    if (bUseTransTable)
                    {
                        iCacheHit += TransTable.GetTransTable(0).CacheHit;
                    }
                    moveBest = alphaBetaRes.movePosBest;
                    bRetVal  = true;
                }
            }
            return(bRetVal);
        }
コード例 #14
0
        /// <summary>
        /// Find the best move for a player using alpha-beta in a secondary thread
        /// </summary>
        /// <param name="board">            Chess board</param>
        /// <param name="searchMode">       Search mode</param>
        /// <param name="ePlayer">          Color doing the move</param>
        /// <param name="iThreadId">        Thread Id (0-n)</param>
        /// <param name="moveList">         List of move to try</param>
        /// <param name="posInfoWhite">     Information about pieces attacks for the white</param>
        /// <param name="posInfoBlack">     Information about pieces attacks for the black</param>
        /// <param name="iTotalMoveCount">  Total number of moves</param>
        /// <param name="iAlpha">           Alpha bound</param>
        /// <param name="iBeta">            Beta bound</param>
        /// <returns>
        /// Points
        /// </returns>
        private AlphaBetaResult FindBestMoveUsingAlphaBetaAsync(ChessBoard board,
                                                                SearchMode searchMode,
                                                                ChessBoard.PlayerE ePlayer,
                                                                int iThreadId,
                                                                List <Move> moveList,
                                                                ChessBoard.PosInfoS posInfoWhite,
                                                                ChessBoard.PosInfoS posInfoBlack,
                                                                int iTotalMoveCount,
                                                                int iAlpha,
                                                                int iBeta)
        {
            AlphaBetaResult resRetVal;
            DateTime        dtTimeOut;
            int             iDepth;
            int             iPermCountAtLevel;
            int             iPoint;
            int             iBestMoveIndex;
            int             iDepthLimit;

            int[] arrPoints;
            System.Threading.ThreadPriority eThreadPriority;
            TransTable transTable;
            bool       bTimeOut;
            bool       bIterativeDepthFirst;

            resRetVal       = new AlphaBetaResult();
            eThreadPriority = System.Threading.Thread.CurrentThread.Priority;
            System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.BelowNormal;
            if ((searchMode.m_eOption & SearchMode.OptionE.UseTransTable) != 0)
            {
                transTable = TransTable.GetTransTable(iThreadId);
                transTable.Reset();
            }
            else
            {
                transTable = null;
            }
            bIterativeDepthFirst                = (searchMode.m_eOption.HasFlag(SearchMode.OptionE.UseIterativeDepthSearch));
            resRetVal.movePosBest.StartPos      = 255;
            resRetVal.movePosBest.EndPos        = 255;
            resRetVal.movePosBest.OriginalPiece = ChessBoard.PieceE.None;
            resRetVal.movePosBest.Type          = Move.TypeE.Normal;
            try {
                resRetVal.iPermCount = 0;
                if (searchMode.m_iSearchDepth == 0 || bIterativeDepthFirst)
                {
                    dtTimeOut      = (bIterativeDepthFirst) ? DateTime.MaxValue : DateTime.Now + TimeSpan.FromSeconds(searchMode.m_iTimeOutInSec);
                    iDepthLimit    = (bIterativeDepthFirst) ? searchMode.m_iSearchDepth : 999;
                    iDepth         = 1;
                    resRetVal.iPts = FindBestMoveUsingAlphaBetaAtDepth(board,
                                                                       searchMode,
                                                                       ePlayer,
                                                                       moveList,
                                                                       posInfoWhite,
                                                                       posInfoBlack,
                                                                       iTotalMoveCount,
                                                                       iDepth,
                                                                       iAlpha,
                                                                       iBeta,
                                                                       transTable,
                                                                       DateTime.MaxValue,
                                                                       out iPermCountAtLevel,
                                                                       out iBestMoveIndex,
                                                                       out bTimeOut,
                                                                       out arrPoints);
                    if (iBestMoveIndex != -1)
                    {
                        resRetVal.movePosBest = moveList[iBestMoveIndex];
                    }
                    resRetVal.iPermCount += iPermCountAtLevel;
                    resRetVal.iMaxDepth   = iDepth;
                    while (DateTime.Now < dtTimeOut && !m_bCancelSearch && !bTimeOut && iDepth < iDepthLimit)
                    {
                        moveList = SortMoveList(moveList, arrPoints);
                        iDepth++;
                        iPoint = FindBestMoveUsingAlphaBetaAtDepth(board,
                                                                   searchMode,
                                                                   ePlayer,
                                                                   moveList,
                                                                   posInfoWhite,
                                                                   posInfoBlack,
                                                                   iTotalMoveCount,
                                                                   iDepth,
                                                                   iAlpha,
                                                                   iBeta,
                                                                   transTable,
                                                                   dtTimeOut,
                                                                   out iPermCountAtLevel,
                                                                   out iBestMoveIndex,
                                                                   out bTimeOut,
                                                                   out arrPoints);
                        if (!bTimeOut)
                        {
                            if (iBestMoveIndex != -1)
                            {
                                resRetVal.movePosBest = moveList[iBestMoveIndex];
                            }
                            resRetVal.iPermCount += iPermCountAtLevel;
                            resRetVal.iMaxDepth   = iDepth;
                            resRetVal.iPts        = iPoint;
                        }
                    }
                }
                else
                {
                    resRetVal.iMaxDepth = searchMode.m_iSearchDepth;
                    resRetVal.iPts      = FindBestMoveUsingAlphaBetaAtDepth(board,
                                                                            searchMode,
                                                                            ePlayer,
                                                                            moveList,
                                                                            posInfoWhite,
                                                                            posInfoBlack,
                                                                            iTotalMoveCount,
                                                                            resRetVal.iMaxDepth,
                                                                            iAlpha,
                                                                            iBeta,
                                                                            transTable,
                                                                            DateTime.MaxValue,
                                                                            out resRetVal.iPermCount,
                                                                            out iBestMoveIndex,
                                                                            out bTimeOut,
                                                                            out arrPoints);
                    if (iBestMoveIndex != -1)
                    {
                        resRetVal.movePosBest = moveList[iBestMoveIndex];
                    }
                }
            } finally {
                System.Threading.Thread.CurrentThread.Priority = eThreadPriority;
            }
            return(resRetVal);
        }
コード例 #15
0
        /// <summary>
        /// Find the best move for a player using alpha-beta for a given depth
        /// </summary>
        /// <param name="board">            Chess board</param>
        /// <param name="searchMode">       Search mode</param>
        /// <param name="ePlayer">          Color doing the move</param>
        /// <param name="moveList">         List of move to try</param>
        /// <param name="posInfoWhite">     Information about pieces attacks for the white</param>
        /// <param name="posInfoBlack">     Information about pieces attacks for the black</param>
        /// <param name="iTotalMoveCount">  Total list of moves</param>
        /// <param name="iDepth">           Maximum depth</param>
        /// <param name="iAlpha">           Alpha bound</param>
        /// <param name="iBeta">            Beta bound</param>
        /// <param name="transTable">       Transposition table or null if not using one</param>
        /// <param name="dtTimeOut">        Time limit (DateTime.MaxValue for no time limit)</param>
        /// <param name="iPermCount">       Total permutation evaluated</param>
        /// <param name="iBestMoveIndex">   Index of the best move</param>
        /// <param name="bTimeOut">         Return true if time out</param>
        /// <param name="arrPoints">        Returns point of each move in move list</param>
        /// <returns>
        /// Points
        /// </returns>
        private int FindBestMoveUsingAlphaBetaAtDepth(ChessBoard board,
                                                      SearchMode searchMode,
                                                      ChessBoard.PlayerE ePlayer,
                                                      List <Move> moveList,
                                                      ChessBoard.PosInfoS posInfoWhite,
                                                      ChessBoard.PosInfoS posInfoBlack,
                                                      int iTotalMoveCount,
                                                      int iDepth,
                                                      int iAlpha,
                                                      int iBeta,
                                                      TransTable transTable,
                                                      DateTime dtTimeOut,
                                                      out int iPermCount,
                                                      out int iBestMoveIndex,
                                                      out bool bTimeOut,
                                                      out int[]             arrPoints)
        {
            int           iRetVal = -10000000;
            int           iWhiteMoveCount;
            int           iBlackMoveCount;
            int           iMoveCount;
            int           iIndex;
            int           iPts;
            Move          move;
            AlphaBetaInfo abInfo;

            ChessBoard.RepeatResultE eResult;

            bTimeOut              = false;
            abInfo                = new AlphaBetaInfo();
            abInfo.m_arrMove      = new Move[iDepth];
            abInfo.m_iPermCount   = 0;
            abInfo.m_dtTimeOut    = dtTimeOut;
            abInfo.m_transTable   = transTable;
            abInfo.m_iMaxDepth    = iDepth;
            abInfo.m_searchMode   = searchMode;
            abInfo.m_posInfoWhite = posInfoWhite;
            abInfo.m_posInfoBlack = posInfoBlack;
            iBestMoveIndex        = -1;
            arrPoints             = new int[moveList.Count];
            if (ePlayer == ChessBoard.PlayerE.White)
            {
                iWhiteMoveCount = iTotalMoveCount;
                iBlackMoveCount = 0;
            }
            else
            {
                iWhiteMoveCount = 0;
                iBlackMoveCount = iTotalMoveCount;
            }
            iMoveCount = moveList.Count;
            iIndex     = 0;
            iRetVal    = iAlpha;
            while (iIndex < iMoveCount && !bTimeOut)
            {
                move    = moveList[iIndex];
                eResult = board.DoMoveNoLog(move);
                abInfo.m_arrMove[iDepth - 1] = move;
                if (eResult == ChessBoard.RepeatResultE.NoRepeat)
                {
                    iPts = -AlphaBeta(board,
                                      (ePlayer == ChessBoard.PlayerE.Black) ? ChessBoard.PlayerE.White : ChessBoard.PlayerE.Black,
                                      iDepth - 1,
                                      -iBeta,
                                      -iRetVal,
                                      iWhiteMoveCount,
                                      iBlackMoveCount,
                                      abInfo);
                }
                else
                {
                    iPts = 0;
                }
                arrPoints[iIndex] = iPts;
                board.UndoMoveNoLog(move);
                if (iPts == Int32.MinValue)
                {
                    iRetVal  = iPts;
                    bTimeOut = true;
                }
                else
                {
                    if (iPts > iRetVal)
                    {
                        TraceSearch(iDepth, ePlayer, move, iPts);
                        iRetVal        = iPts;
                        iBestMoveIndex = iIndex;
                    }
                }
                iIndex++;
            }
            iPermCount = abInfo.m_iPermCount;
            return(iRetVal);
        }
コード例 #16
0
ファイル: GameTimer.cs プロジェクト: cyberdive/C-chess
 /// <summary>
 /// Reset the timer of both player
 /// </summary>
 /// <param name="ePlayerColor"> Playing color</param>
 public void Reset(ChessBoard.PlayerE ePlayerColor)
 {
     ResetTo(ePlayerColor, 0, 0);
 }