コード例 #1
0
        /// <summary>
        ///     Counts the amount of leafNode at the parameter input depth,
        ///     by an inorder recursive tree traversion algorithm.
        ///     It checks all legal moves with the parameter input depth,
        ///     and increments the leafNode counter when the "last" move
        ///     (the leaf) has been located.
        /// </summary>
        /// <param name="depth"> The depth to traverse </param>
        /// <param name="board"> The chess board operate on </param>
        /// <exception cref="Exception"></exception>
        public void _Perft(int depth, Board board)   // For counting the TOTAL available moves
        {
            Debug.Assert(BoardOperations.CheckBoard(board));
            // Increment leafNode and return.
            if (depth == 0)
            {
                LeafNodes++;
                return;
            }

            // Generate moves for rootposition
            MoveList list = new MoveList();

            MoveGen.GenerateAllMoves(board, list, false);

            for (int i = 0; i < list.Count; ++i)
            {
                if (!MakeMove.Make_Move(board, list.Moves[i].Move))
                {
                    continue;
                }

                _Perft(depth - 1, board);
                MakeMove.TakeMove(board);
            }
        }
コード例 #2
0
        public void Perft_Test(int depth, Board board)   // Also prints information regarding the moves
        {
            Debug.Assert(BoardOperations.CheckBoard(board));
            var startTime = Variables.Watch.ElapsedMilliseconds;

            Console.Write("\nStarting Perft Test to Depth {0}", depth);
            BoardOperations.PrintBoard(board);

            LeafNodes = 0;

            MoveList list = new MoveList();

            MoveGen.GenerateAllMoves(board, list, false);


            for (int i = 0; i < list.Count; ++i)
            {
                int move = list.Moves[i].Move;

                if (!MakeMove.Make_Move(board, list.Moves[i].Move))
                {
                    continue;
                }

                long cumulativeNodes = LeafNodes;
                _Perft(depth - 1, board);
                MakeMove.TakeMove(board);
                long oldNodes = LeafNodes - cumulativeNodes;
                Console.Write("\nmove {0} : {1} : {2}", i + 1, Io.MoveToString(move), oldNodes);
            }

            Console.Write("\nTest Complete: {0} nodes visited in {1} miliseconds\n", LeafNodes, Variables.Watch.ElapsedMilliseconds - startTime);
        }
コード例 #3
0
        protected override ActionContext DoAction(ActionContext context)
        {
            if (context.Game == null)
            {
                throw new InvalidOperationException("Action context missing required property (Game)");
            }
            if (context.Board == null)
            {
                throw new InvalidOperationException("Action context missing required property (Board)");
            }
            GameActionData actionData = MakeActionData(context);

            Game  game  = context.Game;
            Board board = context.Board;

            string[] turnOrder = game.TurnOrder;
            game.CurrentTurn++;
            game.CurrentTurn %= turnOrder.Length;
            game.turnCount++;
            game.TilesActiveThisTurn = new int[0];

            if (game.FirstPlayer != game.CurrentPlayer)
            {
                game.AddGameAction(actionData);
                return(context);
            }
            game.CurrentTurn++;
            game.CurrentTurn %= turnOrder.Length;
            game.FirstPlayer  = turnOrder[game.CurrentTurn];
            game.SunPosition  =
                (SunPosition)(((int)game.SunPosition + 1) % Enum.GetNames(typeof(SunPosition)).Length);

            if (game.SunPosition == SunPosition.NorthWest)
            {
                game.Revolution++;
                if (game.Revolution == game.LengthOfGame)
                {
                    game.Status = GameStatus.Ended;
                    game.AddGameAction(actionData);
                    context.Game  = game;
                    context.Board = board;
                    return(context);
                }
            }

            board.Tiles = Shadow.UpdateAllShadows(board, game.SunPosition);
            foreach (string playerId in game.TurnOrder)
            {
                PlayerBoard playerBoard = PlayerBoard.Get(game, playerId);
                int         earnedLight = BoardOperations.CountLight(board, playerBoard.TreeType);
                Console.WriteLine($"{playerId} - {earnedLight}");
                playerBoard.RecoverLight(earnedLight);
                game.SetPlayerBoard(playerId, playerBoard);
            }
            game.AddGameAction(actionData);
            return(context);
        }
コード例 #4
0
    private void PrintIfGameOver()
    {
        var winner = BoardOperations.GetBoardWinner(_grid.Cells, toWin);

        if (winner == Winner.Draw && BoardOperations.HasAnyMovesLeft(_grid.Cells))
        {
            return;
        }
        _text.SetText(winner == Winner.Draw ? "Draw" : winner == (player == CellType.X ? Winner.X : Winner.O) ? "You won" : "You lose");
        _text.gameObject.SetActive(true);
        StartCoroutine(WaitAndExit());
    }
コード例 #5
0
        public void Should_AddWorkItemToBoard()
        {
            //Arrange
            var boardOperations = new BoardOperations();
            var mockBoard       = new Mock <IBoard>();
            var mockWorkitem    = new Mock <IBug>();

            mockBoard.Setup(x => x.WorkItems).Returns(new List <IWorkItem>());

            //Act
            boardOperations.AddWorkitemToBoard(mockBoard.Object, mockWorkitem.Object);

            //Assert
            Assert.IsTrue(mockBoard.Object.WorkItems.Contains(mockWorkitem.Object));
        }
