Esempio n. 1
0
        /// <summary>
        /// 输出开局库中元素的散列分布图,用图示的办法来查看散列的效果
        /// 2048行、2048列,2^11 * 2^11 * 4 = 16M 正好是16M个盘面情况
        /// 每4个元素为一组,未占用是白色,占用1个是黄色,占用2个是绿色,全部占用(3个)是蓝色
        /// 通过输出的位图可以看到散列效果还是不错的
        /// </summary>
        //public void SaveHashPicture(string filename)
        //{
        //    using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(2048, 2048, System.Drawing.Imaging.PixelFormat.Format24bppRgb))
        //    {
        //        fs.Seek(0, SeekOrigin.Begin);
        //        for (int h = 0; h < 2048; h++)
        //            for (int w = 0; w < 2048; w++)
        //            {
        //                int count = 0;
        //                for (int i = 0; i < 4; i++)
        //                {
        //                    //从文件中取出6个字节,前4个字节是zobrist值,后2字节是相同盘面统计数
        //                    byte[] bytes6 = new byte[6];
        //                    fs.Read(bytes6, 0, 6);
        //                    int zobristInOpening = BitConverter.ToInt32(bytes6, 0);   //前4字节
        //                    //countSameBoard = BitConverter.ToUInt16(bytes6, 4); //后2个字节
        //                    if (zobristInOpening != 0)
        //                    {
        //                        ++count;
        //                    }
        //                }
        //                if (count == 0)
        //                    bmp.SetPixel(w, h, System.Drawing.Color.White);
        //                else if (count == 1)
        //                    bmp.SetPixel(w, h, System.Drawing.Color.Yellow);
        //                else if (count == 2)
        //                    bmp.SetPixel(w, h, System.Drawing.Color.Green);
        //                else
        //                    bmp.SetPixel(w, h, System.Drawing.Color.Blue);
        //            }
        //        bmp.Save(filename, System.Drawing.Imaging.ImageFormat.Png);
        //    }

        //}


        public Move FindBestMove(Board board)
        {
            Move maxUsedMove = new Move(0, 0, 0, 0); // 使用率最高的着法
            int  maxCount    = 0;                    // 保存使用得最多的次数

            // 在所有的可行的着法里查找一遍,可以发现这种办法效率有点低
            Move[] movelist = new Move[200];
            MoveGenerator.GenAllMoveList(board, movelist);
            foreach (Move m in movelist)
            {
                UInt16 countSameBoard;
                board.MakeMove(m);
                FindBoardHash(Zobrist.ZoristHash(board), out countSameBoard);

                //if (countSameBoard != 0)
                //    Console.WriteLine(m + ":  " + countSameBoard);
                if (countSameBoard > maxCount)
                {
                    maxCount    = countSameBoard;
                    maxUsedMove = new Move(m);
                }
                board.UnmakeMove(m);  // 要恢复原始的盘面
            }
            return(maxUsedMove);
        }
