Exemple #1
0
        public void GetMoves_WithMoveUnder_6candidates()
        {
            var field     = Field.Create(0, 0, 0, @"
.XX.......
XX........
");
            var generator = new MoveGenerator();
            var candiates = generator.GetMoves(field, Block.S).Select(m => new MoveInstruction(m.Path.Moves.ToArray())).ToList();

            var act = candiates.Select(c => c.ToString()).ToArray();
            var exp = new string[]
            {
                "drop",
                "down,left,drop",
                "down,right,drop",
                "down,right,right,drop",
                "down,right,right,right,drop",
                "down,right,right,right,right,drop",
            };

            foreach (var a in act)
            {
                Console.WriteLine(a);
            }

            CollectionAssert.AreEqual(exp, act);
        }
		public void GetMoves_WithMoveUnder_6candidates()
		{
			var field = Field.Create(0, 0, 0, @"
.XX.......
XX........
");
			var generator = new MoveGenerator();
			var candiates = generator.GetMoves(field, Block.S).Select(m=> new MoveInstruction(m.Path.Moves.ToArray())).ToList();

			var act = candiates.Select(c => c.ToString()).ToArray();
			var exp = new string[]
			{
				"drop",
				"down,left,drop",
				"down,right,drop",
				"down,right,right,drop",
				"down,right,right,right,drop",
				"down,right,right,right,right,drop",
			};

			foreach (var a in act)
			{
				Console.WriteLine(a);
			}

			CollectionAssert.AreEqual(exp, act);
		}
Exemple #3
0
        // Sets values for initial board position
        private void SetStartingBoardData()
        {
            Parent = null;



            WhiteEligibleSquares = ~WhitePieces;
            BlackEligibleSquares = ~BlackPieces;


            BlackMoves  = MoveGenerator.GetMoves(this);
            TurnIsWhite = true;
            WhiteMoves  = MoveGenerator.GetMoves(this);


            BlackAttacks = GetBlackAttacks();
            WhiteAttacks = GetWhiteAttacks();

            this.WhiteInCheck = IsWhiteInCheck();
            this.BlackInCheck = IsBlackInCheck();



            CanWhiteCastle = true;
            CanBlackCastle = true;
            WhiteInCheck   = false;
            BlackInCheck   = false;
            Number         = 1;
            Value          = 0;
        }
Exemple #4
0
        public int CountLegalMoves(Board board, int depth)
        {
            if (depth == 0)
            {
                return(1);
            }

            var count     = 0;
            var generator = new MoveGenerator(board);

            generator.Setup();
            foreach (var move in generator.GetMoves(false))
            {
                board.SubmitMove(move);
                count += CountLegalMoves(board, depth - 1);
                board.UndoMove();
            }

            if (board.states.Count == 1)
            {
                Debug.WriteLine($"depth: {board.states.Count}, count: {count}, after {board.states.Peek().lastMove.ToAlgebraicNotation()}");
            }

            return(count);
        }
Exemple #5
0
        public static void SetPosition(string[] line)
        {
            if (line[1] == "startpos")
            {
                board = new Board();
                ai    = new AI(board);
            }
            else
            {
                throw new Exception("UNSUPPORTED");
            }

            for (int i = 3; i < line.Length; i++)
            {
                var  moveAlg = line[i];
                Move theMove = null;
                var  gen     = new MoveGenerator(board);
                gen.Setup();
                foreach (var move in gen.GetMoves(false))
                {
                    if (move.ToAlgebraicNotation().Equals(moveAlg))
                    {
                        theMove = move;
                        break;
                    }
                }
                if (theMove == null)
                {
                    Console.WriteLine("Move " + moveAlg + " was not found");
                }
                board.SubmitMove(theMove);
            }
        }
Exemple #6
0
        public void Ensure_king_can_just_step_away_from_check()
        {
            var target = new MoveGenerator(GameState.FromForsythEdwardsNotation("1K5r/8/1k6/8/8/8/8/8 w - -"));

            var moves = target.GetMoves();

            Assert.IsFalse(moves.Contains(new Move(Cell.b8, Cell.a8)));
        }
Exemple #7
0
        // Update Methods



        // Changes all board data to coorespond to the state after white moves
        private void InitializeWhitesChildBoard(Board Parent, Tuple <ulong, ulong> Move)
        {
            this.Parent = Parent;

            this.Move = Move;



            this.WhiteKing    = (Parent.WhiteKing & Move.Item1) > 0 ? Parent.WhiteKing ^ Move.Item1 | Move.Item2 : Parent.WhiteKing;
            this.WhiteQueen   = (Parent.WhiteQueen & Move.Item1) > 0 ? Parent.WhiteQueen ^ Move.Item1 | Move.Item2 : Parent.WhiteQueen;
            this.WhiteRooks   = (Parent.WhiteRooks & Move.Item1) > 0 ? Parent.WhiteRooks ^ Move.Item1 | Move.Item2 : Parent.WhiteRooks;
            this.WhiteBishops = (Parent.WhiteBishops & Move.Item1) > 0 ? Parent.WhiteBishops ^ Move.Item1 | Move.Item2 : Parent.WhiteBishops;
            this.WhiteKnights = (Parent.WhiteKnights & Move.Item1) > 0 ? Parent.WhiteKnights ^ Move.Item1 | Move.Item2 : Parent.WhiteKnights;
            this.WhitePawns   = (Parent.WhitePawns & Move.Item1) > 0 ? Parent.WhitePawns ^ Move.Item1 | Move.Item2 : Parent.WhitePawns;
            this.WhitePieces |= this.WhiteKing;
            this.WhitePieces |= this.WhiteQueen;
            this.WhitePieces |= this.WhiteRooks;
            this.WhitePieces |= this.WhiteBishops;
            this.WhitePieces |= this.WhiteKnights;
            this.WhitePieces |= this.WhitePawns;


            this.BlackKing    = (Parent.BlackKing & Move.Item2) > 0 ? Parent.BlackKing ^ Move.Item2: Parent.BlackKing;
            this.BlackQueen   = (Parent.BlackQueen & Move.Item2) > 0 ? Parent.BlackQueen ^ Move.Item2 : Parent.BlackQueen;
            this.BlackRooks   = (Parent.BlackRooks & Move.Item2) > 0 ? Parent.BlackRooks ^ Move.Item2 : Parent.BlackRooks;
            this.BlackBishops = (Parent.BlackBishops & Move.Item2) > 0 ? Parent.BlackBishops ^ Move.Item2 : Parent.BlackBishops;
            this.BlackKnights = (Parent.BlackKnights & Move.Item2) > 0 ? Parent.BlackKnights ^ Move.Item2 : Parent.BlackKnights;
            this.BlackPawns   = (Parent.BlackPawns & Move.Item2) > 0 ? Parent.BlackPawns ^ Move.Item2 : Parent.BlackPawns;
            this.BlackPieces |= this.BlackKing;
            this.BlackPieces |= this.BlackQueen;
            this.BlackPieces |= this.BlackRooks;
            this.BlackPieces |= this.BlackBishops;
            this.BlackPieces |= this.BlackKnights;
            this.BlackPieces |= this.BlackPawns;

            WhiteEligibleSquares = ~WhitePieces;
            BlackEligibleSquares = ~BlackPieces;


            WhiteMoves       = MoveGenerator.GetMoves(this);
            this.TurnIsWhite = false;
            BlackMoves       = MoveGenerator.GetMoves(this);

            this.BlackAttacks = GetBlackAttacks();
            this.WhiteAttacks = GetWhiteAttacks();

            this.WhiteInCheck = IsWhiteInCheck();
            this.BlackInCheck = IsBlackInCheck();


            this.CanWhiteCastle = true;
            this.CanBlackCastle = true;

            this.Value = this.CalcValue();
        }
Exemple #8
0
    public void ZoomToPiece(bool suppress = false)
    {
        StartCoroutine(game.CenterCameraOnPiece(this));

        if (!suppress)
        {
            List <Move> moveTargets = MoveGenerator.GetMoves(game.gameBoard, this);

            StartCoroutine(game.HighlightMoves(moveTargets, 1f));
        }
    }
        public void GetMovesCornerCase()
        {
            var board     = new SquareBoard(4);
            var generator = new MoveGenerator(board);

            const int repeat = 1000;

            for (int i = 0; i < repeat; ++i)
            {
                var moves = generator.GetMoves();
                Assert.IsTrue(moves.Length == 2);
            }
        }
Exemple #10
0
        private static void AssertGetMoves(string[] exp, Block block)
        {
            var generator = new MoveGenerator();
            var moves     = generator.GetMoves(TestData.Small, block).Select(candidate => candidate.Path.ToString()).ToArray();

            foreach (var move in moves)
            {
                Console.WriteLine('"' + move + '"' + ',');
            }

            Assert.AreEqual(block.ChildCount, moves.Length, "GetMoves for {0} has the wrong number of answers.", block.Name);
            CollectionAssert.AreEqual(exp, moves);
        }
Exemple #11
0
        public Move WaitMove(Position position, Score score)
        {
            PrintPosition(position, score);
            StringBuilder candidates = new StringBuilder("合法手: ");
            Stopwatch     sw         = new Stopwatch();

            sw.Start();
            foreach (var move in MoveGenerator.GetMoves(position))
            {
                candidates.AppendFormat("{0}{1}{2} ", move.DstIndex, move.PieceType.ToPieceName(), move.Promote ? "成" : "");
            }
            sw.Stop();
            Console.WriteLine(candidates);
            Console.WriteLine(String.Format("Time to get legal moves: {0}", sw.Elapsed));

            return(position.Turn == Color.Black ? black.WaitMove(position) : white.WaitMove(position));
        }
Exemple #12
0
        public static int CountMoves(Board board, MoveGenerator generator, uint us, int depth)
        {
            if (depth == 0)
            {
                return(1);
            }

            var count = 0;
            var them  = Piece.OtherColor(us);

            generator.Setup();
            foreach (var move in generator.GetMoves(false))
            {
                board.SubmitMove(move);
                count += CountMoves(board, generator, them, depth - 1);
                board.UndoMove();
            }

            return(count);
        }
Exemple #13
0
        private static void AssertGetFields(string[] exp, Block block)
        {
            var generator       = new MoveGenerator();
            var candidateFields = generator.GetMoves(TestData.Small, block).Select(candidate => candidate.Field.ToString()).ToArray();
            var fields          = generator.GetFields(TestData.Small, block).Select(field => field.ToString()).ToArray();

            foreach (var field in candidateFields)
            {
                Console.WriteLine('"' + field + '"' + ',');
            }

            foreach (var field in candidateFields)
            {
                Console.WriteLine(field.Replace("|", Environment.NewLine));
                Console.WriteLine();
            }
            Assert.AreEqual(block.ChildCount, candidateFields.Length, "GetMoves for {0} has the wrong number of answers.", block.Name);
            CollectionAssert.AreEqual(exp, candidateFields, "Moves");
            CollectionAssert.AreEqual(exp, fields, "Fields");
        }
		public void GetMoves_AlmostFilledField_21candidates()
		{
			var field = Field.Create(0, 0, 0, @"
..........
..........
XXXX.XX...
.XXXXXXXXX
XXXX..XX.X
XXX.XXXXXX
XXX.XXXXXX
XXX.XXXXXX
XXX.XXXXXX
XXX.XXXXXX
XXX.XXXXXX
XXX.XXXXXX
XXXXX.XXXX
.XXXX.XXXX");
			var generator = new MoveGenerator();
			var candiates = generator.GetMoves(field, Block.J).ToList();

			Assert.AreEqual(8 + 8 + 3 + 2, candiates.Count);
		}
		public void GetMoves_()
		{
			var field = Field.Create(0, 0, 0, @"
.......XXX
.........X
.........X
X........X
XX.......X
XX.......X
XX......XX
XXX.....XX
XXXXXX..XX
XXXXXX.XXX
XXXXXX.XXX
XXX.XX.XXX
XXXXXX.XXX
XXXXXX.XXX
X.XXXXXXXX
XXXXXX.XXX");
			var generator = new MoveGenerator();
			var candiates = generator.GetMoves(field, Block.I).ToList();
		}
Exemple #16
0
    public Move GetRandomMove(GameBoardState gameBoard, Player player)
    {
        PieceState  piece;
        List <Move> moves = new List <Move>();

        int i = 0;

        do
        {
            piece = gameBoard.AlivePieces[sysRandom.Next(0, gameBoard.AlivePieces.Count)];

            moves = MoveGenerator.GetMoves(gameBoard, piece);
            i++;
        }while ((piece.player != player || moves.Count == 0) && i < 10000 && gameBoard.AlivePieces.Count > 0);

        if (i == 10000)
        {
            throw new System.Exception("no move found " + i + " " + gameBoard.AlivePieces.Count);
        }

        return(moves[sysRandom.Next(0, moves.Count)]);
    }
Exemple #17
0
        public void GetMoves_AlmostFilledField_21candidates()
        {
            var field     = Field.Create(0, 0, 0, @"
..........
..........
XXXX.XX...
.XXXXXXXXX
XXXX..XX.X
XXX.XXXXXX
XXX.XXXXXX
XXX.XXXXXX
XXX.XXXXXX
XXX.XXXXXX
XXX.XXXXXX
XXX.XXXXXX
XXXXX.XXXX
.XXXX.XXXX");
            var generator = new MoveGenerator();
            var candiates = generator.GetMoves(field, Block.J).ToList();

            Assert.AreEqual(8 + 8 + 3 + 2, candiates.Count);
        }
Exemple #18
0
        public void GetMoves_()
        {
            var field     = Field.Create(0, 0, 0, @"
.......XXX
.........X
.........X
X........X
XX.......X
XX.......X
XX......XX
XXX.....XX
XXXXXX..XX
XXXXXX.XXX
XXXXXX.XXX
XXX.XX.XXX
XXXXXX.XXX
XXXXXX.XXX
X.XXXXXXXX
XXXXXX.XXX");
            var generator = new MoveGenerator();
            var candiates = generator.GetMoves(field, Block.I).ToList();
        }
Exemple #19
0
    public void SquareClickEvent(int level, int row, int col)
    {
        if (game.currentPlayer.playerType == Player.PlayerType.Human)
        {
            ISpaceState s     = game.gameBoard.GetSpace(level, row, col);
            bool        moved = false;
            if (moveTargets != null)
            {
                foreach (Move m in moveTargets)
                {
                    if (m.space == s)
                    {
                        game.currentPlayer.selectedMove = m;
                        game.currentPlayer.playerState  = Player.PlayerState.Moving;

                        moved = true;

                        break;
                    }
                }
                moveTargets = null;
            }

            ResetButtonHighlights();

            if (s.IsOccupied() && !moved && s.Occupier().GetPlayer() == game.currentPlayer.playerNumber)
            {
                game.gameBoard.GetPiece(s.Occupier()).ZoomToPiece();

                moveTargets = MoveGenerator.GetMoves(game.gameBoard, s.Occupier());
                foreach (Move m in moveTargets)
                {
                    squareLookup[m.space.GetLevel()][m.space.GetRow()][m.space.GetCol()].color = Color.cyan;
                }
            }
        }
    }
Exemple #20
0
    /// <summary>
    /// select a random piece until a legal list of moves is found. select a random move from the list.
    /// </summary>
    public Move GetRandomMove(Player player)
    {
        Piece       piece;
        List <Move> moves = new List <Move>();

        int i = 0;

        do
        {
            piece = gameBoard.AlivePieces[sysRandom.Next(0, gameBoard.AlivePieces.Count)];

            moves = MoveGenerator.GetMoves(gameBoard, piece);
            i++;
        }while ((piece.player != player || moves.Count == 0) && i < 10000 && gameBoard.AlivePieces.Count > 0);

        if (i == 10000)
        {
            throw new System.Exception("no move found " + i + " " + gameBoard.AlivePieces.Count);
        }

        piece.space.AnimateShell(MoveTime, Color.red);
        StartCoroutine(HighlightMoves(moves));
        return(moves[sysRandom.Next(0, moves.Count)]);
    }
		private static void AssertGetMoves(string[] exp, Block block)
		{
			var generator = new MoveGenerator();
			var moves = generator.GetMoves(TestData.Small, block).Select(candidate => candidate.Path.ToString()).ToArray();

			foreach (var move in moves)
			{
				Console.WriteLine('"' + move + '"' + ',');
			}

			Assert.AreEqual(block.ChildCount, moves.Length, "GetMoves for {0} has the wrong number of answers.", block.Name);
			CollectionAssert.AreEqual(exp, moves);
		}
Exemple #22
0
    /// Returns a list of moves given a pgn string.
    /// Note that Board should be set to whatever starting position of pgn is.
    public static List <ushort> MovesFromPGN(string pgn)
    {
        List <string> moveStrings = MoveStringsFromPGN(pgn);
        List <ushort> allMoves    = new List <ushort> ();

        MoveGenerator moveGen = new MoveGenerator();

        for (int i = 0; i < moveStrings.Count; i++)
        {
            string moveString = moveStrings[i];

            moveString = moveString.Replace("+", "");            // remove check symbol
            moveString = moveString.Replace("#", "");            // remove mate symbol
            moveString = moveString.Replace("x", "");            // remove capture symbol
            string moveStringLower = moveStrings[i].ToLower();

            ushort[] movesInPosition = moveGen.GetMoves(false, false).moves;
            ushort   move            = 0;
            for (int j = 0; j < movesInPosition.Length; j++)
            {
                move = movesInPosition[j];
                int moveFromIndex = move & 127;
                int moveToIndex   = (move >> 7) & 127;
                int movePieceType = Board.boardArray[moveFromIndex] & ~1;
                int colourCode    = Board.boardArray[moveFromIndex] & 1;


                if (moveStringLower == "oo")                   // castle kingside
                {
                    if (movePieceType == Board.kingCode && moveToIndex - moveFromIndex == 2)
                    {
                        break;
                    }
                }
                else if (moveStringLower == "ooo")                   // castle queenside
                {
                    if (movePieceType == Board.kingCode && moveToIndex - moveFromIndex == -2)
                    {
                        break;
                    }
                }
                else if (Definitions.fileNames.Contains(moveString[0] + ""))                   // pawn move if starts with any file indicator (e.g. 'e'4. Note that uppercase B is used for bishops)
                {
                    if (movePieceType != Board.pawnCode)
                    {
                        continue;
                    }
                    if (Definitions.FileNumberFromAlgebraicName(moveStringLower[0]) == Board.FileFrom128(moveFromIndex)) // correct starting file
                    {
                        if (moveString.Contains("="))                                                                    // is promotion
                        {
                            char promotionChar = moveStringLower[moveStringLower.Length - 1];

                            int promotionPieceIndex = move >> 14 & 3;
                            int promotionPieceCode  = Board.pieceCodeArray [promotionPieceIndex];

                            if ((promotionPieceCode == Board.queenCode && promotionChar != 'q') || (promotionPieceCode == Board.rookCode && promotionChar != 'r') ||
                                (promotionPieceCode == Board.bishopCode && promotionChar != 'b') || (promotionPieceCode == Board.knightCode && promotionChar != 'n'))
                            {
                                continue;                                 // skip this move, incorrect promotion type
                            }
                            break;
                        }
                        else
                        {
                            char targetFile = moveString[moveString.Length - 2];
                            char targetRank = moveString[moveString.Length - 1];

                            if (Definitions.FileNumberFromAlgebraicName(targetFile) == Board.FileFrom128(moveToIndex))                               // correct ending file
                            {
                                if (Definitions.RankNumberFromAlgebraicName(targetRank) == Board.RankFrom128(moveToIndex))                           // correct ending rank
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
                else                   // regular piece move

                {
                    char movePieceChar = moveString[0];
                    if (!(movePieceType == Board.queenCode && movePieceChar == 'Q') && !(movePieceType == Board.rookCode && movePieceChar == 'R') &&
                        !(movePieceType == Board.bishopCode && movePieceChar == 'B') && !(movePieceType == Board.knightCode && movePieceChar == 'N') && !(movePieceType == Board.kingCode && movePieceChar == 'K'))
                    {
                        continue;                         // skip this move, incorrect move piece type
                    }

                    char targetFile = moveString[moveString.Length - 2];
                    char targetRank = moveString[moveString.Length - 1];
                    if (Definitions.FileNumberFromAlgebraicName(targetFile) == Board.FileFrom128(moveToIndex))     // correct ending file
                    {
                        if (Definitions.RankNumberFromAlgebraicName(targetRank) == Board.RankFrom128(moveToIndex)) // correct ending rank
                        {
                            if (moveString.Length == 4)                                                            // addition char present for disambiguation (e.g. Nbd7 or R7e2)
                            {
                                char disambiguationChar = moveString[1];

                                if (Definitions.fileNames.Contains(disambiguationChar + ""))                                             // is file disambiguation
                                {
                                    if (Definitions.FileNumberFromAlgebraicName(disambiguationChar) != Board.FileFrom128(moveFromIndex)) // incorrect starting file
                                    {
                                        continue;
                                    }
                                }
                                else                                                                                                     // is rank disambiguation
                                {
                                    if (Definitions.RankNumberFromAlgebraicName(disambiguationChar) != Board.RankFrom128(moveFromIndex)) // incorrect starting rank
                                    {
                                        continue;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            }
            if (move == 0)               // move is illegal; discard and return moves up to this point
            {
                UnityEngine.Debug.Log(moveString);
                break;
            }
            else
            {
                allMoves.Add(move);
            }
            Board.MakeMove(move);
        }
        for (int i = allMoves.Count - 1; i >= 0; i--)
        {
            Board.UnmakeMove(allMoves[i]);
        }

        return(allMoves);
    }
Exemple #23
0
    public static int Evaluate()
    {
        Timer.Start("Eval");
        int materialEval    = 0;
        int mobilityEval    = 0;
        int developmentEval = 0;
        int kingSafetyEval  = 0;

        // piece index vars (assigned when found to be used in later calculations)
        int        whiteKingSquareIndex = -1;
        int        blackKingSquareIndex = -1;
        List <int> whiteQueenIndices    = new List <int> (2);
        List <int> whiteRookIndices     = new List <int> (2);
        List <int> whiteKnightIndices   = new List <int> (2);
        List <int> whiteBishopIndices   = new List <int> (2);
        List <int> whitePawnIndices     = new List <int> (8);

        List <int> blackQueenIndices  = new List <int> (2);
        List <int> blackRookIndices   = new List <int> (2);
        List <int> blackKnightIndices = new List <int> (2);
        List <int> blackBishopIndices = new List <int> (2);
        List <int> blackPawnIndices   = new List <int> (8);


        for (int squareIndex = 0; squareIndex <= 127; squareIndex++)
        {
            if ((squareIndex & 8) != 0)               // don't look at indices which are not on the real board
            {
                continue;
            }

            if (Board.boardArray[squareIndex] != 0)
            {
                int pieceCode = Board.boardArray[squareIndex];
                if (pieceCode == Board.kingCode + 1)                   // found white king
                {
                    whiteKingSquareIndex = squareIndex;
                }
                else if (pieceCode == Board.kingCode)                   // found black king
                {
                    blackKingSquareIndex = squareIndex;
                }
                else                                        // non-king pieces
                {
                    materialEval += pieceValues[pieceCode]; // count material (excluding kings)

                    switch (pieceCode)
                    {
                    case Board.queenCode + 1:
                        whiteQueenIndices.Add(squareIndex);
                        break;

                    case Board.rookCode + 1:
                        whiteRookIndices.Add(squareIndex);
                        break;

                    case Board.knightCode + 1:
                        whiteKnightIndices.Add(squareIndex);
                        break;

                    case Board.bishopCode + 1:
                        whiteBishopIndices.Add(squareIndex);
                        break;

                    case Board.pawnCode + 1:
                        whitePawnIndices.Add(squareIndex);
                        break;

                    case Board.queenCode:
                        blackQueenIndices.Add(squareIndex);
                        break;

                    case Board.rookCode:
                        blackRookIndices.Add(squareIndex);
                        break;

                    case Board.knightCode:
                        blackKnightIndices.Add(squareIndex);
                        break;

                    case Board.bishopCode:
                        blackBishopIndices.Add(squareIndex);
                        break;

                    case Board.pawnCode:
                        blackPawnIndices.Add(squareIndex);
                        break;
                    }
                }
            }
        }

        if (whiteKingSquareIndex == -1)           // return best score for black if white's king has been captured (this may sometimes be allowed during alphabeta search for faster move generation)
        //return int.MinValue;
        {
        }


        // piece mobility
        moveGenerator.SetMoveColour(1);
        mobilityEval += moveGenerator.GetMoves(false, true, false).Count;         // white piece mobility
        mobilityEval += moveGenerator.GetMoves(true, true, false).Count;          // white piece attacking black
        moveGenerator.SetMoveColour(0);
        mobilityEval -= moveGenerator.GetMoves(false, true, false).Count;         // black piece mobility
        mobilityEval -= moveGenerator.GetMoves(true, true, false).Count;          // black piece attacking white

        // piece development white
        for (int i = 0; i < whiteKnightIndices.Count; i++)
        {
            if (Board.RankFrom128(whiteKnightIndices[i]) == 1)               // penalize knight remaining on first rank
            {
                developmentEval -= 50;
            }
            else if (Board.RankFrom128(whiteKnightIndices[i]) == 2)               // penalize knight remaining on second rank
            {
                developmentEval -= 10;
            }
            if (Board.FileFrom128(whiteKnightIndices[i]) == 1)               // knights on the rim are dim
            {
                developmentEval -= 5;
            }
            else if (Board.FileFrom128(whiteKnightIndices[i]) == 8)               // knights on the rim are dim
            {
                developmentEval -= 5;
            }
        }

        for (int i = 0; i < whiteBishopIndices.Count; i++)
        {
            if (Board.RankFrom128(whiteBishopIndices[i]) == 1)               // penalize bishop remaining on first rank
            {
                developmentEval -= 50;
            }
        }

        // piece development black
        for (int i = 0; i < blackKnightIndices.Count; i++)
        {
            if (Board.RankFrom128(blackKnightIndices[i]) == 8)               // penalize knight remaining on eighth rank
            {
                developmentEval += 50;
            }
            else if (Board.RankFrom128(blackKnightIndices[i]) == 7)               // penalize knight remaining on seventh rank
            {
                developmentEval += 10;
            }
            if (Board.FileFrom128(blackKnightIndices[i]) == 1)               // knights on the rim are dim
            {
                developmentEval += 5;
            }
            else if (Board.FileFrom128(blackKnightIndices[i]) == 8)               // knights on the rim are dim
            {
                developmentEval += 5;
            }
        }

        for (int i = 0; i < blackBishopIndices.Count; i++)
        {
            if (Board.RankFrom128(blackBishopIndices[i]) == 8)               // penalize bishop remaining on eighth rank
            {
                developmentEval += 50;
            }
        }

        // king safety white
        if (Board.WhiteHasCastlingRights())
        {
            kingSafetyEval += 10;             // not safe, but at least retaining ability to castle
        }
        else
        {
            if (whiteKingSquareIndex == 6 || whiteKingSquareIndex == 7)               // generally safe kingside squares for king (g1,h1)
            {
                kingSafetyEval += 50;
                for (int i = 0; i < whiteRookIndices.Count; i++)
                {
                    if (Board.FileFrom128(whiteRookIndices[i]) > 6)
                    {
                        kingSafetyEval -= 55;                         // penalize non-castling king manoeuvres where rook is boxed in by king
                    }
                }
            }
            else if (whiteKingSquareIndex == 2 || whiteKingSquareIndex == 1 || whiteKingSquareIndex == 0)               // generally safe queenside squares for king (a1,b1,c1)
            {
                kingSafetyEval += 50;
                for (int i = 0; i < whiteRookIndices.Count; i++)
                {
                    if (Board.FileFrom128(whiteRookIndices[i]) < 3)
                    {
                        kingSafetyEval -= 55;                         // penalize non-castling king manoeuvres where rook is boxed in by king
                    }
                }
            }
        }
        // king safety black
        if (Board.BlackHasCastlingRights())
        {
            kingSafetyEval -= 10;             // not safe, but at least retaining ability to castle
        }
        else
        {
            if (blackKingSquareIndex == 118 || blackKingSquareIndex == 119)               // generally safe kingside squares for king (g8,h8)
            {
                kingSafetyEval -= 50;
                for (int i = 0; i < blackRookIndices.Count; i++)
                {
                    if (Board.FileFrom128(blackRookIndices[i]) > 6)
                    {
                        kingSafetyEval += 55;                         // penalize non-castling king manoeuvres where rook is boxed in by king
                    }
                }
            }
            else if (blackKingSquareIndex == 114 || blackKingSquareIndex == 113 || blackKingSquareIndex == 112)               // generally safe queenside squares for king (a8,b8,c8)
            {
                kingSafetyEval -= 50;
                for (int i = 0; i < blackRookIndices.Count; i++)
                {
                    if (Board.FileFrom128(blackRookIndices[i]) < 3)
                    {
                        kingSafetyEval += 55;                         // penalize non-castling king manoeuvres where rook is boxed in by king
                    }
                }
            }
        }

        int openingMaterialCount = 16 * pawnValue + 4 * (rookValue + knightValue + bishopValue) + 2 * queenValue;
        int endgameMaterialCount = 2 * (rookValue + knightValue);

        //float gameStage =

        int finalEval = materialEval * 1000 + mobilityEval + kingSafetyEval + developmentEval;

        Timer.Stop("Eval");
        return(finalEval);
    }
Exemple #24
0
    /// <summary>
    /// Recursive alpha beta pruning minimax search strategy.
    /// </summary>
    /// <param name="gbs">The Game Board State.</param>
    /// <param name="searchLevels">The number of levels to search (depth)</param>
    /// <param name="currentPlayer">The current player's turn.</param>
    /// <param name="BestMove">The best move found during the search</param>
    /// <param name="alpha">Starting alpha value.</param>
    /// <param name="beta">Starting beta value.</param>
    /// <returns></returns>
    public static AIMinMaxResult AIMinMaxSearch(this IGameBoardState gbs, int searchLevels, Player.PlayerNumber currentPlayer, bool QuiescenceSearch = false, double alpha = -1.0, double beta = 1.0)
    {
        Move BestMove = null;

        double checkWinner = gbs.CheckWinner();

        //cutoff for search (recursive base cases)
        if (checkWinner == -1.0)
        {
            return(new AIMinMaxResult(BestMove, -1.0, 1));
        }

        if (checkWinner == 1.0)
        {
            return(new AIMinMaxResult(BestMove, 1.0, 1));
        }

        if (searchLevels == 0)
        {
            return(new AIMinMaxResult(BestMove, gbs.CalculateUtility(), 1));
        }

        AIMinMaxResult result         = null;
        long           statesSearched = 0;
        //iterate by looking at all possible moves for each piece
        List <IPieceState> pieces = gbs.GetAlivePieces().Where(s => s.GetPlayer() == currentPlayer).Select(s => s).ToList();

        foreach (IPieceState piece in pieces.Shuffle())
        {
            List <Move> moves;
            if (QuiescenceSearch)
            {
                moves = MoveGenerator.GetCaptureMoves(gbs, piece);
            }
            else
            {
                moves = MoveGenerator.GetMoves(gbs, piece);
            }

            MovesSearched += moves.Count;

            //perform each move on a cloned board and search clone recursively, swapping players each turn
            foreach (Move move in moves.Shuffle())
            {
                IGameBoardState clone = gbs.Clone();
                clone.Move(move.piece, move.space);

                if (currentPlayer == Player.PlayerNumber.Player1)
                {
                    result          = clone.AIMinMaxSearch(searchLevels - 1, Player.PlayerNumber.Player2, true, alpha, beta);
                    statesSearched += result.TotalStatesSearched;
                    if (statesSearched > StatesSearched)
                    {
                        StatesSearched = statesSearched;
                    }
                    if (result.AlphaBeta > alpha)
                    {
                        alpha    = result.AlphaBeta;
                        BestMove = move;
                    }

                    //beta cut off
                    if (beta <= alpha)
                    {
                        break;
                    }
                }
                else /* (currentPlayer == Player.PlayerNumber.Player2) */
                {
                    result          = clone.AIMinMaxSearch(searchLevels - 1, Player.PlayerNumber.Player1, true, alpha, beta);
                    statesSearched += result.TotalStatesSearched;
                    if (statesSearched > StatesSearched)
                    {
                        StatesSearched = statesSearched;
                    }
                    if (result.AlphaBeta < beta)
                    {
                        beta     = result.AlphaBeta;
                        BestMove = move;
                    }

                    //alpha cut off
                    if (beta <= alpha)
                    {
                        break;
                    }
                }

                if (jobStatus == AIMinMaxJobStatus.StopRequested && LevelsSearched > 0)
                {
                    searchLevels = 1;
                }
            }

            if (jobStatus == AIMinMaxJobStatus.StopRequested && LevelsSearched > 0)
            {
                searchLevels = 1;
            }
        }

        //no moves found, treat as a base case
        if (BestMove == null)
        {
            return(new AIMinMaxResult(BestMove, gbs.CalculateUtility(), 1));
        }

        //Create a result and return it
        return(new AIMinMaxResult(BestMove, result.AlphaBeta, statesSearched));
    }
Exemple #25
0
    public static string NotationFromMove(ushort move)
    {
        Board.UnmakeMove(move);          // unmake move on board

        MoveGenerator moveGen             = new MoveGenerator();
        int           moveFromIndex       = move & 127;
        int           moveToIndex         = (move >> 7) & 127;
        int           promotionPieceIndex = (move >> 14) & 3; // 0 = queen, 1 = rook, 2 = knight, 3 = bishop
        int           colourToMove        = Board.boardColourArray[moveFromIndex];

        int movePieceCode     = Board.boardArray [moveFromIndex]; // get move piece code
        int movePieceType     = movePieceCode & ~1;               // get move piece type code (no colour info)
        int capturedPieceCode = Board.boardArray [moveToIndex];   // get capture piece code

        int promotionPieceType = Board.pieceCodeArray [promotionPieceIndex];

        if (movePieceType == Board.kingCode)
        {
            if (moveToIndex - moveFromIndex == 2)
            {
                Board.MakeMove(move);                  // remake move
                return("O-O");
            }
            else if (moveToIndex - moveFromIndex == -2)
            {
                Board.MakeMove(move);                  // remake move
                return("O-O-O");
            }
        }

        string moveNotation = GetSymbolFromPieceType(movePieceType);

        // check if any ambiguity exists in notation (e.g if e2 can be reached via Nfe2 and Nbe2)
        if (movePieceType != Board.pawnCode && movePieceType != Board.kingCode)
        {
            Heap allMoves = moveGen.GetMoves(false, false);

            for (int i = 0; i < allMoves.Count; i++)
            {
                int alternateMoveFromIndex = allMoves.moves[i] & 127;
                int alternateMoveToIndex   = (allMoves.moves[i] >> 7) & 127;
                int alternateMovePieceCode = Board.boardArray [alternateMoveFromIndex];

                if (alternateMoveFromIndex != moveFromIndex && alternateMoveToIndex == moveToIndex) // if moving to same square from different square
                {
                    if (alternateMovePieceCode == movePieceCode)                                    // same piece type
                    {
                        int fromFileIndex          = Board.FileFrom128(moveFromIndex) - 1;
                        int alternateFromFileIndex = Board.FileFrom128(alternateMoveFromIndex) - 1;
                        int fromRankIndex          = Board.RankFrom128(moveFromIndex) - 1;
                        int alternateFromRankIndex = Board.RankFrom128(alternateMoveFromIndex) - 1;

                        if (fromFileIndex != alternateFromFileIndex)                           // pieces on different files, thus ambiguity can be resolved by specifying file
                        {
                            moveNotation += Definitions.fileNames[fromFileIndex];
                            break;                             // ambiguity resolved
                        }
                        else if (fromRankIndex != alternateFromRankIndex)
                        {
                            moveNotation += Definitions.rankNames[fromRankIndex];
                            break;                             // ambiguity resolved
                        }
                    }
                }
            }
        }

        if (capturedPieceCode != 0)           // add 'x' to indicate capture
        {
            if (movePieceType == Board.pawnCode)
            {
                moveNotation += Definitions.fileNames[Board.FileFrom128(moveFromIndex) - 1];
            }
            moveNotation += "x";
        }
        else             // check if capturing ep
        {
            if (movePieceType == Board.pawnCode)
            {
                if (System.Math.Abs(moveToIndex - moveFromIndex) != 16 && System.Math.Abs(moveToIndex - moveFromIndex) != 32)
                {
                    moveNotation += Definitions.fileNames[Board.FileFrom128(moveFromIndex) - 1] + "x";
                }
            }
        }

        moveNotation += Definitions.fileNames [Board.FileFrom128(moveToIndex) - 1];
        moveNotation += Definitions.rankNames [Board.RankFrom128(moveToIndex) - 1];

        // add = piece type if promotion
        if (movePieceType == Board.pawnCode)
        {
            if (moveToIndex >= 112 || moveToIndex <= 7)               // pawn has reached first/eighth rank
            {
                moveNotation += "=" + GetSymbolFromPieceType(promotionPieceType);
            }
        }

        // add check/mate symbol if applicable
        Board.MakeMove(move);          // remake move
        if (moveGen.PositionIsMate())
        {
            moveNotation += "#";
        }
        else if (moveGen.PositionIsCheck())
        {
            moveNotation += "+";
        }
        return(moveNotation);
    }
Exemple #26
0
    int AlphaBetaSearch(int plyRemaining, int alpha, int beta, bool isWhite)
    {
        Heap moveHeap = moveGenerator.GetMoves(false, false);
        int  count    = moveHeap.Count;

        if (moveHeap.Count == 0)
        {
            return(((isWhite)?-1:1) * (10000000 + plyRemaining));          // if no moves available, side has been checkmated. Return best score for opponent. Checkmating sooner (higher depth) is rewarded.
        }


        if (plyRemaining == 0)
        {
            nodesSearched++;
            return(Evaluate());
            //QuiescenceSearch(int.MinValue,int.MaxValue,!isWhite,true);
            //return quiescenceScore;
        }
        if (isWhite)           // white is trying to attain the highest evaluation possible

        {
            for (int i = 0; i < count; i++)
            {
                ushort move = moveHeap.RemoveFirst();
                Board.MakeMove(move);
                alpha = Math.Max(alpha, AlphaBetaSearch(plyRemaining - 1, alpha, beta, false));
                Board.UnmakeMove(move);

                if (plyRemaining == searchDepth)                   // has searched full depth and is now looking at top layer of moves to select the best
                {
                    if (alpha > bestScoreThisIteration)
                    {
                        bestScoreThisIteration = alpha;
                        bestMoveThisIteration  = move;
                    }
                }

                if (beta <= alpha)                   // break
                {
                    breakCount++;
                    break;
                }
            }
            return(alpha);
        }
        else
        {
            // black is trying to obtain the lowest evaluation possible
            for (int i = 0; i < count; i++)
            {
                ushort move = moveHeap.RemoveFirst();
                Board.MakeMove(move);
                beta = Math.Min(beta, AlphaBetaSearch(plyRemaining - 1, alpha, beta, true));
                Board.UnmakeMove(move);

                if (plyRemaining == searchDepth)                   // has searched full depth and is now looking at top layer of moves to select the best
                {
                    if (beta < bestScoreThisIteration)
                    {
                        bestScoreThisIteration = beta;
                        bestMoveThisIteration  = move;
                    }
                }

                if (beta <= alpha)                   // break
                {
                    breakCount++;
                    break;
                }
            }

            return(beta);
        }

        return(0);
    }
Exemple #27
0
        public Move WaitMove(Position position)
        {
            var moves = MoveGenerator.GetMoves(position);

            return(moves.ToList()[new Random().Next(moves.Count())]);
        }
Exemple #28
0
        public void Expect_white_pawn_can_make_double_move_from_2th_rank()
        {
            var target = new MoveGenerator(GameState.FromForsythEdwardsNotation("4k3/8/8/8/8/8/P7/4K3 w - -"));

            var moves = target.GetMoves();

            Assert.IsTrue(moves.Contains(new Move(Cell.a2, Cell.a4)));
        }
		public void GetMoves_Column3And3Full_5NoneEmptyFields()
		{
			var generator = new MoveGenerator();
			var field = Field.Parse(@"
				0,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,0,0,1,2,0,0;
				1,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,0,0,1,2,0,0");

			var act = generator.GetMoves(field, false);
			var exp = new Field[]
			{
				// Column 0
				Field.Parse(@"
				0,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,0,0,1,2,0,0;
				1,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,0,0,1,2,0,2"),

				// Column 1
				Field.Parse(@"
				0,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,0,0,1,2,0,0;
				1,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,0,0,1,2,2,0"),

				// Column 2
				Field.Empty,

				// Column 3
				Field.Empty,

				// Column 4
				Field.Parse(@"
				0,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,0,0,1,2,0,0;
				1,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,0,2,1,2,0,0"),

				// Column 5
				Field.Parse(@"
				0,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,0,0,1,2,0,0;
				1,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,2,0,1,2,0,0"),
				
				// Column 6
				Field.Parse(@"
				2,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,0,0,1,2,0,0;
				1,0,0,1,1,0,0;
				2,0,0,2,1,0,0;
				2,0,0,1,2,0,0"),
			};

			CollectionAssert.AreEqual(exp, act);

		}
		private static void AssertGetFields(string[] exp, Block block)
		{
			var generator = new MoveGenerator();
			var candidateFields = generator.GetMoves(TestData.Small, block).Select(candidate => candidate.Field.ToString()).ToArray();
			var fields = generator.GetFields(TestData.Small, block).Select(field => field.ToString()).ToArray();

			foreach (var field in candidateFields)
			{
				Console.WriteLine('"' + field + '"' + ',');
			}

			foreach (var field in candidateFields)
			{
				Console.WriteLine(field.Replace("|", Environment.NewLine));
				Console.WriteLine();
			}
			Assert.AreEqual(block.ChildCount, candidateFields.Length, "GetMoves for {0} has the wrong number of answers.", block.Name);
			CollectionAssert.AreEqual(exp, candidateFields, "Moves");
			CollectionAssert.AreEqual(exp, fields, "Fields");
		}
Exemple #31
0
        public void Expect_black_pawn_can_make_double_move_from_7th_rank()
        {
            var target = new MoveGenerator(GameState.FromForsythEdwardsNotation("4k3/p7/8/8/8/8/8/4K3 b - -"));

            var moves = target.GetMoves();

            Assert.IsTrue(moves.Contains(new Move(Cell.a7, Cell.a5)));
        }
    public bool ValidateEntry()
    {
        if (currentInput.Length > 0)
        {
            List <ushort> inputtedMoves = PGNReader.MovesFromPGN(currentInput);
            if (inputtedMoves.Count > 0)
            {
                string cleanedInput = PGNReader.MoveStringsFromPGN(currentInput) [0];

                ushort   inputMove     = inputtedMoves [0];
                int      movePieceCode = PieceTypeCodeFromNotation(cleanedInput) + ((Board.IsWhiteToPlay()) ? 1 : 0);
                ushort[] legalMoves    = moveGen.GetMoves(false, false).moves;

                bool ambiguousCaseSpecified = false;                 // does the inputted string describe an ambiguous case (e.g Rad1)
                if (cleanedInput.Length >= 3)
                {
                    ambiguousCaseSpecified = Definitions.fileNames.Contains(cleanedInput [2] + "");
                }
                if ((movePieceCode & ~1) == Board.kingCode || (movePieceCode & ~1) == Board.pawnCode)                   // king and pawn moves can't be ambiguous
                {
                    ambiguousCaseSpecified = true;
                }

                bool moveIsAmbiguous = false;

                if (!ambiguousCaseSpecified)                   // check if case is ambiguous if no specification has been given in input
                {
                    int movesFoundFollowingInput = 0;

                    for (int i = 0; i < legalMoves.Length; i++)
                    {
                        int moveFromIndex = legalMoves [i] & 127;
                        int moveToIndex   = (legalMoves [i] >> 7) & 127;
                        if (Board.boardArray [moveFromIndex] == movePieceCode && moveToIndex == ((inputMove >> 7) & 127))                           // is move as described by input string
                        {
                            movesFoundFollowingInput++;
                            if (movesFoundFollowingInput == 2)
                            {
                                moveIsAmbiguous = true;
                                break;
                            }
                        }
                    }
                }

                if (moveIsAmbiguous)
                {
                    uiManager.SetMessage("move is ambiguous. please specify file/rank of piece you wish to move", 3, true);
                }
                else
                {
                    if (player != null)
                    {
                        player.TryMakeMove(inputMove);
                    }
                    return(true);
                }
            }
            else
            {
                print("Move illegal/incorrect format");
            }
        }

        return(false);
    }
Exemple #33
0
	/// Returns a list of moves given a pgn string.
	/// Note that Board should be set to whatever starting position of pgn is.
	public static List<ushort> MovesFromPGN(string pgn) {
		List<string> moveStrings = MoveStringsFromPGN (pgn);
		List<ushort> allMoves = new List<ushort> ();

		MoveGenerator moveGen = new MoveGenerator ();

		for (int i =0; i < moveStrings.Count; i++) {
			string moveString = moveStrings[i];

			moveString = moveString.Replace("+",""); // remove check symbol
			moveString = moveString.Replace("#",""); // remove mate symbol
			moveString = moveString.Replace("x",""); // remove capture symbol
			string moveStringLower = moveStrings[i].ToLower();

			ushort[] movesInPosition = moveGen.GetMoves(false,false).moves;
			ushort move = 0;
			for (int j =0; j < movesInPosition.Length; j ++) {
				move = movesInPosition[j];
				int moveFromIndex = move & 127;
				int moveToIndex = (move >> 7) & 127;
				int movePieceType = Board.boardArray[moveFromIndex] & ~1;
				int colourCode = Board.boardArray[moveFromIndex] & 1;


				if (moveStringLower == "oo") { // castle kingside
					if (movePieceType == Board.kingCode && moveToIndex - moveFromIndex == 2) {
						break;
					}
				}
				else if (moveStringLower == "ooo") { // castle queenside
					if (movePieceType == Board.kingCode && moveToIndex - moveFromIndex == -2) {
						break;
					}
				}
				else if (Definitions.fileNames.Contains(moveString[0] + "")) { // pawn move if starts with any file indicator (e.g. 'e'4. Note that uppercase B is used for bishops)
					if (movePieceType != Board.pawnCode) {
						continue;
					}
					if (Definitions.FileNumberFromAlgebraicName(moveStringLower[0]) == Board.FileFrom128(moveFromIndex)) { // correct starting file
						if (moveString.Contains("=")) { // is promotion
							char promotionChar = moveStringLower[moveStringLower.Length-1];

							int promotionPieceIndex = move >> 14 & 3;
							int promotionPieceCode = Board.pieceCodeArray [promotionPieceIndex];

							if ((promotionPieceCode == Board.queenCode && promotionChar != 'q') || (promotionPieceCode == Board.rookCode && promotionChar != 'r')
							    || (promotionPieceCode == Board.bishopCode && promotionChar != 'b') || (promotionPieceCode == Board.knightCode && promotionChar != 'n')) {
								continue; // skip this move, incorrect promotion type
							}
							break;
						}
						else {
					
							char targetFile = moveString[moveString.Length-2];
							char targetRank = moveString[moveString.Length-1];

							if (Definitions.FileNumberFromAlgebraicName(targetFile) == Board.FileFrom128(moveToIndex)) { // correct ending file
								if (Definitions.RankNumberFromAlgebraicName(targetRank) == Board.RankFrom128(moveToIndex)) { // correct ending rank
									break;
								}
							}
						}
					}
				}
				else { // regular piece move
				
					char movePieceChar = moveString[0];
					if (!(movePieceType == Board.queenCode && movePieceChar == 'Q') && !(movePieceType == Board.rookCode && movePieceChar == 'R')
					    && !(movePieceType == Board.bishopCode && movePieceChar == 'B') && !(movePieceType == Board.knightCode && movePieceChar == 'N') && !(movePieceType == Board.kingCode && movePieceChar == 'K')) {
						continue; // skip this move, incorrect move piece type
					}

					char targetFile = moveString[moveString.Length-2];
					char targetRank = moveString[moveString.Length-1];
					if (Definitions.FileNumberFromAlgebraicName(targetFile) == Board.FileFrom128(moveToIndex)) { // correct ending file
						if (Definitions.RankNumberFromAlgebraicName(targetRank) == Board.RankFrom128(moveToIndex)) { // correct ending rank
							if (moveString.Length == 4) { // addition char present for disambiguation (e.g. Nbd7 or R7e2)
								char disambiguationChar = moveString[1];

								if (Definitions.fileNames.Contains(disambiguationChar + "")) { // is file disambiguation
									if (Definitions.FileNumberFromAlgebraicName(disambiguationChar) != Board.FileFrom128(moveFromIndex)) { // incorrect starting file
										continue;
									}
								}
								else { // is rank disambiguation
									if (Definitions.RankNumberFromAlgebraicName(disambiguationChar) != Board.RankFrom128(moveFromIndex)) { // incorrect starting rank
										continue;
									}

								}
							}
							break;
						}
					}
				}

			}
			if (move == 0) { // move is illegal; discard and return moves up to this point
				UnityEngine.Debug.Log(moveString);
				break;
			}
			else {
				allMoves.Add(move);
			}
			Board.MakeMove(move);
		}
		for (int i = allMoves.Count-1; i>= 0; i --) {
			Board.UnmakeMove(allMoves[i]);
		}

		return allMoves;
	}
Exemple #34
0
	public static string NotationFromMove(ushort move) {
		Board.UnmakeMove (move); // unmake move on board

		MoveGenerator moveGen = new MoveGenerator ();
		int moveFromIndex = move & 127;
		int moveToIndex = (move >> 7) & 127;
		int promotionPieceIndex = (move >> 14) & 3; // 0 = queen, 1 = rook, 2 = knight, 3 = bishop
		int colourToMove = Board.boardColourArray[moveFromIndex];
		
		int movePieceCode = Board.boardArray [moveFromIndex]; // get move piece code
		int movePieceType = movePieceCode & ~1; // get move piece type code (no colour info)
		int capturedPieceCode = Board.boardArray [moveToIndex]; // get capture piece code
		
		int promotionPieceType = Board.pieceCodeArray [promotionPieceIndex];
		
		if (movePieceType == Board.kingCode) {
			if (moveToIndex - moveFromIndex == 2) {
				Board.MakeMove (move); // remake move
				return "O-O";
			}
			else if (moveToIndex - moveFromIndex == -2) {
				Board.MakeMove (move); // remake move
				return "O-O-O";
			}
		}
		
		string moveNotation = GetSymbolFromPieceType(movePieceType);
		
		// check if any ambiguity exists in notation (e.g if e2 can be reached via Nfe2 and Nbe2)
		if (movePieceType != Board.pawnCode && movePieceType != Board.kingCode) {
			Heap allMoves = moveGen.GetMoves(false, false);
			
			for (int i =0; i < allMoves.Count; i ++) {
				int alternateMoveFromIndex = allMoves.moves[i] & 127;
				int alternateMoveToIndex = ( allMoves.moves[i]  >> 7) & 127;
				int alternateMovePieceCode = Board.boardArray [alternateMoveFromIndex];
				
				if (alternateMoveFromIndex != moveFromIndex && alternateMoveToIndex == moveToIndex) { // if moving to same square from different square
					if (alternateMovePieceCode == movePieceCode) { // same piece type
						int fromFileIndex = Board.FileFrom128(moveFromIndex) -1;
						int alternateFromFileIndex = Board.FileFrom128(alternateMoveFromIndex) -1;
						int fromRankIndex = Board.RankFrom128(moveFromIndex) -1;
						int alternateFromRankIndex = Board.RankFrom128(alternateMoveFromIndex) -1;
						
						if (fromFileIndex != alternateFromFileIndex) { // pieces on different files, thus ambiguity can be resolved by specifying file
							moveNotation += Definitions.fileNames[fromFileIndex];
							break; // ambiguity resolved
						}
						else if (fromRankIndex != alternateFromRankIndex) {
							moveNotation += Definitions.rankNames[fromRankIndex];
							break; // ambiguity resolved
						}
					}
				}
				
			}
		}
		
		if (capturedPieceCode != 0) { // add 'x' to indicate capture
			if (movePieceType == Board.pawnCode) {
				moveNotation += Definitions.fileNames[Board.FileFrom128(moveFromIndex)-1];
			}
			moveNotation += "x";
		} else { // check if capturing ep
			if (movePieceType == Board.pawnCode) {
				if (System.Math.Abs (moveToIndex - moveFromIndex) != 16 && System.Math.Abs (moveToIndex - moveFromIndex) != 32) {
					moveNotation += Definitions.fileNames[Board.FileFrom128(moveFromIndex)-1] + "x";
				}
			}
		}
		
		moveNotation += Definitions.fileNames [Board.FileFrom128 (moveToIndex) - 1];
		moveNotation += Definitions.rankNames [Board.RankFrom128 (moveToIndex) - 1];
		
		// add = piece type if promotion
		if (movePieceType == Board.pawnCode) {
			if (moveToIndex >= 112 || moveToIndex <= 7) { // pawn has reached first/eighth rank
				moveNotation += "=" + GetSymbolFromPieceType(promotionPieceType);
			}
		}
		
		// add check/mate symbol if applicable
		Board.MakeMove (move); // remake move
		if (moveGen.PositionIsMate ()) {
			moveNotation += "#";
		} else if (moveGen.PositionIsCheck ()) {
			moveNotation += "+";
		}
		return moveNotation;
	}