コード例 #1
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);
        }
コード例 #2
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);
        }