Exemple #1
0
    public ulong Reverse(int x, int y, Stone.ColorType color)
    {
        var mask = 0x8000000000000000;
        var move = mask >> (x + y * 8);

        return(Reverse(move, color));
    }
Exemple #2
0
    //浅い探索を行いソートした合法手を得る
    private List <ulong> GetSortedMovailable(Stone.ColorType color, float alpha, float beta)
    {
        sortedMoves.Clear();

        var movable = board.GetMovableBitBoard(color);

        while (movable != 0)
        {
            var next = GetLeastSignificantBit(movable);

            board.Log();
            board.Reverse(next, color);

            var eval = -NegaAlpha(Stone.GetReverseColor(color), 1,
                                  -beta, -alpha);

            board.Undo();

            sortedMoves.Add(next, eval);

            movable ^= next;
        }

        return(sortedMoves.OrderByDescending(s => s.Value).Select(x => x.Key).ToList <ulong>());
    }
Exemple #3
0
    public void Move(int x, int y, Stone.ColorType color)
    {
        var mask = 0x8000000000000000;
        var move = mask >> x + y * 8;

        bitBoards[(int)color] |= move;
    }
Exemple #4
0
    //合法手を描画
    public void RenderMarks(List <Vector2Int> movable, Stone.ColorType color)
    {
        marks.ForEach(m => Destroy(m.gameObject));
        marks.Clear();

        RenderMovableMarks(movable, color);
    }
Exemple #5
0
    public ulong Reverse(ulong move, Stone.ColorType color)
    {
        int   c           = (int)color;
        var   opponent    = bitBoards[c ^ 1];
        ulong allReversed = 0;
        ulong lineReversed;

        //一方向ずつ反転できる石を探し重ね合わせる
        for (var i = 0; i < 8; i++)
        {
            var next = ShiftBitboard(move, i);
            lineReversed = 0;

            while (next != 0 && (next & opponent) != 0)
            {
                lineReversed |= next;
                next          = ShiftBitboard(next, i);
            }

            if ((next & bitBoards[c]) != 0)
            {
                allReversed |= lineReversed;
            }
        }

        //石を置き、反転させる。
        bitBoards[c]     |= move | allReversed;
        bitBoards[c ^ 1] ^= allReversed;

        return(allReversed);
    }
Exemple #6
0
    public static float Evaluate(LogicBoard logicBoard, Stone.ColorType corrent)
    {
        board = logicBoard;

        var currentBit     = board.CurrentBitBoards[(int)corrent];
        int currentMovable = CountMovableCells(corrent);

        EdgeEvaluator.Setup(currentBit);
        int currentStable = EdgeEvaluator.CountStableStone(currentBit);
        int currentCMove  = EdgeEvaluator.CountCMove(currentBit);
        int currentXMove  = EdgeEvaluator.CountXMove(currentBit);

        var opponentColor = Stone.GetReverseColor(corrent);

        var opponentBit     = board.CurrentBitBoards[(int)opponentColor];
        int opponentMovable = CountMovableCells(opponentColor);

        EdgeEvaluator.Setup(opponentBit);
        int opponentStable = EdgeEvaluator.CountStableStone(opponentBit);
        int opponentCMove  = EdgeEvaluator.CountCMove(opponentBit);
        int opponentXMove  = EdgeEvaluator.CountXMove(opponentBit);

        float eval = (currentMovable - opponentMovable) * mobilityWeight +
                     (currentStable - opponentStable) * stableWeight +
                     (currentCMove - opponentCMove) * cMoveWeight +
                     (currentXMove - opponentXMove) * xMoveWeight;

        return(eval);
    }
Exemple #7
0
    private void RenderMovableMarks(List <Vector2Int> points, Stone.ColorType color)
    {
        points.ForEach(p =>
        {
            var cell = GetCell(p);

            var mark = cell.CreateMark(color);
            marks.Add(mark);
        });
    }
Exemple #8
0
    //全てを描画
    public void RenderAll(List <Vector2Int> blacks, List <Vector2Int> whites,
                          List <Vector2Int> movable, Stone.ColorType color)
    {
        Clear();
        blacks.ForEach(p => RenderOne(p, Stone.ColorType.Black));
        whites.ForEach(p => RenderOne(p, Stone.ColorType.White));

        RenderMovableMarks(movable, color);

        if (lastMoved != null)
        {
            Destroy(lastMoved.gameObject);
        }
    }
Exemple #9
0
    //最善手を探す
    public Vector2Int Search(LogicBoard logicBoard, Stone.ColorType color)
    {
        board = logicBoard;
        ulong found   = 0;
        var   maxEval = Mathf.NegativeInfinity;
        var   beta    = Mathf.Infinity;
        var   a       = Mathf.NegativeInfinity;
        var   b       = beta;

        var movables = GetSortedMovailable(color, a, b);

        if (movables.Count == 1)
        {
            return(LogicBoard.BitToPoints(movables[0])[0]);
        }

        for (int i = 0; i < movables.Count; i++)
        {
            var p = movables[i];

            board.Log();
            board.Reverse(p, color);

            var eval = -NegaScout(Stone.GetReverseColor(color), depth - 1,
                                  -b, -a);

            //最初の子ノードは再探索しない(ソートがうまくいっていれば評価が最大だから?)
            //葉から2つ以内のノードは再探索しない(なぜ?)
            if (i != 0 && depth > 2 && eval > a && eval < beta)
            {
                eval = -NegaScout(Stone.GetReverseColor(color), depth - 1,
                                  -beta, -eval);
            }

            board.Undo();

            if (maxEval < eval)
            {
                a       = Mathf.Max(a, eval);
                maxEval = eval;
                found   = p;
            }

            b = a + 1;
        }

        return(LogicBoard.BitToPoints(found)[0]);
    }
