Пример #1
0
        // Return a numeric array for evaluation
        // Self stone => +1.0, Opponent stone => -1.0, Blank => 0.0
        int[,] GetBoardForEval(int color)
        {
            int[,] arr = new int[8, 8];
            Array.Copy(board, arr, board.Length);

            for (int i = 0; i < arr.GetLength(0); i++)
            {
                for (int j = 0; j < arr.GetLength(1); j++)
                {
                    if (arr[i, j] == color)
                    {
                        arr[i, j] = 1;
                    }
                    else if (arr[i, j] == StoneColor.OppColor(color))
                    {
                        arr[i, j] = -1;
                    }
                    else
                    {
                        arr[i, j] = 0;
                    }
                }
            }
            return(arr);
        }
Пример #2
0
        // Return the 2 dimentional array of the position where the stone is reversible
        internal List <List <Pos> > GetReversibles(Pos pos, int color)
        {
            int[,] directionXY = new int[8, 2]
            {
                { -1, -1 }, { 0, -1 }, { 1, -1 },
                { -1, 0 }, { 1, 0 },
                { -1, 1 }, { 0, 1 }, { 1, 1 }
            };

            List <List <Pos> > reversibleStones = new List <List <Pos> >();

            for (int i = 0; i < directionXY.GetLength(0); i++)
            {
                reversibleStones.Add(new List <Pos>());
            }

            for (int i = 0; i < directionXY.GetLength(0); i++)
            {
                int dx = directionXY[i, 0];
                int dy = directionXY[i, 1];
                int x  = pos.x;
                int y  = pos.y;
                for (int j = 0; j < boardSize; j++)
                {
                    x += dx;
                    y += dy;
                    if (!(0 <= x && x < boardSize && 0 <= y && y < boardSize))
                    {
                        reversibleStones[i] = new List <Pos>();
                        break;
                    }
                    if (board[y, x] == StoneColor.OppColor(color))
                    {
                        reversibleStones[i].Add(new Pos()
                        {
                            x = x, y = y
                        });
                    }
                    else if (board[y, x] == color)
                    {
                        break;
                    }
                    else
                    {
                        reversibleStones[i] = new List <Pos>();
                        break;
                    }
                }
            }
            return(reversibleStones);
        }
Пример #3
0
        // Calculate evaluation value
        internal double Evaluate(int color)
        {
            System.Random r = new System.Random();

            double fs = (Confirms(color) - Confirms(StoneColor.OppColor(color)) + r.NextDouble() * 3) * 11;

            double cn = (Availables(color).Count + r.NextDouble() * 2) * 10;

            double bp = 0.0;

            int[,] tmpBoard = GetBoardForEval(color);
            for (int i = 0; i < boardSize; i++)
            {
                for (int j = 0; j < boardSize; j++)
                {
                    bp += evaluateValue[i, j] * tmpBoard[i, j] * r.NextDouble() * 3;
                }
            }

            return(w1 * bp + w2 * fs + w3 * cn);
        }
Пример #4
0
        // Alpha beta searching with transposition table
        private double AlphaBeta(int[,] board, int color, int depth = 0, double alpha = double.NegativeInfinity, double beta = double.PositiveInfinity)
        {
            nodeCount += 1;

            evaluator.SetBoard(board);

            // Return evaluation value if reaching depth = depthMax or terminal node
            if (depth >= currentDepthMax)
            {
                return(evaluator.Evaluate(selfColor));
            }


            // Return evaluation when game ends
            List <Pos> newOptions    = evaluator.Availables(color);
            List <Pos> oppNewOptions = evaluator.Availables(StoneColor.OppColor(color));

            if (newOptions.Count == 0 && oppNewOptions.Count == 0)
            {
                int selfStones = evaluator.CountStones(selfColor);
                int oppStones  = evaluator.CountStones(StoneColor.OppColor(selfColor));
                if (selfStones > oppStones)
                {
                    return(double.PositiveInfinity);
                }
                else if (selfStones < oppStones)
                {
                    return(double.NegativeInfinity);
                }
                else
                {
                    return(evaluator.Evaluate(selfColor));
                }
            }


            // When only the opponent can put stone, go to next depth
            if (newOptions.Count == 0)
            {
                depth     += 1;
                color      = StoneColor.OppColor(color);
                newOptions = oppNewOptions;
            }


            // Expand board and store the all child boards in children list
            // Associate the child and the action of that time
            List <int[, ]>            children         = new List <int[, ]>();
            Dictionary <int[, ], Pos> actionChildTable = new Dictionary <int[, ], Pos>();

            foreach (Pos action in newOptions)
            {
                Board childBoard = new Board();
                childBoard.SetBoard(board);
                childBoard.UpdateBoard(action, color);
                children.Add(childBoard.GetBoard());
                actionChildTable.Add(childBoard.GetBoard(), action);
            }


            // Sort children in order of the score
            // In descending order when self turn and in ascending order when opponent turn
            st.Start();
            if (depth <= 3)
            {
                children = OrderBoards(children, color);
            }
            st.Stop();


            // Alpha beta searching
            if (color == selfColor)
            {
                // In self turn, search max value of children

                double score = double.NegativeInfinity;

                foreach (int[,] child in children)
                {
                    // Check if the child is stored in transposition table and the node type is EXACT
                    // If it does, set the value for the score
                    // If not, start alpha-beta-searching in next depth and store the score

                    string childHash = BoardToHash(child);

                    if (transpositionTable.ContainsKey(childHash) && transpositionTable[childHash].Depth >= currentDepthMax && transpositionTable[childHash].NodeType == "EXACT")
                    {
                        transpositionCutCount += 1;
                        score = transpositionTable[childHash].Score;
                    }
                    else
                    {
                        score = AlphaBeta(child, StoneColor.OppColor(color), depth + 1, alpha, beta);
                        transpositionTable[childHash] = new TranspositionTableEntry(child, currentDepthMax, score);
                    }


                    if (score > alpha)
                    {
                        alpha = score;

                        // Get best action
                        if (depth == 0)
                        {
                            foreach (KeyValuePair <int[, ], Pos> kvp in actionChildTable)
                            {
                                if (kvp.Key.Cast <int>().SequenceEqual(child.Cast <int>()))
                                {
                                    bestAction = kvp.Value;
                                }
                            }
                        }
                    }

                    // Beta cut
                    if (alpha >= beta)
                    {
                        betaCutCount += 1;
                        break;
                    }
                }
                return(alpha);
            }
            else
            {
                // If the opponent turn, search minimum value of children

                double score = double.PositiveInfinity;

                foreach (int[,] child in children)
                {
                    string childHash = BoardToHash(child);

                    if (transpositionTable.ContainsKey(childHash) && transpositionTable[childHash].Depth >= currentDepthMax && transpositionTable[childHash].NodeType == "EXACT")
                    {
                        transpositionCutCount += 1;
                        score = transpositionTable[childHash].Score;
                    }
                    else
                    {
                        score = AlphaBeta(child, StoneColor.OppColor(color), depth + 1, alpha, beta);
                        transpositionTable[childHash] = new TranspositionTableEntry(child, currentDepthMax, score);
                    }

                    beta = Math.Min(beta, score);

                    // Alpha cut
                    if (beta <= alpha)
                    {
                        alphaCutCount += 1;
                        break;
                    }
                }
                return(beta);
            }
        }
Пример #5
0
 void Reverse(Pos pos)
 {
     board[pos.y, pos.x] = StoneColor.OppColor(board[pos.y, pos.x]);
 }