Esempio n. 2
0
        ///// <summary>
        ///// 使用了置换表的AlphaBeta剪枝搜索
        ///// </summary>
        ///// <param name="depth">当前搜索的深度,0代表树根</param>
        ///// <param name="maxDepth">最大搜索深度</param>
        ///// <param name="alpha">初始值可以设置为MIN_EVAL_VALUE</param>
        ///// <param name="beta">初始值可以设置为MAX_EVAL_VALUE</param>
        ///// <returns></returns>
        //public int NegaAlphaBetaTT_old(int depth, int maxDepth, int alpha, int beta)
        //{
        //    //if (depth == 0) bestMove = new Move(0,0,0,0);

        //    ulong boardHash = Zobrist.ZoristHash(board);

        //    // 探查置换表
        //    NodeOfSearch entry = transpositionTable[boardHash]; //ProbeHash(boardHash);

        //    // (depth=0)            a
        //    //                    /   \
        //    // (depth=1)        b      c       这里的b是已经搜索过的节点,已经保存在置换表中,entry.Depth = 1
        //    //                 / \      \
        //    // (depth=2)      d   e      f   (当前搜索的节点是f) depth = 2
        //    //              ..................
        //    // 假设b是以前搜索过的节点,已经保存在置换表中,entry.depth=1
        //    // 当前搜索的节点是f,depth=2,如果f与b的局面相同,由于b的评估值是经过了更深层的搜索得到的,
        //    // 所以f可以直接用b的评估值,这个结果只会好,不会差,所以应该判断entry.Depth <= depth
        //    if (entry != null && (entry.MaxDepth - entry.Depth) >= (maxDepth - depth)  )
        //    //if (entry != null && entry.Depth <= depth)
        //    {
        //        //PrintDebugInfo("Hash表命中!" + entry);

        //        if (entry.Type == NodeOfSearch.PV_NODES)
        //        {
        //            return entry.Score;
        //        }

        //        if (entry.Type == NodeOfSearch.ALL_NODES && entry.Score <= alpha)
        //        {
        //            //PrintDebugInfo("Hash表命中!修改alpha:" + entry.Score + " -> " + alpha);
        //            alpha = entry.Score;
        //            //return alpha;
        //        }
        //        if (entry.Type == NodeOfSearch.CUT_NODES && entry.Score >= beta)
        //        {
        //            //PrintDebugInfo("Hash表命中!修改beta:" + entry.Score + " -> " + beta);
        //            beta = entry.Score;
        //            //return beta;
        //        }

        //        //if (alpha >= beta)
        //        //{
        //        //    PrintDebugInfo("***************这里还会发生alpha>=beta?");
        //        //    //return entry.Score;
        //        //}

        //    }

        //    // 到达叶子节点,搜索到最大深度了
        //    if (depth == maxDepth)
        //    {
        //        int valueLeaf = Evaluator.EvaluateAllWithSide(board);
        //        // 应该肯定是EXACT节点吧?
        //        /* if(v0 <= alpha)
        //            node.Type = NODE_ALPHA;
        //        else if(v0 >= beta)
        //            node.Type = NODE_BETA;
        //        else  */
        //        NodeOfSearch nodeLeaf = new NodeOfSearch(boardHash, depth, maxDepth, NodeOfSearch.PV_NODES, valueLeaf);
        //        transpositionTable.RecordHash(nodeLeaf);
        //        //DEBUG(DBG_DEBUG, SPACES[depth] << "到达最大深度:" << " return score: "<< v0);

        //        return valueLeaf;
        //    }


        //    int nodeType = NodeOfSearch.ALL_NODES;
        //    Move[] moveList = new Move[200];
        //    int countMove = MoveGenerator.GenAllMoveList(board, moveList);

        //    // 无着可走,说明是终止局面,即被将死
        //    if (countMove == 0)
        //    {
        //        int scoreEndStatus = Evaluator.MIN_EVAL_VALUE + depth;
        //        NodeOfSearch nodeEnd = new NodeOfSearch(boardHash, depth, maxDepth, NodeOfSearch.PV_NODES, scoreEndStatus);
        //        transpositionTable.RecordHash(nodeEnd);
        //        return scoreEndStatus;
        //    }

        //    // 利用了置换表中的历史评估数据,进行着法排序
        //    //            局面"9/4a4/3k5/3N5/3N5/r8/9/9/9/4K4 w"
        //    // 用迭代加深算法来测试效果:迭代加深计算到第8层
        //    // DEBUG
        //    // 不排序时1.7秒,探查并对着法排序时:17秒,代价很大
        //    // Release
        //    // 不排序时0.7秒,探查并对着法排序时:7秒

        //    // if(depth == 0)
        //    //     SortMovelist(moveList, countMove);


        //    //int bestScore = Evaluator.MIN_EVAL_VALUE + depth;

        //    for (int i = 0; i < countMove; i++)
        //    {
        //        board.MakeMove(moveList[i]);
        //        int score = -NegaAlphaBetaTT_old(depth + 1, maxDepth, -beta, -alpha);
        //        board.UnmakeMove(moveList[i]);

        //        // 这里负责记录最佳着法
        //        //if (score > bestScore)
        //        //{
        //        //    bestScore = score;
        //        //    if(depth == 0) bestMove = moveList[i];
        //        //}

        //        if (score >= beta)
        //        {
        //            //PrintDebugInfo("发生剪枝!bestScore >= beta: " + bestScore + " >= " + beta);
        //            // 应该记录该节点!!
        //            NodeOfSearch nodeBeta = new NodeOfSearch(boardHash, depth, maxDepth, NodeOfSearch.CUT_NODES, beta);
        //            transpositionTable.RecordHash(nodeBeta);
        //            return beta;// score;
        //        }
        //        if (score > alpha)
        //        {
        //           // alpha = bestScore;  // alpha = score????
        //            // 这时只是记录alpha值的变化情况,并不写置换表
        //            nodeType = NodeOfSearch.PV_NODES;
        //            alpha = score;
        //            //PrintDebugInfo("修改alpha: " + alpha);
        //        }

        //    }

        //    //int type =
        //    //    (bestScore <= alpha) ?  NodeOfSearch.NODE_TYPE_ALPHA
        //    //    : (bestScore >= beta) ? NodeOfSearch.NODE_TYPE_BETA
        //    //    : NodeOfSearch.NODE_TYPE_EXACT;
        //    //NodeOfSearch node = new NodeOfSearch(boardHash, depth, maxDepth, type, bestScore);
        //    NodeOfSearch node = new NodeOfSearch(boardHash, depth, maxDepth, nodeType, alpha);
        //    transpositionTable.RecordHash(node);
        //    //return bestScore;
        //    return alpha;
        //}

        /// <summary>
        /// 试验数据,对于局面"9/4a4/3k5/3N5/3N5/r8/9/9/9/4K4 w"
        // 用迭代加深算法来测试效果:迭代加深计算到第8层
        // DEBUG
        // 不排序时1.7秒,探查并对着法排序时:17秒,代价很大
        // Release
        // 不排序时0.7秒,探查并对着法排序时:7秒
        /// </summary>
        /// <param name="moveList"></param>
        /// <param name="countMove"></param>
        private void SortMovelist(Move[] moveList, int countMove)
        {
            for (int i = 0; i < countMove; i++)
            {
                board.MakeMove(moveList[i]);
                ulong boardHash = Zobrist.ZoristHash(board);

                // 探查置换表
                //NodeOfSearch entry = transpositionTable.Probe(boardHash);
                //if (entry != null)
                //{
                //    moveList[i].Score = entry.Score;
                //}
                //else
                //    moveList[i].Score = 0;

                board.UnmakeMove(moveList[i]);
            }
            Array.Sort(moveList, 0, countMove);
        }
