Beispiel #1
0
 public Board(Board b)
 {
     this.WhiteBitBoard = b.WhiteBitBoard;
     this.BlackBitBoard = b.BlackBitBoard;
     this.CurrentPlayer = b.CurrentPlayer;
     this.Evaluation = b.Evaluation;
 }
Beispiel #2
0
        public Board PlayFirstMove()
        {
            if (Color != PieceColor.White)
                throw new InvalidOperationException("Can't play first move as black");

            Board b = new Board();
            Random rnd = new Random();
            int x = rnd.Next(1, 5);
            int y = rnd.Next(1, 5);
            b.PlacePieceAt(x, y, PieceColor.White);
            b.CurrentPlayer = PieceColor.Black;
            return b;
        }
Beispiel #3
0
        // Gives high score to opposite color of .CurrentPlayer,
        // which is the color which presumably just played a move.
        // Negamax requires the evaluation function to keep track of
        // appropriately assigning +/- evaluations depending on who
        // is playing.
        public static int Evaluate(ref Board b)
        {
            int multiplier = (b.CurrentPlayer == PieceColor.White) ? -1 : 1;

            switch (b.GetWinner())
            {
                case PieceColor.Empty:
                    if (b.NumBlack() == 18)
                        return EVAL_DRAW;
                    break;
                case PieceColor.White:
                    return multiplier * EVAL_WHITE_WIN;
                case PieceColor.Black:
                    return multiplier * EVAL_BLACK_WIN;
                case PieceColor.Both:
                    return EVAL_DRAW;
            }

            return multiplier * EvaluateChains(ref b);
        }
Beispiel #4
0
        public static bool HasCheckmate(Board b, PieceColor pieceColor)
        {
            int whiteTemp = 0;
            int blackTemp = 0;
            UInt64 whiteLine = 0;
            UInt64 blackLine = 0;
            List<UInt64> lines = new List<UInt64>();

            for (int i = 0; i < BoardHelper.WinningLines.Length; i++)
            {
                whiteLine = b.WhiteBitBoard & BoardHelper.WinningLines[i];
                whiteTemp = BoardHelper.NumOneBits(whiteLine);
                blackLine = b.BlackBitBoard & BoardHelper.WinningLines[i];
                blackTemp = BoardHelper.NumOneBits(blackLine);

                if (pieceColor == PieceColor.White && blackTemp == 0 && whiteTemp == 4)
                {
                    foreach (UInt64 line in lines)
                    {
                        if (line == whiteLine)
                            return true;
                    }
                    lines.Add(whiteLine);
                }
                else if (pieceColor == PieceColor.Black && whiteTemp == 0 && blackTemp == 4)
                {
                    foreach (UInt64 line in lines)
                    {
                        if (line == blackLine)
                            return true;
                    }
                    lines.Add(blackLine);
                }
            }
            return false;
        }
Beispiel #5
0
 public abstract Board Play(Board b);
Beispiel #6
0
 private static int CompareEvaluations(Board a, Board b)
 {
     return -a.Evaluation.CompareTo(b.Evaluation);
 }