Exemple #10
0
    //NegaAlpha法
    private float NegaAlpha(Stone.ColorType color, int depth,
                            float alpha, float beta)
    {
        if (depth == 0)
        {
            return(Evaluator.Evaluate(board, color));
        }

        var movable = board.GetMovableBitBoard(color);

        if (LogicBoard.CountBit(movable) == 0)
        {
            board.Log();

            var eval = -NegaAlpha(Stone.GetReverseColor(color), depth - 1,
                                  -beta, -alpha);

            board.Undo();

            return(eval);
        }

        while (movable != 0)
        {
            ulong next = GetLeastSignificantBit(movable);

            board.Log();
            board.Reverse(next, color);

            var eval = -NegaAlpha(Stone.GetReverseColor(color), depth - 1,
                                  -beta, -alpha);

            board.Undo();

            if (beta <= eval)
            {
                return(eval);
            }

            alpha = Mathf.Max(eval, alpha);

            movable ^= next;
        }

        return(alpha);
    }
Exemple #11
0
    private Player CreatePlayer(int n, Stone.ColorType color)
    {
        Player p;

        if (n == 0)
        {
            p = new Human();
        }
        else
        {
            p = new Computer(n);
        }

        p.Color = color;

        return(p);
    }
Exemple #12
0
    //指した石を描画
    public void RenderOne(Vector2Int p, Stone.ColorType color)
    {
        var cell = GetCell(p);

        if (stones.Exists(s => s.X == p.x && s.Y == p.y))
        {
            throw new Exception("duplication");
        }

        var stone = cell.CreateStone(color);

        stones.Add(stone);

        //最後の手
        if (lastMoved != null)
        {
            Destroy(lastMoved.gameObject);
        }
        lastMoved = cell.CreateMoved();
    }
Exemple #13
0
    //合法手を返す
    public ulong GetMovableBitBoard(Stone.ColorType color)
    {
        var current  = bitBoards[(int)color];
        var opponent = bitBoards[(int)color ^ 1];
        //左右のセルを除いた相手の盤の状態
        var horizontalWatcher = opponent & 0x7e7e7e7e7e7e7e7e;
        //上下のセルを除いた相手の盤の状態
        var verticalWatcher = opponent & 0x00ffffffffffff00;
        //上下左右のセルを除いた相手の盤の状態
        var allSideWatcher = opponent & 0x007e7e7e7e7e7e00;
        var empty          = ~(current | opponent);

        //8方向それぞれの合法手を調べ重ね合わせる
        var movable = GetMovableBitBoardInLine(current, empty, horizontalWatcher,
                                               c => c << 1);

        movable |= GetMovableBitBoardInLine(current, empty, horizontalWatcher,
                                            c => c >> 1);

        movable |= GetMovableBitBoardInLine(current, empty, verticalWatcher,
                                            c => c << 8);

        movable |= GetMovableBitBoardInLine(current, empty, verticalWatcher,
                                            c => c >> 8);

        movable |= GetMovableBitBoardInLine(current, empty, allSideWatcher,
                                            c => c << 7);

        movable |= GetMovableBitBoardInLine(current, empty, allSideWatcher,
                                            c => c >> 7);

        movable |= GetMovableBitBoardInLine(current, empty, allSideWatcher,
                                            c => c << 9);

        movable |= GetMovableBitBoardInLine(current, empty, allSideWatcher,
                                            c => c >> 9);

        return(movable);
    }
Exemple #14
0
    //NegaScout法
    private float NegaScout(Stone.ColorType color, int depth,
                            float alpha, float beta)
    {
        if (depth == 0)
        {
            return(Evaluator.Evaluate(board, color));
        }

        var movables = GetSortedMovailable(color, alpha, beta);

        if (movables.Count == 0)
        {
            board.Log();

            var eval = -NegaScout(Stone.GetReverseColor(color), depth - 1,
                                  -beta, -alpha);

            board.Undo();

            return(eval);
        }

        var maxEval = Mathf.NegativeInfinity;
        var a       = alpha;
        var b       = beta;

        for (int i = 0; i < movables.Count; i++)
        {
            var p = movables[i];

            board.Log();
            board.Reverse(p, color);

            var eval = -NegaScout(Stone.GetReverseColor(color), depth - 1,
                                  -b, -a);

            //最初の子ノードは再探索しない(ソートがうまくいっていれば評価が最大だから?)
            //葉から2つ以内のノードは再探索しない(なぜ?)
            if (i != 0 && depth > 2 && eval > a && eval < beta)
            {
                eval = -NegaScout(Stone.GetReverseColor(color), depth - 1,
                                  -beta, -eval);
            }

            board.Undo();

            if (maxEval < eval)
            {
                if (beta <= eval)
                {
                    return(eval);
                }

                a       = Mathf.Max(a, eval);
                maxEval = eval;
            }

            b = a + 1;
        }

        //子ノードの最大値を返す(fail-soft)
        return(maxEval);
    }
Exemple #15
0
    //合法手の数を取得
    private static int CountMovableCells(Stone.ColorType color)
    {
        var movable = board.GetMovableBitBoard(color);

        return(LogicBoard.CountBit(movable));
    }
Exemple #16
0
 public void Show(Stone.ColorType color)
 {
     image.sprite = passSprites[(int)color];
 }