コード例 #6
0
        public void Should_AddActivityHistoryToBoard()
        {
            //Arrange
            var boardOperations = new BoardOperations();
            var mockBoard       = new Mock <IBoard>();
            var mockWorkItem    = new Mock <IBug>();

            mockBoard.Setup(x => x.WorkItems).Returns(new List <IWorkItem>());
            mockWorkItem.Setup(x => x.Title).Returns("Bug1234567");
            mockBoard.Setup(x => x.ActivityHistory).Returns(new List <IActivityHistory>());

            //Act
            boardOperations.AddActivityHistoryToBoard(mockBoard.Object, mockWorkItem.Object);

            //Assert
            Assert.AreEqual(mockBoard.Object.ActivityHistory.First().Message, "A IBugProxy with Title: Bug1234567");
        }
コード例 #7
0
        public void Should_AddActivityHistoryToBoardForAssignAndUnassign()
        {
            //Arrange
            var boardOperations    = new BoardOperations();
            var mockBoard          = new Mock <IBoard>();
            var mockMemberAssign   = new Mock <IMember>();
            var mockMemberUnassign = new Mock <IMember>();

            mockBoard.Setup(x => x.WorkItems).Returns(new List <IWorkItem>());
            mockMemberAssign.Setup(x => x.Name).Returns("Edward");
            mockMemberUnassign.Setup(x => x.Name).Returns("Kiro");
            mockBoard.Setup(x => x.ActivityHistory).Returns(new List <IActivityHistory>());
            string type          = "bug";
            string workItemTitle = "bug1234567";

            //Act
            boardOperations.AddActivityHistoryAfterAssignUnsignToBoard(mockBoard.Object, type, workItemTitle, mockMemberAssign.Object, mockMemberUnassign.Object);

            //Assert
            Assert.AreEqual(mockBoard.Object.ActivityHistory.First().Message, "A bug with Title: bug1234567 was unassigned from Kiro and assigned to Edward");
        }
コード例 #8
0
        public void DepthK(int k)
        {
            for (int i = 0; i < perftSuite.Length - 1; ++i)
            {
                string line  = perftSuite[i];
                string fen   = "";
                int    index = 0;

                // Locate the FEN
                for (int j = 0; j < line.Length; j++)
                {
                    if (line[j] == ';')
                    {
                        fen   = line.Substring(0, j - 1);
                        index = j;
                        break;
                    }
                }

                for (int j = 1; j < k; j++)
                {
                    FindNextSemiColon(ref index, line);
                    index++;
                }

                FindNextSemiColon(ref index, line);

                index += 4;
                int depthInt = FindExpectedDepthVal(index, line);

                BoardOperations.ParseFen(fen, board);
                MoveGen.GenerateAllMoves(board, moveList, false);

                perft.Perft_Test(k, board);
                Assert.AreEqual(perft.LeafNodes, depthInt);
            }
        }
コード例 #9
0
        // should read "position fen"
        //             "position startpos"
        // which could possibly be followed by  "... moves a2a3 a3a4" etc.
        public void ParsePosition(string lineIn, Board board)
        {
            int stringIndex = 9;                       // starts at 9 cause position is length 8
            int moveIndex   = lineIn.IndexOf("moves"); // is there any moves to consider?

            if (lineIn.Length >= stringIndex + 8 &&
                lineIn.Substring(stringIndex, 8).Equals("startpos"))
            {
                BoardOperations.ParseFen(Fens.START_FEN, board);
            }
            else     // Else "position fen fenstring"
            {
                if (lineIn.Length >= stringIndex + 3 &&
                    lineIn.Substring(stringIndex, 3).Equals("fen"))
                {
                    stringIndex += 4; // should be at start of fenstring now.
                    if (moveIndex == -1)
                    {
                        BoardOperations.ParseFen(lineIn.Substring(stringIndex), board);
                    }
                    else
                    {
                        BoardOperations.ParseFen(
                            lineIn.Substring(stringIndex, moveIndex - stringIndex - 1), board);
                    }
                }
                else
                {
                    BoardOperations.ParseFen(Fens.START_FEN, board);
                }
            }

            if (moveIndex != -1)             // moves were found.
            {
                stringIndex = moveIndex + 6; // We are now at start of command moves. moves |a2a3
                int move = Variables.NO_MOVE;

                while (stringIndex <= lineIn.Length - 1)
                {
                    stringIndex += 5;

                    if (lineIn.Length > stringIndex && lineIn[stringIndex - 1] == ' ')
                    {
                        move = Io.ParseMove(board, lineIn.Substring(stringIndex - 5, 4).ToCharArray()); // not a promotion move.
                    }
                    else if (stringIndex == lineIn.Length + 1)                                          // if at last move
                    {
                        move = Io.ParseMove(board,
                                            lineIn.Substring(stringIndex - 5, 4).ToCharArray());
                    }
                    else if (stringIndex == lineIn.Length)     // promotion move at end of line
                    {
                        move = Io.ParseMove(board,
                                            lineIn.Substring(stringIndex - 5, 5).ToCharArray());
                    }
                    else if (lineIn.Length >= stringIndex && lineIn[stringIndex - 1] != ' ')
                    {
                        move = Io.ParseMove(board,
                                            lineIn.Substring(stringIndex - 5, 5).ToCharArray());
                        stringIndex++;
                    }

                    if (move == Variables.NO_MOVE)
                    {
                        break;
                    }

                    MakeMove.Make_Move(board, move);
                    board.Ply = 0;
                }
            }

            BoardOperations.PrintBoard(board);
        }