Beispiel #7
0
        /* Evaluation heurisitc:
         *      Consider each potential winning line.  If there is a black piece
         *      in the line, then it cannot be won by white, so score that line as zero.
         *      Otherwise, score the line as the # of white pieces residing in the line.
         *      Keep track of the highest scoring chain, and how many were found with
         *      that score.  Do the same for black.
         *
         *      Give most favor to longer chains, then secondary favor to the number of
         *      such chains present.  Create a positive white score this way, then
         *      subtract off the corresponding black score using the same logic.
         *
         *      Always gives positive score to white, negative to black.  Up to the
         *      caller to multiply by -1 if needed.
         */
        private static int EvaluateChains(ref Board b)
        {
            int longestWhiteChain = 0;
            int numLongestWhiteChain = 0;
            int longestBlackChain = 0;
            int numLongestBlackChain = 0;
            UInt64 whiteTemp, blackTemp;
            int temp;

            for (int i = 0; i < BoardHelper.WinningLines.Length; i++)
            {
                // how many white pieces are in this line
                whiteTemp = b.WhiteBitBoard & BoardHelper.WinningLines[i];
                // how many black pieces are in this line
                blackTemp = b.BlackBitBoard & BoardHelper.WinningLines[i];

                if (blackTemp == 0 && whiteTemp != 0)
                {
                    temp = BoardHelper.NumCommonOneBits(b.WhiteBitBoard, BoardHelper.WinningLines[i]);
                    if (temp >= longestWhiteChain)
                    {
                        if (temp == longestWhiteChain)
                            numLongestWhiteChain++;
                        else
                        {
                            longestWhiteChain = temp;
                            numLongestWhiteChain = 1;
                        }
                    }
                    continue;  // no need to evaluate black
                }
                if (whiteTemp == 0 && blackTemp != 0)
                {
                    temp = BoardHelper.NumCommonOneBits(b.BlackBitBoard, BoardHelper.WinningLines[i]);
                    if (temp >= longestBlackChain)
                    {
                        if (temp == longestBlackChain)
                            numLongestBlackChain++;
                        else
                        {
                            longestBlackChain = temp;
                            numLongestBlackChain = 1;
                        }
                    }
                }
            }

            return (100 * longestWhiteChain + numLongestWhiteChain) - (100 * longestBlackChain + numLongestBlackChain);
        }
Beispiel #8
0
        private void DoAiMoveComplete(Board aiBoard)
        {
            FadeBottomText.Stop();

            Move aiMove = GetMoveFromBoards(masterBoard, aiBoard);
            Debug.Assert(false, String.Format("x: {0} y:{1} r:{2}", aiMove.xCoord, aiMove.yCoord, aiMove.rotation));

            if (aiMove.pieceColor != PieceColor.Empty)
            {
                AnimateMove(aiMove);

                masterBoard = new Board(aiBoard);
            }
            if (masterBoard.IsDraw())
            {
                okToClickDots = false;
                okToRotateQuadrant = false;
                BottomText.Text = "";
                PopupTextBoxText.Text = "draw!";

                Thread.Sleep(1000);
                PopupPanel.Visibility = System.Windows.Visibility.Visible;

            }
            else if (masterBoard.GetWinner() != PieceColor.Empty)
            {
                okToClickDots = false;
                okToRotateQuadrant = false;

                BottomText.Text = "";

                PopupTextBoxText.Text = String.Format("{0} wins!", masterBoard.GetWinner() == PieceColor.White ? "white" : "black");

                PopupPanel.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                BottomText.Text = "your move";
                okToClickDots = true;
            }
            aiThinking = false;
        }
Beispiel #9
0
        private void DoAiMoveComplete(Board aiBoard)
        {
            FadeBottomText.Stop();

            Move aiMove = GetMoveFromBoards(masterBoard, aiBoard);
            Debug.Assert(false, String.Format("x: {0} y:{1} r:{2}", aiMove.xCoord, aiMove.yCoord, aiMove.rotation));

            if (aiMove.pieceColor != PieceColor.Empty)
            {
                AnimateMove(aiMove);
                masterBoard = new Board(aiBoard);
            }
            if (masterBoard.IsDraw())
            {
                BottomText.Text = "Draw!";
                okToClickDots = false;
                okToRotateQuadrant = false;
            }
            else if (masterBoard.GetWinner() != PieceColor.Empty)
            {
                if (masterBoard.GetWinner() == playerColor)
                {
                    BottomText.Text = "You win!";
                }
                else
                {
                    BottomText.Text = "Computer wins!";
                }
                okToClickDots = false;
                okToRotateQuadrant = false;
            }
            else
            {
                BottomText.Text = "Your move";
                okToClickDots = true;
            }
            aiThinking = false;
        }