Esempio n. 3
0
        /// <summary>
        /// 把一盘PGN对局里的前N个着法放入对局库中
        /// </summary>
        /// <param name="pgnFilename">PGN文件名</param>
        /// <returns>加入到开局库时,返回true
        /// 如果在解析PGN时遇到不规范的棋谱时,返回false,此时控制台会打印出错误信息</returns>
        public static bool AddPgnFileToOpeningBook(string bookFilename, string pgnFilename, int maxStep)
        {
            using (OpeningBook book = new OpeningBook(bookFilename))
            {
                // 从PGN文件里读出所有着法来,这里用的是纵列格式
                string[] allmoves = PgnUtil.GetAllMovesFromPgnFile(pgnFilename);

                Board board   = new Board();
                int   numMove = 0; // 记录已走了第几步了
                foreach (string strMove in allmoves)
                {
                    if (numMove >= maxStep)
                    {
                        break;
                    }
                    try
                    {
                        // 走一步后,把盘面生成zobrist值,保存到开局库里
                        // TODO: board.CreateMoveFromString(NotationConverter.Convert(board, strMove));
                        Move move = MoveNotation.CreateMoveFromChineseNotation(board, strMove);
                        board.MakeMove(move);
                        //   Console.WriteLine("==== " + strMove + "\n" + board);
                        ++numMove;
                        ulong zobrist = Zobrist.ZoristHash(board);
                        book.InsertBoardZobrist(zobrist);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("--- " + strMove + " ---");
                        Console.WriteLine(e.Message);
                        Console.WriteLine(board);
                        return(false);
                    }
                } // end 对每一着法循环结束
            }
            return(true);
        }