コード例 #10
0
        /// <summary>
        /// Validates whether the parameter square is attacked by input side.
        /// </summary>
        /// <param name="sq"> The square to validate </param>
        /// <param name="side"> The side to check for attacks </param>
        /// <param name="board"> The current board </param>
        /// <returns> True or false depending on whether the sq is attacked </returns>
        /// <exception cref="Exception"></exception>
        public static bool IsSqAttacked(int sq, int side, Board.Board board)
        {
            Debug.Assert(Validators.SqOnBoard(sq), String.Format("Square {0} on board is invalid", sq));
            Debug.Assert(Validators.SideValid(side), String.Format("Side {0} on board is invalid", side));
            Debug.Assert(BoardOperations.CheckBoard(board), String.Format("Checkboard is false"));

            // first checking pawns
            if (side == (int)Colour.WHITE)
            {
                if (board[sq - 9] == (int)Piece.wP || board[sq - 11] == (int)Piece.wP)
                {
                    return(true);
                }
            }
            else
            {
                // side black
                if (board[sq + 9] == (int)Piece.bP || board[sq + 11] == (int)Piece.bP)
                {
                    return(true);
                }
            }

            // knights
            for (var i = 0; i < Attack.KN_DIR.Length; ++i)
            {
                var piece = board[sq + Attack.KN_DIR[i]];
                if (piece == (int)Piece.EMPTY || piece == (int)Square.NO_SQ)
                {
                    continue;
                }

                if (Data.IsPieceKnight(piece) && (int)Data.PIECE_COLOURS[piece] == side)
                {
                    return(true);
                }
            }

            // Rooks queens
            for (var i = 0; i < Attack.RK_DIR.Length; ++i)
            {
                var square = sq + Attack.RK_DIR[i];
                var piece  = board[square];
                while (Validators.IsSq(square))
                {
                    if (piece != (int)Piece.EMPTY)
                    {
                        if (Data.IsPieceRookQueen(piece) &&
                            (int)Data.PIECE_COLOURS[piece] == side)
                        {
                            return(true);
                        }

                        break;
                    }

                    square += Attack.RK_DIR[i];
                    piece   = board[square];
                }
            }

            // Bishop queens
            for (var i = 0; i < Attack.BI_DIR.Length; ++i)
            {
                var square = sq + Attack.BI_DIR[i];
                var piece  = board[square];
                while (Validators.IsSq(square))
                {
                    if (piece != (int)Piece.EMPTY)
                    {
                        if (Data.IsPieceBishopQueen(piece) &&
                            (int)Data.PIECE_COLOURS[piece] == side)
                        {
                            return(true);
                        }

                        break;
                    }

                    square += Attack.BI_DIR[i];
                    piece   = board[square];
                }
            }

            // Kings
            for (var i = 0; i < Attack.KI_DIR.Length; ++i)
            {
                var piece = board[sq + Attack.KI_DIR[i]];
                if (piece == (int)Piece.EMPTY || piece == (int)Square.NO_SQ)
                {
                    continue;
                }

                if (Data.IsPieceKing(piece) && (int)Data.PIECE_COLOURS[piece] == side)
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #11
0
ファイル: PlayerController.cs プロジェクト: etopuz/Flood-It
 private void Awake()
 {
     boardOperations = GetComponent <BoardOperations>();
     uI = GameObject.FindWithTag("UserPanel").GetComponent <UpdateUI>();
 }
コード例 #12
0
        /// <summary>
        /// Generates all available moves for the current position on the board in the parameter MoveList.
        /// If the onlyCaptures parameter is true, it will only generate capture moves.
        /// </summary>
        /// <param name="board"> The current board position </param>
        /// <param name="list"> The MoveList to parse the available moves to. </param>
        /// <param name="onlyCaptures"> True if only generating for captures. </param>
        public static void GenerateAllMoves(Board.Board board, MoveList list, bool onlyCaptures)
        {
            Debug.Assert(BoardOperations.CheckBoard(board));
            list.Count = 0;

            var side  = (Colour)board.Side;
            var piece = side == Colour.WHITE ? (int)Piece.wP : (int)Piece.bP;

            for (var pceNum = 0; pceNum < board.PceNum[piece]; ++pceNum)
            {
                var sq = board.PList[piece, pceNum];
                Debug.Assert(Validators.IsSq(sq), String.Format("Sq {0} is invalid", sq));
                var leftCaptureSq  = side == Colour.WHITE ? sq + 9 : sq - 9;
                var rightCaptureSq = side == Colour.WHITE ? sq + 11 : sq - 11;

                if (!onlyCaptures)
                {
                    var sqInfront = side == Colour.WHITE ? sq + 10 : sq - 10;
                    if (board[sqInfront] == (int)Piece.EMPTY && Validators.SqOnBoard(sqInfront))
                    {
                        if (side == Colour.WHITE)
                        {
                            MoveGen.AddWhitePawnMove(board, sq, sqInfront, list);

                            // Check if the number two square infront of the pawn is empty and that the rank is 2.
                            if (Conversion.getRanksBrd(sq) == (int)Rank.RANK_2 &&
                                board[sq + 20] == (int)Piece.EMPTY)
                            {
                                MoveGen.AddQuietMove(board,
                                                     MoveOperations.CreateMove(sq, sq + 20, (int)Piece.EMPTY,
                                                                               (int)Piece.EMPTY, MoveOperations.MoveFlagPawnStart), list);
                            }
                        }
                        else     // BLACK
                        {
                            MoveGen.AddBlackPawnMove(board, sq, sqInfront, list);

                            // Check if the number two square infront of the pawn is empty and that the rank is 7.
                            if (Conversion.getRanksBrd(sq) == (int)Rank.RANK_7 &&
                                board[sq - 20] == (int)Piece.EMPTY)
                            {
                                MoveGen.AddQuietMove(board,
                                                     MoveOperations.CreateMove(sq, sq - 20, (int)Piece.EMPTY,
                                                                               (int)Piece.EMPTY, MoveOperations.MoveFlagPawnStart), list);
                            }
                        }
                    }
                }

                if (Validators.IsSq(leftCaptureSq) &&
                    Data.PIECE_COLOURS[board[leftCaptureSq]] == (Colour)((int)side ^ 1))
                {
                    if (side == Colour.WHITE)
                    {
                        MoveGen.AddWhitePawnCapMove(board, sq, leftCaptureSq, board[leftCaptureSq],
                                                    list);
                    }
                    else
                    {
                        // BLACK
                        MoveGen.AddBlackPawnCapMove(board, sq, leftCaptureSq, board[leftCaptureSq],
                                                    list);
                    }
                }

                if (Validators.IsSq(rightCaptureSq) &&
                    Data.PIECE_COLOURS[board[rightCaptureSq]] == (Colour)((int)side ^ 1))
                {
                    if (side == Colour.WHITE)
                    {
                        MoveGen.AddWhitePawnCapMove(board, sq, rightCaptureSq,
                                                    board[rightCaptureSq], list);
                    }
                    else
                    {
                        // BLACK
                        MoveGen.AddBlackPawnCapMove(board, sq, rightCaptureSq,
                                                    board[rightCaptureSq], list);
                    }
                }

                if (Validators.IsSq(board.EnPas))
                {
                    if (leftCaptureSq == board.EnPas)
                    {
                        MoveGen.AddEnPassantMove(board, MoveOperations.CreateMove(sq, leftCaptureSq,
                                                                                  (int)Piece.EMPTY
                                                                                  , (int)Piece.EMPTY, MoveOperations.MoveFlagEnPas), list);
                    }
                    else if (rightCaptureSq == board.EnPas)
                    {
                        MoveGen.AddEnPassantMove(board, MoveOperations.CreateMove(sq,
                                                                                  rightCaptureSq, (int)Piece.EMPTY
                                                                                  , (int)Piece.EMPTY, MoveOperations.MoveFlagEnPas), list);
                    }
                }
            }

            // Castling
            if (!onlyCaptures)
            {
                if (side == Colour.WHITE)
                {
                    // If there is White King Castle Permission.
                    if ((board.CastlePerm & (int)Castling.WKCA) != 0)
                    {
                        // Check if squares are empty before we call the less efficient SqAttacked method.
                        var isSqG1F1Empty = board[(int)Square.F1] == (int)Piece.EMPTY && board[
                            (int)Square.G1] == (int)Piece.EMPTY;
                        if (isSqG1F1Empty)
                        {
                            var IsSqE1OrF1NotAtt =
                                !Attack.IsSqAttacked((int)Square.F1, (int)Colour.BLACK, board) &&
                                !Attack.IsSqAttacked((int)Square.E1, (int)Colour.BLACK, board);
                            if (IsSqE1OrF1NotAtt)
                            {
                                MoveGen.AddQuietMove(board,
                                                     MoveOperations.CreateMove((int)Square.E1, (int)Square.G1,
                                                                               (int)Piece.EMPTY, (int)Piece.EMPTY,
                                                                               MoveOperations.MoveFlagCastle), list);
                            }
                        }
                    }

                    // If there is White Queen Castle Permission.
                    if ((board.CastlePerm & (int)Castling.WQCA) != 0)
                    {
                        var isSqB1C1D1Empty = board[(int)Square.B1] == (int)Piece.EMPTY &&
                                              board[(int)Square.C1] == (int)Piece.EMPTY &&
                                              board[(int)Square.D1] == (int)Piece.EMPTY;
                        if (isSqB1C1D1Empty)
                        {
                            var isSqE1OrD1NotAtt =
                                !Attack.IsSqAttacked((int)Square.E1, (int)Colour.BLACK, board) &&
                                !Attack.IsSqAttacked((int)Square.D1, (int)Colour.BLACK, board);
                            if (isSqE1OrD1NotAtt)
                            {
                                MoveGen.AddQuietMove(board,
                                                     MoveOperations.CreateMove((int)Square.E1, (int)Square.C1,
                                                                               (int)Piece.EMPTY, (int)Piece.EMPTY,
                                                                               MoveOperations.MoveFlagCastle), list);
                            }
                        }
                    }
                }
                else
                {
                    // If there is Black King Castle Permission.
                    if ((board.CastlePerm & (int)Castling.BKCA) != 0)
                    {
                        // Check if squares are empty before we call the less efficient SqAttacked method.
                        var isSqG8F8Empty = board[(int)Square.F8] == (int)Piece.EMPTY &&
                                            board[(int)Square.G8] == (int)Piece.EMPTY;
                        if (isSqG8F8Empty)
                        {
                            var isSqE8F8NotAttacked =
                                !Attack.IsSqAttacked((int)Square.E8, (int)Colour.WHITE, board) &&
                                !Attack.IsSqAttacked((int)Square.F8, (int)Colour.WHITE, board);
                            if (isSqE8F8NotAttacked)
                            {
                                MoveGen.AddQuietMove(board,
                                                     MoveOperations.CreateMove((int)Square.E8, (int)Square.G8,
                                                                               (int)Piece.EMPTY, (int)Piece.EMPTY,
                                                                               MoveOperations.MoveFlagCastle), list);
                            }
                        }
                    }

                    // If there is White Queen Castle Permission.
                    if ((board.CastlePerm & (int)Castling.BQCA) != 0)
                    {
                        // Check if squares are empty before we call the less efficient SqAttacked method.
                        var isSqB8C8D8Empty = board[(int)Square.B8] == (int)Piece.EMPTY &&
                                              board[(int)Square.C8] == (int)Piece.EMPTY &&
                                              board[(int)Square.D8] == (int)Piece.EMPTY;

                        if (isSqB8C8D8Empty)
                        {
                            var isSqE8D8NotAttacked =
                                !Attack.IsSqAttacked((int)Square.E8, (int)Colour.WHITE, board) &&
                                !Attack.IsSqAttacked((int)Square.D8, (int)Colour.WHITE, board);
                            if (isSqE8D8NotAttacked)
                            {
                                MoveGen.AddQuietMove(board,
                                                     MoveOperations.CreateMove((int)Square.E8, (int)Square.C8,
                                                                               (int)Piece.EMPTY, (int)Piece.EMPTY,
                                                                               MoveOperations.MoveFlagCastle), list);
                            }
                        }
                    }
                }
            }

            // Loop sliding pieces
            var pceIndex = MoveGen.LOOP_SLIDE_INDEX[board.Side];
            // Increments AFTER it's run
            var pce = MoveGen.LOOP_SLIDE_PCE[pceIndex++];

            while (pce != 0)
            {
                Debug.Assert(Validators.PieceValid(pce),
                             String.Format("You have reached an invalid sliding piece {0}", pce));
                for (var pceNum = 0; pceNum < board.PceNum[pce]; ++pceNum)
                {
                    var sq = board.PList[pce, pceNum];

                    // Square check
                    Debug.Assert(Validators.IsSq(sq), String.Format("Sq {0} is false", sq));

                    for (var index = 0; index < MoveGen.NUM_DIR[pce]; ++index)
                    {
                        var t_sq = sq + MoveGen.PCE_DIR[pce, index];
                        // Check if offboard
                        if (!Validators.SqOnBoard(t_sq))
                        {
                            continue;
                        }

                        while (Validators.SqOnBoard(t_sq))
                        {
                            if (board[t_sq] != (int)Piece.EMPTY)
                            {
                                // 0 EXCLUSIVE OR 1 returns 1 = COLOUR.WHITE
                                // 1 EXCLUSIVE OR 1 returns 0 = COLOUR.BLACK
                                if ((int)Data.PIECE_COLOURS[board[t_sq]] == (board.Side ^ 1))
                                {
                                    AddCaptureMove(board, MoveOperations.CreateMove(sq, t_sq, board[t_sq], (int)Piece.EMPTY, 0), list);
                                }

                                break;
                            }

                            if (!onlyCaptures)
                            {
                                AddQuietMove(board,
                                             MoveOperations.CreateMove(sq, t_sq, (int)Piece.EMPTY,
                                                                       (int)Piece.EMPTY, 0), list);
                            }
                            t_sq += MoveGen.PCE_DIR[pce, index];
                        }
                    }
                }

                pce = MoveGen.LOOP_SLIDE_PCE[pceIndex++];
            }

            // Loop non_sliding pieces
            pceIndex = MoveGen.LOOP_NON_SLIDE_INDEX[board.Side];
            pce      = MoveGen.LOOP_NON_SLIDE_PCE[pceIndex++];

            while (pce != 0)
            {
                Debug.Assert(Validators.PieceValid(pce), String.Format("You have reached an invalid sliding piece {0}", pce));

                for (var pceNum = 0; pceNum < board.PceNum[pce]; ++pceNum)
                {
                    var sq = board.PList[pce, pceNum];

                    // Square check
                    Debug.Assert(Validators.IsSq(sq), String.Format("Sq {0} is invalid", sq));

                    for (var index = 0; index < MoveGen.NUM_DIR[pce]; ++index)
                    {
                        var t_sq = sq + MoveGen.PCE_DIR[pce, index];

                        // Check if offboard
                        if (!Validators.SqOnBoard(t_sq))
                        {
                            continue;
                        }

                        if (board[t_sq] != (int)Piece.EMPTY)
                        {
                            // 0 EXCLUSIVE OR 1 returns 1 = COLOUR.WHITE
                            // 1 EXCLUSIVE OR 1 returns 0 = COLOUR.BLACK
                            if ((int)Data.PIECE_COLOURS[board[t_sq]] == (board.Side ^ 1))
                            {
                                AddCaptureMove(board, MoveOperations.CreateMove(sq, t_sq, board[t_sq], (int)Piece.EMPTY, 0), list);
                            }

                            continue;
                        }

                        if (!onlyCaptures)
                        {
                            AddQuietMove(board,
                                         MoveOperations.CreateMove(sq, t_sq, (int)Piece.EMPTY,
                                                                   (int)Piece.EMPTY, 0), list);
                        }
                    }
                }


                pce = MoveGen.LOOP_NON_SLIDE_PCE[pceIndex++];
            }
        }
コード例 #13
0
ファイル: Search.cs プロジェクト: Woldbye/LINKcs
        public int AlphaBeta(int alpha, int beta, int depth, ref S_SearchInfo info, bool DoNull)
        {
            Debug.Assert(BoardOperations.CheckBoard(board));

            if (depth == 0)
            {
                return(Quiescence(alpha, beta, ref info));
            }

            if ((info.Nodes & 2047) == 0)
            {
                CheckUp(ref info);
            }

            info.Nodes++;

            // If position is a draw.
            if ((IsRepetition() || board.FiftyMoves >= 100) && board.Ply != 0)
            {
                return(0);
            }

            if (board.Ply > Variables.MAX_DEPTH - 1)
            {
                return(Evaluate.Position(board));
            }

            bool kingInCheck = Attack.IsSqAttacked(board.KingSq[board.Side], board.Side ^ 1, board);

            // If king is in check, search deeper to get out of check.
            if (kingInCheck)
            {
                depth++;
                // The two following lines are possibly ERROR.
                long timeInc = (info.StopTime - info.StartTime) * (1 / 2);
                info.StopTime += timeInc;
            }

            MoveList list = new MoveList();

            MoveGen.GenerateAllMoves(board, list, false);
            int oldAlpha = alpha;
            int score    = -infinite;
            int legal    = 0; // Will increment when we find a legal move.
            int bestMove = Variables.NO_MOVE;
            int PvMove   = PvTable.Probe(board);

            // Prioritize Principle Variation move if it's found.
            if (PvMove != Variables.NO_MOVE)
            {
                for (int i = 0; i < list.Count; ++i)
                {
                    var move = list.Moves[i].Move;
                    if (move == PvMove)
                    {
                        list.Moves[i].Score = 2000000;
                        break;
                    }
                }
            }

            for (int i = 0; i < list.Count; ++i)
            {
                PickNextMove(i, list);

                var move = list.Moves[i].Move;
                if (!MakeMove.Make_Move(board, move))
                {
                    continue;
                }

                legal++;
                score = -AlphaBeta(-beta, -alpha, depth - 1, ref info, true);
                MakeMove.TakeMove(board); // Take back the made move.

                if (info.Stopped)
                {
                    return(0); // Back up to the root if times up.
                }

                // We have a new alpha or beta cutoff.
                if (score > alpha)
                {
                    bool isCaptureMove = (move & MoveOperations.MoveFlagCapture) != 0;
                    // beta cutoff?
                    if (score >= beta)
                    {
                        if (legal == 1)
                        {
                            info.Fhf++; // We searched the best move first.
                        }

                        info.Fh++;

                        // If beta cutoff, but no capture move.
                        if (!isCaptureMove)
                        {
                            board.SearchKillers[1, board.Ply] = board.SearchKillers[0, board.Ply];
                            board.SearchKillers[0, board.Ply] = move;
                        }
                        return(beta);
                    }

                    // Alpha cutoff
                    alpha    = score;
                    bestMove = move;

                    if (!isCaptureMove)
                    {
                        int from = MoveOperations.FromSq(move);
                        int to   = MoveOperations.ToSq(move);
                        board.SearchHistory[board[from], to] += depth; // Prioritizes move near the root of the tree.
                    }
                }
            }

            // If we haven't had any legal moves.
            if (legal == 0)
            {
                // If in check with no legal moves checkmate.
                if (kingInCheck)
                {
                    return(-mate + board.Ply); // Return the amount of moves it takes to mate.
                    // Returning in this way, allows the method to "prefer" the fastest checkmate combination.
                }
                else
                {
                    return(0); // Stalemate.
                }
            }

            if (alpha != oldAlpha)
            {
                PvTable.StoreMove(board, bestMove);
            }

            return(alpha);
        }
コード例 #14
0
        protected override ActionContext DoAction(ActionContext context)
        {
            if (context.Game == null)
            {
                throw new InvalidOperationException("Action context missing required property (Game)");
            }
            if (context.Board == null)
            {
                throw new InvalidOperationException("Action context missing required property (Board)");
            }
            if (context.Origin == null)
            {
                throw new InvalidOperationException("Action context missing required property (Origin)");
            }
            GameActionData actionData = MakeActionData(context);



            Game        game        = context.Game;
            Board       board       = context.Board;
            Hex         origin      = (Hex)context.Origin;
            PlayerBoard playerBoard = PlayerBoard.Get(game, context.PlayerId);
            int         tileCode    = context.Board.Get(origin);

            tileCode = Tile.SetPieceType(tileCode, PieceType.SmallTree);
            TreeType treeType = playerBoard.TreeType;

            tileCode = Tile.SetTreeType(tileCode, treeType);
            playerBoard.Pieces(PieceType.SmallTree).DecreaseAvailable();
            PlayerBoard.Set(game, context.PlayerId, playerBoard);
            context.Board.Set(origin, tileCode);
            PlayerBoard.Set(game, context.PlayerId, playerBoard);

            board = BoardOperations.CastShadow(board, origin, game.SunPosition);

            game.AddGameAction(actionData);
            switch (game.Status)
            {
            case GameStatus.PlacingFirstTrees when game.CurrentTurn == game.TurnOrder.Length - 1:
                game.Status = GameStatus.PlacingSecondTrees;
                return(context);

            case GameStatus.PlacingFirstTrees:
                game.CurrentTurn++;
                return(context);

            case GameStatus.PlacingSecondTrees when game.CurrentTurn == 0:
                foreach (string id in game.TurnOrder)
                {
                    PlayerBoard pb = PlayerBoard.Get(game, id);
                    pb.Light = (BoardOperations.CountLight(context.Board, pb.TreeType));
                    game.SetPlayerBoard(id, pb);
                }
                game.Status = GameStatus.InProgress;
                return(context);

            case GameStatus.PlacingSecondTrees: game.CurrentTurn--;
                return(context);

            case GameStatus.Preparing: break;

            case GameStatus.InProgress: break;

            case GameStatus.Ended: break;

            default: throw new ArgumentOutOfRangeException();
            }

            context.Game  = game;
            context.Board = board;

            return(context);
        }
コード例 #15
0
ファイル: MakeMove.cs プロジェクト: Woldbye/LINKcs
        // Possibly not static
        // Returns true if legal move, or false otherwise
        /// <summary>
        /// Makes the input move on the board, if the move is legal.
        /// If illegal, nothing happens and the method returns false.
        /// </summary>
        /// <param name="board"> The board to make the move on </param>
        /// <param name="move"> The move to perform </param>
        public static bool Make_Move(Board.Board board, int move)
        {
            Debug.Assert(BoardOperations.CheckBoard(board), "The CheckBoard method returned false.");

            int from = MoveOperations.FromSq(move);
            int to   = MoveOperations.ToSq(move);
            int side = board.Side;

            Debug.Assert(Validators.SqOnBoard(from), String.Format("Invalid From Square {0}", Io.SqToString(from)));
            Debug.Assert(Validators.SqOnBoard(to), String.Format("Invalid To Square {0}", Io.SqToString(to)));
            Debug.Assert(Validators.SideValid(side), String.Format("Invalid Side with integer value {0}", side));
            Debug.Assert(Validators.PieceValid(board[from]), String.Format("Invalid From Square {0}", Io.SqToString(from)));

            board.History[board.HistoryPly].PosKey = board.PosKey;

            // Now we check for special moves.
            if ((move & MoveOperations.MoveFlagEnPas) != 0)
            {
                if (side == (int)Colour.WHITE)    // If EnPas move we need to kill the pawn
                {
                    ClearPiece(to - 10, board);
                }
                else     // Else black
                {
                    ClearPiece(to + 10, board);
                }
            }
            else if ((move & MoveOperations.MoveFlagCastle) != 0)
            {
                // If castle we need to move the rook.
                switch (to)
                {
                case (int)Square.C1:
                    MovePiece((int)Square.A1, (int)Square.D1, board); break;

                case (int)Square.C8:
                    MovePiece((int)Square.A8, (int)Square.D8, board); break;

                case (int)Square.G1:
                    MovePiece((int)Square.H1, (int)Square.F1, board); break;

                case (int)Square.G8:
                    MovePiece((int)Square.H8, (int)Square.F8, board); break;

                default:
                    throw new Exception(
                              "The move is a castling move, but the to square doesn't match any eligible moves");
                }
            }

            if (board.EnPas != (int)Square.NO_SQ)
            {
                MakeMove.HashEnPas(board);
            }

            MakeMove.HashCastle(board); // POSSIBLE ERROR, MAYBE IT SHOULD BE IN IF STATEMENT ABOVE.

            // Store information in history array.
            board.History[board.HistoryPly].Move       = move;
            board.History[board.HistoryPly].EnPas      = board.EnPas;
            board.History[board.HistoryPly].CastlePerm = board.CastlePerm;
            board.History[board.HistoryPly].FiftyMoves = board.FiftyMoves;

            // Adjust castle permissions if rook or king has moved.
            board.CastlePerm &= MakeMove.castlePerm[from];
            board.CastlePerm &= MakeMove.castlePerm[to];
            board.EnPas       = (int)Square.NO_SQ;

            HashCastle(board);

            int captured = MoveOperations.Captured(move);

            board.FiftyMoves++;

            // If there is a piece captured
            if (captured != (int)Piece.EMPTY)
            {
                // Test if the piece is valid.
                Debug.Assert(Validators.PieceValid(captured), String.Format("Invalid piece ID integer {0}", captured));

                ClearPiece(to, board);
                board.FiftyMoves = 0; // reset 50moves, cuz a piece has been captured.
            }

            board.HistoryPly++;
            board.Ply++;


            if (Data.IsPiecePawn(board[from]))
            {
                board.FiftyMoves = 0; // Reset 50moves, cuz a pawn has moved.
                if ((move & MoveOperations.MoveFlagPawnStart) != 0)
                {
                    if (side == (int)Colour.WHITE)
                    {
                        board.EnPas = from + 10;
                        Debug.Assert(Conversion.getRanksBrd(board.EnPas) == (int)Rank.RANK_3, String.Format("Invalid board state: the enPas square {0} is wrong", Io.SqToString(board.EnPas)));
                    }
                    else
                    {
                        board.EnPas = from - 10;
                        Debug.Assert(Conversion.getRanksBrd(board.EnPas) == (int)Rank.RANK_6, String.Format("Invalid board state: the enPas square {0} is wrong", Io.SqToString(board.EnPas)));
                    }

                    HashEnPas(board);
                }
            }

            MovePiece(from, to, board);

            int promotedPce = MoveOperations.Promoted(move);

            if (promotedPce != (int)Piece.EMPTY)    // If there is a promoted piece
            // A piece cannot be promoted to a pawn.
            {
                Debug.Assert(Validators.PieceValid(promotedPce) && !Data.IsPiecePawn(promotedPce), String.Format("Promoted piece {0} is invalid", (Piece)promotedPce));
                ClearPiece(to, board);
                AddPiece(to, board, promotedPce);
            }

            if (Data.IsPieceKing(board[to]))
            {
                // If piece is king set the KingSQ
                board.KingSq[side] = to;
            }

            // Exclusive or, changes the side from white to black or black to white.
            board.Side ^= 1;
            HashSide(board);

            Debug.Assert(BoardOperations.CheckBoard(board));
            // Make sure that the new king square isn't attacked.
            if (Attack.IsSqAttacked(board.KingSq[side], board.Side, board))
            {
                TakeMove(board);
                return(false);
            }

            return(true);
        }
コード例 #16
0
ファイル: MakeMove.cs プロジェクト: Woldbye/LINKcs
        public static void TakeMove(Board.Board board)
        {
            Debug.Assert(BoardOperations.CheckBoard(board));

            // Decrement the plys.
            board.HistoryPly--;
            board.Ply--;

            int move = board.History[board.HistoryPly].Move;
            int from = MoveOperations.FromSq(move);
            int to   = MoveOperations.ToSq(move);

            Debug.Assert(Validators.SqOnBoard(from), String.Format("Invalid From Square {0}", Io.SqToString(from)));
            Debug.Assert(Validators.SqOnBoard(to), String.Format("Invalid To Square {0}", Io.SqToString(to)));

            // If there is an EnPas square, hash it out.
            if (board.EnPas != (int)Square.NO_SQ)
            {
                HashEnPas(board);
            }

            HashCastle(board);

            // Reverse relevant board structures.
            board.CastlePerm = board.History[board.HistoryPly].CastlePerm;
            board.FiftyMoves = board.History[board.HistoryPly].FiftyMoves;
            board.EnPas      = board.History[board.HistoryPly].EnPas;

            // If the previous move have an EnPas square set, we need to hash it back in
            if (board.EnPas != (int)Square.NO_SQ)
            {
                HashEnPas(board);
            }
            // Hash the castling back incase it's changed.
            HashCastle(board);
            // Change the side to move back.
            board.Side ^= 1;
            HashSide(board);

            if ((move & MoveOperations.MoveFlagEnPas) != 0)
            {
                if (board.Side == (int)Colour.WHITE)    // If EnPas move we need to add the pawn
                {
                    AddPiece(to - 10, board, (int)Piece.bP);
                }
                else     // Else black
                {
                    AddPiece(to + 10, board, (int)Piece.wP);
                }
            }
            else if ((move & MoveOperations.MoveFlagCastle) != 0)
            {
                // If castle we need to move the rook.
                switch (to)
                {
                case (int)Square.C1:
                    MovePiece((int)Square.D1, (int)Square.A1, board); break;

                case (int)Square.C8:
                    MovePiece((int)Square.D8, (int)Square.A8, board); break;

                case (int)Square.G1:
                    MovePiece((int)Square.F1, (int)Square.H1, board); break;

                case (int)Square.G8:
                    MovePiece((int)Square.F8, (int)Square.H8, board); break;

                default:
                    throw new Exception(
                              "The move is a castling move, but the to square doesn't match any eligible moves");
                }
            }

            // Move the piece back to the original square.
            MovePiece(to, from, board);

            if (Data.IsPieceKing(board[from]))
            {
                board.KingSq[board.Side] = from;
            }

            int captured = MoveOperations.Captured(move);

            if (captured != (int)Piece.EMPTY)
            {
                Debug.Assert(Validators.PieceValid(captured), "Invalid piece captured");

                AddPiece(to, board, captured);
            }

            int promotedPce = MoveOperations.Promoted(move);

            if (promotedPce != (int)Piece.EMPTY)    // If there is a promoted piece
            // A piece cannot be promoted to a pawn.
            {
                Debug.Assert((Validators.PieceValid(promotedPce) || !Data.IsPiecePawn(promotedPce)), String.Format("Promoted piece {0} is invalid. PieceValid returned {1}, and IsPiecePawn returned {2}", (Piece)promotedPce, Validators.PieceValid(promotedPce), Data.IsPiecePawn(promotedPce)));
                ClearPiece(from, board);
                AddPiece(from, board, ((Data.PIECE_COLOURS[promotedPce] == Colour.WHITE) ? (int)Piece.wP : (int)Piece.bP));
            }

            Debug.Assert(BoardOperations.CheckBoard(board));
        }
コード例 #17
0
ファイル: Search.cs プロジェクト: Woldbye/LINKcs
        /// <summary>
        /// Search all capture positions, to help avoid the Horizon effect.
        /// </summary>
        private int Quiescence(int alpha, int beta, ref S_SearchInfo info)
        {
            Debug.Assert(BoardOperations.CheckBoard(board));

            if ((info.Nodes & 2047) == 0)
            {
                CheckUp(ref info);
            }

            info.Nodes++;

            // If position is a draw.
            if ((IsRepetition() || board.FiftyMoves >= 100) && board.Ply != 0)
            {
                return(0);
            }

            int score = Evaluate.Position(board); // Stand_pat.

            if (board.Ply > Variables.MAX_DEPTH - 1)
            {
                return(score);
            }

            if (score >= beta)
            {
                return(beta);
            }

            if (score > alpha)
            {
                alpha = score;
            }


            MoveList list = new MoveList();

            MoveGen.GenerateAllMoves(board, list, true); // Only capture moves

            int oldAlpha = alpha;

            score = -infinite;
            int legal    = 0; // Will increment when we find a legal move.
            int bestMove = Variables.NO_MOVE;
            int PvMove   = PvTable.Probe(board);

            for (int i = 0; i < list.Count; ++i)
            {
                PickNextMove(i, list);

                var move = list.Moves[i].Move;

                if (!MakeMove.Make_Move(board, move))
                {
                    continue;
                }

                legal++;
                score = -Quiescence(-beta, -alpha, ref info);
                MakeMove.TakeMove(board); // Take back the made move.

                if (info.Stopped)
                {
                    return(0);
                }

                // We have a new alpha or beta cutoff.
                if (score > alpha)
                {
                    bool isCaptureMove = (move & MoveOperations.MoveFlagCapture) != 0;
                    // beta cutoff?
                    if (score >= beta)
                    {
                        if (legal == 1)
                        {
                            info.Fhf++; // We searched the best move first.
                        }

                        info.Fh++;
                        return(beta);
                    }

                    // Alpha cutoff
                    alpha    = score;
                    bestMove = move;
                }
            }

            if (alpha != oldAlpha)
            {
                PvTable.StoreMove(board, bestMove);
            }

            return(alpha);
        }