Beispiel #10
0
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // ignore new game requests if the ai is running
            if (aiThinking)
                return;

            HowTo.Visibility = Visibility.Collapsed;
            HowToText.Visibility = Visibility.Collapsed;

            okToRotateQuadrant = false;
            okToClickDots = false;

            UpperLeft.Reset();
            UpperRight.Reset();
            LowerLeft.Reset();
            LowerRight.Reset();

            masterBoard = new Board();

            if ((bool)playerBlackRadioButton.IsChecked)
            {
                playerColor = PieceColor.Black;

                if ((bool)aiEasyRadioButton.IsChecked)
                {
                    Debug.Assert(false, "Easy");
                    masterAI = new FixedDepthPlayer(PieceColor.White, 0);
                }
                else if ((bool)aiMediumRadioButton.IsChecked)
                {
                    Debug.Assert(false,"Med");
                    masterAI = new FixedDepthPlayer(PieceColor.White, 2);
                }
                else
                {
                    Debug.Assert(false, "Hard");
                    masterAI = new FixedTimePlayer(PieceColor.White, 5);
                }

                aiThinking = true;
                DoAiMove();
            }
            else
            {
                playerColor = PieceColor.White;
                if ((bool)aiEasyRadioButton.IsChecked)
                    masterAI = new FixedDepthPlayer(PieceColor.Black, 0);
                else if ((bool)aiMediumRadioButton.IsChecked)
                    masterAI = new FixedDepthPlayer(PieceColor.Black, 2);
                else
                    masterAI = new FixedTimePlayer(PieceColor.Black, 5);
                okToClickDots = true;
                okToRotateQuadrant = false;
                BottomText.Text = "Your move";
            }
        }
Beispiel #11
0
        // Finds all unique boards possible after applying a move by the current player
        public List<Board> GenerateSubBoards()
        {
            Dictionary<Board, int> boards = new Dictionary<Board, int>(256);

            if (this.GetWinner() != PieceColor.Empty)
                return new List<Board>();

            Board b = new Board(this);

            for (int i = 0; i < 6; i++)
            {
                for (int j = 0; j < 6; j++)
                {
                    if (this.GetColorAt(i, j) == PieceColor.Empty)
                    {
                        b.Copy(this);
                        b.ApplyMoveFast(i, j, this.CurrentPlayer, Rotation.LowerLeftAntiClockwise);
                        if (!boards.ContainsKey(b))
                        {
                            b.Evaluation = BoardEvaluator.Evaluate(ref b);
                            boards.Add(new Board(b), 0);
                        }
                        b.Copy(this);
                        b.ApplyMoveFast(i, j, this.CurrentPlayer, Rotation.LowerLeftClockwise);
                        if (!boards.ContainsKey(b))
                        {
                            b.Evaluation = BoardEvaluator.Evaluate(ref b);
                            boards.Add(new Board(b), 0);
                        }
                        b.Copy(this);
                        b.ApplyMoveFast(i, j, this.CurrentPlayer, Rotation.LowerRightAntiClockwise);
                        if (!boards.ContainsKey(b))
                        {
                            b.Evaluation = BoardEvaluator.Evaluate(ref b);
                            boards.Add(new Board(b), 0);
                        }
                        b.Copy(this);
                        b.ApplyMoveFast(i, j, this.CurrentPlayer, Rotation.LowerRightClockwise);
                        if (!boards.ContainsKey(b))
                        {
                            b.Evaluation = BoardEvaluator.Evaluate(ref b);
                            boards.Add(new Board(b), 0);
                        }
                        b.Copy(this);
                        b.ApplyMoveFast(i, j, this.CurrentPlayer, Rotation.UpperLeftAntiClockwise);
                        if (!boards.ContainsKey(b))
                        {
                            b.Evaluation = BoardEvaluator.Evaluate(ref b);
                            boards.Add(new Board(b), 0);
                        }
                        b.Copy(this);
                        b.ApplyMoveFast(i, j, this.CurrentPlayer, Rotation.UpperLeftClockwise);
                        if (!boards.ContainsKey(b))
                        {
                            b.Evaluation = BoardEvaluator.Evaluate(ref b);
                            boards.Add(new Board(b), 0);
                        }
                        b.Copy(this);
                        b.ApplyMoveFast(i, j, this.CurrentPlayer, Rotation.UpperRightAntiClockwise);
                        if (!boards.ContainsKey(b))
                        {
                            b.Evaluation = BoardEvaluator.Evaluate(ref b);
                            boards.Add(new Board(b), 0);
                        }
                        b.Copy(this);
                        b.ApplyMoveFast(i, j, this.CurrentPlayer, Rotation.UpperRightClockwise);
                        if (!boards.ContainsKey(b))
                        {
                            b.Evaluation = BoardEvaluator.Evaluate(ref b);
                            boards.Add(new Board(b), 0);
                        }
                    }
                }
            }

            return new List<Board>(boards.Keys);
        }
Beispiel #12
0
        public List<Board> GenerateSafeBoards(bool includeCheckmates)
        {
            List<Board> boards = this.GenerateSubBoards();
            Board workingBoard = new Board();

            for (int k = 0; k < boards.Count; k++)
            {
                workingBoard.Copy(boards[k]);

                foreach (Board b in workingBoard.GenerateSubBoards())
                {
                    if (b.GetWinner() == workingBoard.CurrentPlayer)
                    {
                        boards.RemoveAt(k);
                        k--;
                        break;
                    }
                    if(includeCheckmates &&
                        BoardEvaluator.HasCheckmate(b, workingBoard.CurrentPlayer))
                    {
                        boards.RemoveAt(k);
                        k--;
                        break;
                    }
                }
            }
            return boards;
        }
Beispiel #13
0
        private void NewGameButton_Click(object sender, EventArgs e)
        {
            // ignore new game requests if the ai is running
            if (aiThinking)
                return;

            okToRotateQuadrant = false;
            okToClickDots = false;

            UpperLeft.Reset();
            UpperRight.Reset();
            LowerLeft.Reset();
            LowerRight.Reset();

            PopupPanel.Visibility = System.Windows.Visibility.Collapsed;

            masterBoard = new Board();

            this.currentGameStyle = settings.GameStyleSetting;

            if (this.currentGameStyle == GameStyle.VsAi && settings.PlayerColorSetting == PieceColor.Black)
            {
                playerColor = PieceColor.Black;

                if (0 == settings.AiStrengthSetting)
                {
                    Debug.Assert(false, "Easy");
                    masterAI = new FixedDepthPlayer(PieceColor.White, 0);
                }
                else if (1 == settings.AiStrengthSetting)
                {
                    Debug.Assert(false, "Med");
                    masterAI = new FixedDepthPlayer(PieceColor.White, 2);
                }
                else
                {
                    Debug.Assert(false, "Hard");
                    masterAI = new FixedTimePlayer(PieceColor.White, 5);
                }

                aiThinking = true;
                DoAiMove();
            }
            else if (this.currentGameStyle == GameStyle.VsAi && settings.PlayerColorSetting == PieceColor.White)
            {
                playerColor = PieceColor.White;
                if (0 == settings.AiStrengthSetting)
                       masterAI = new FixedDepthPlayer(PieceColor.Black, 0);
                else if (1 == settings.AiStrengthSetting)
                    masterAI = new FixedDepthPlayer(PieceColor.Black, 2);
                     else
                        masterAI = new FixedTimePlayer(PieceColor.Black, 5);
                okToClickDots = true;
                okToRotateQuadrant = false;
                BottomText.Text = "your move";
            }
            else if (this.currentGameStyle == GameStyle.VsHuman)
            {
                playerColor = PieceColor.White;

                okToClickDots = true;
                okToRotateQuadrant = false;
                BottomText.Text = "white's move";
            }
        }
Beispiel #14
0
        // negamax style alpha beta pruning search
        private int AlphaBeta(Board b, int depth, int alpha, int beta)
        {
            DateTime currentTime = DateTime.Now;
            if ((currentTime - startTime).TotalSeconds > thinkTimeSeconds)
                return TIMEUP;

            if (depth == 0)
                return -b.Evaluation;

            switch (b.GetWinner())
            {
                case PieceColor.White:
                    return (b.CurrentPlayer == PieceColor.White) ? BoardEvaluator.EVAL_WHITE_WIN : -BoardEvaluator.EVAL_WHITE_WIN;
                case PieceColor.Black:
                    return (b.CurrentPlayer == PieceColor.White) ? BoardEvaluator.EVAL_BLACK_WIN : -BoardEvaluator.EVAL_BLACK_WIN;
                case PieceColor.Both:
                    return BoardEvaluator.EVAL_DRAW;
                case PieceColor.Empty:
                    break;
            }

            List<Board> boards = b.GenerateSubBoards();
            if (boards.Count == 0)
                return NOMOVES;

            BoardEvaluator.SortBoards(ref boards);

            int current;
            int best = MINSCORE;
            int localAlpha = alpha;

            for (int i = 0; i < boards.Count; i++)
            {
                current = -AlphaBeta(boards[i], depth - 1, -beta, -localAlpha);

                if (current == -NOMOVES)
                    current = boards[i].Evaluation;

                else if (current == -TIMEUP)
                    return TIMEUP;

                best = Math.Max(current, best);

                if (best >= beta)
                    return beta;

                if (best > localAlpha)
                    localAlpha = best;
            }
            return best;
        }
Beispiel #15
0
        private Move GetMoveFromBoards(Board currentBoard, Board aiBoard)
        {
            Move returnMove = new Move();
            if (currentBoard.Equals(aiBoard))
            {
                returnMove.pieceColor = PieceColor.Empty;
                return returnMove;
            }

            PieceColor moveColor = (aiBoard.CurrentPlayer == PieceColor.White) ? PieceColor.Black: PieceColor.White;

            returnMove.pieceColor = moveColor;

            Board b = new Board(currentBoard);

            for (int i = 0; i < 6; i++)
            {
                for (int j = 0; j < 6; j++)
                {
                    b.Copy(currentBoard);
                    if (b.GetColorAt(i, j) == PieceColor.Empty)
                    {
                        returnMove.xCoord = i;
                        returnMove.yCoord = j;

                        b.Copy(currentBoard);
                        b.PlacePieceAt(i, j, moveColor);
                        b.DoRotation(Rotation.LowerLeftAntiClockwise);
                        if (b.Equals(aiBoard))
                        {
                            returnMove.rotation = Rotation.LowerLeftAntiClockwise;
                            return returnMove;
                        }

                        b.Copy(currentBoard);
                        b.PlacePieceAt(i, j, moveColor);
                        b.DoRotation(Rotation.LowerLeftClockwise);
                        if (b.Equals(aiBoard))
                        {
                            returnMove.rotation = Rotation.LowerLeftClockwise;
                            return returnMove;
                        }

                        b.Copy(currentBoard);
                        b.PlacePieceAt(i, j, moveColor);
                        b.DoRotation(Rotation.LowerRightAntiClockwise);
                        if (b.Equals(aiBoard))
                        {
                            returnMove.rotation = Rotation.LowerRightAntiClockwise;
                            return returnMove;
                        }

                        b.Copy(currentBoard);
                        b.PlacePieceAt(i, j, moveColor);
                        b.DoRotation(Rotation.LowerRightClockwise);
                        if (b.Equals(aiBoard))
                        {
                            returnMove.rotation = Rotation.LowerRightClockwise;
                            return returnMove;
                        }

                        b.Copy(currentBoard);
                        b.PlacePieceAt(i, j, moveColor);
                        b.DoRotation(Rotation.UpperLeftAntiClockwise);
                        if (b.Equals(aiBoard))
                        {
                            returnMove.rotation = Rotation.UpperLeftAntiClockwise;
                            return returnMove;
                        }

                        b.Copy(currentBoard);
                        b.PlacePieceAt(i, j, moveColor);
                        b.DoRotation(Rotation.UpperLeftClockwise);
                        if (b.Equals(aiBoard))
                        {
                            returnMove.rotation = Rotation.UpperLeftClockwise;
                            return returnMove;
                        }

                        b.Copy(currentBoard);
                        b.PlacePieceAt(i, j, moveColor);
                        b.DoRotation(Rotation.UpperRightAntiClockwise);
                        if (b.Equals(aiBoard))
                        {
                            returnMove.rotation = Rotation.UpperRightAntiClockwise;
                            return returnMove;
                        }

                        b.Copy(currentBoard);
                        b.PlacePieceAt(i, j, moveColor);
                        b.DoRotation(Rotation.UpperRightClockwise);
                        if (b.Equals(aiBoard))
                        {
                            returnMove.rotation = Rotation.UpperRightClockwise;
                            return returnMove;
                        }
                    }
                }
            }
            // shouldn't ever get here
            Debug.Assert(false, "Bogus move \r\n" + masterBoard.ToString());
            return returnMove;
        }
Beispiel #16
0
        public override Board Play(Board b)
        {
            if (b.CurrentPlayer != this.Color)
                throw new InvalidOperationException();

            List<Board> boards = b.GenerateSafeBoards(true);

            Debug.WriteLine("Safe moves: " + boards.Count.ToString());

            // if opponent wins on their next move no matter what
            if (boards.Count == 0)
            {
                // if we have a legal move, do it even though it's a loser
                boards = b.GenerateSubBoards();
                if(boards.Count == 0)
                    return b;
                return boards[0];
            }

            BoardEvaluator.SortBoards(ref boards);

            int current;
            int localAlpha = MINSCORE;
            Board bestBoard = boards[0];
            Board bestBoardLastCompletedDepth = boards[0];
            int lastCompletedDepth = 1;
            int lastCompletedDepthScore = 0;

            startTime = DateTime.Now;

            for (int depth = 1; depth < 36; depth++)
            {
                localAlpha = MINSCORE;
                int i;
                for (i = 0; i < boards.Count; i++)
                {
                    current = -AlphaBeta(boards[i], depth, MINSCORE, -localAlpha);
                    if (current == -TIMEUP)
                        break;
                    if (current == -NOMOVES)
                        current = boards[i].Evaluation;

                    boards[i].Evaluation = current;

                    if (current > localAlpha)
                    {
                        localAlpha = current;
                        bestBoard = boards[i];
                        if (current == BoardEvaluator.EVAL_WHITE_WIN)
                        {
                            lastCompletedDepth = depth;
                            lastCompletedDepthScore = current;
                            bestBoardLastCompletedDepth = bestBoard;
                            break;
                        }
                    }
                }

                // bail from the loop if we didn't make it
                // all the way through the search at this depth
                if (i != boards.Count)
                    break;

                // otherwise save the best move
                lastCompletedDepthScore = localAlpha;
                lastCompletedDepth = depth;
                bestBoardLastCompletedDepth = bestBoard;

                // re-sort the boards after each completed depth
                //   to increase the number of cutoffs at the next depth
                BoardEvaluator.SortBoards(ref boards);
            }

            Debug.WriteLine(String.Format("Depth: {0} Score: {1}", lastCompletedDepth, lastCompletedDepthScore));
            return bestBoardLastCompletedDepth;
        }
Beispiel #17
0
        public override Board Play(Board b)
        {
            if (b.CurrentPlayer != this.Color)
                throw new InvalidOperationException();

            Debug.Assert(false, b.ToString());

            List<Board> boards;
            if (maxDepth == 2)
                boards = b.GenerateSafeBoards(true);
            else
                boards = b.GenerateSafeBoards();

            Debug.WriteLine("Safe moves: " + boards.Count.ToString());

            // if opponent wins on their next move no matter what
            if (boards.Count == 0)
            {
                // if we have a legal move, do it even though it's a loser
                boards = b.GenerateSubBoards();
                if(boards.Count == 0)
                    return b;
                return boards[0];
            }

            BoardEvaluator.SortBoards(ref boards);

            int current;
            int localAlpha = MINSCORE;
            Board bestBoard = boards[0];

            DateTime startTime = DateTime.Now;
            positionsEvaluated = 0;

            for (int i = 0; i < boards.Count; i++)
            {
              //  Console.Write("+");

                current = -AlphaBeta(boards[i], maxDepth, MINSCORE, -localAlpha);
                if (current == -NOMOVES)
                    current = boards[i].Evaluation;

                if (current > localAlpha)
                {
                    localAlpha = current;
                    bestBoard = boards[i];
                    if (current == BoardEvaluator.EVAL_WHITE_WIN)
                        break;
                }
            }

            DateTime endTime = DateTime.Now;
            TimeSpan moveTime = endTime - startTime;

            //Console.WriteLine(" Score: " + localAlpha.ToString());
            //Console.WriteLine("Time: {0}", moveTime.TotalSeconds);
            //Console.WriteLine("Moves evaluated: {0}", positionsEvaluated);
            //Console.WriteLine("Moves/sec: {0}", positionsEvaluated / moveTime.TotalSeconds);

            Debug.Assert(false, bestBoard.ToString());
            return bestBoard;
        }