Beispiel #1
0
        public void WinForPlayerYIsNotWinForPlayerX()
        {
            int  score  = MoveScoreConverter.ConvertWin(Occupied.PlayerY, 0);
            bool result = MoveScoreConverter.IsImmediateWin(Occupied.PlayerX, score);

            Assert.IsFalse(result);
        }
Beispiel #2
0
        public void DescribeYWinner()
        {
            int    score       = MoveScoreConverter.ConvertWin(Occupied.PlayerY, 2);
            string description = MoveScoreConverter.DescribeScore(score);

            Assert.AreEqual("Win by Y in 2 moves", description);
        }
Beispiel #3
0
        public void EqualScoresAreNotBetterForEitherPlayer()
        {
            const int Score = 0;

            Assert.IsFalse(MoveScoreConverter.IsBetterFor(Score, Score, true));
            Assert.IsFalse(MoveScoreConverter.IsBetterFor(Score, Score, false));
        }
Beispiel #4
0
        /// <summary>
        /// public wrapper for recursion
        /// try each possible move, find the one with the best score
        /// </summary>
        /// <param name="lookahead">how far to look ahead</param>
        /// <param name="playerX">is this for player x</param>
        /// <returns>The data on the best move location and score</returns>
        public MinimaxResult DoMinimax(int lookahead, bool playerX)
        {
            // set up inital state
            DateTime startTime = DateTime.Now;

            if (lookahead < 1)
            {
                throw new Exception("Invalid lookahead of " + lookahead);
            }

            this.debugDataItems.Clear();

            Occupied player = playerX.ToPlayer();
            int      alpha  = MoveScoreConverter.ConvertWin(player.Opponent(), 0);
            int      beta   = MoveScoreConverter.ConvertWin(player, 0);

            MinimaxResult bestMove = this.ScoreBoard(lookahead, this.ActualBoard, playerX, alpha, beta);

            if (bestMove.Move != Location.Null)
            {
                GoodMoves.AddGoodMove(0, bestMove.Move);
            }

            DateTime endTime = DateTime.Now;

            this.MoveTime = endTime - startTime;

            return(bestMove);
        }
Beispiel #5
0
        public void IsImmediateWinSuccessForPlayerX()
        {
            int  score  = MoveScoreConverter.ConvertWin(Occupied.PlayerX, 0);
            bool result = MoveScoreConverter.IsImmediateWin(Occupied.PlayerX, score);

            Assert.IsTrue(result);
        }
Beispiel #6
0
        public void WinIsBetterForPlayerY()
        {
            int winScoreX = MoveScoreConverter.ConvertWin(Occupied.PlayerX, 2);
            int winScoreY = MoveScoreConverter.ConvertWin(Occupied.PlayerY, 2);

            Assert.IsTrue(MoveScoreConverter.IsBetterFor(winScoreY, winScoreX, false));
            Assert.IsFalse(MoveScoreConverter.IsBetterFor(winScoreY, winScoreX, true));
        }
Beispiel #7
0
        public void LowerScoreIsBetterForPlayerX()
        {
            const int PlayerXScore = 1;
            const int PlayerYScore = -1;

            Assert.IsFalse(MoveScoreConverter.IsBetterFor(PlayerYScore, PlayerXScore, true));
            Assert.IsTrue(MoveScoreConverter.IsBetterFor(PlayerYScore, PlayerXScore, false));
        }
Beispiel #8
0
        public void WinForPlayerXIsGreaterThanWinForPlayerY()
        {
            int playerXWin = MoveScoreConverter.ConvertWin(Occupied.PlayerX, 0);
            int playerYWin = MoveScoreConverter.ConvertWin(Occupied.PlayerY, 0);

            Assert.Greater(playerXWin, playerYWin);
            Assert.Greater(playerXWin, 0);
            Assert.Less(playerYWin, 0);
        }
Beispiel #9
0
        public void NegativeScoreIsNotImmediateWin()
        {
            const int Score      = -12;
            bool      resultForX = MoveScoreConverter.IsImmediateWin(Occupied.PlayerX, Score);
            bool      resultForY = MoveScoreConverter.IsImmediateWin(Occupied.PlayerY, Score);

            Assert.IsFalse(resultForX, "X");
            Assert.IsFalse(resultForY, "Y");
        }
Beispiel #10
0
        public void LaterWinForPLayerXIsNotImmediateWin()
        {
            int  score      = MoveScoreConverter.ConvertWin(Occupied.PlayerX, 1);
            bool resultForX = MoveScoreConverter.IsImmediateWin(Occupied.PlayerX, score);
            bool resultForY = MoveScoreConverter.IsImmediateWin(Occupied.PlayerY, score);

            Assert.IsFalse(resultForX, "X");
            Assert.IsFalse(resultForY, "Y");
        }
Beispiel #11
0
        public void NearWinForPlayerXIsGreater()
        {
            int playerXWin    = MoveScoreConverter.ConvertWin(Occupied.PlayerX, 1);
            int playerXFarWin = MoveScoreConverter.ConvertWin(Occupied.PlayerX, 2);

            Assert.Greater(playerXWin, playerXFarWin);
            Assert.Greater(playerXFarWin, 0);
            Assert.Greater(playerXWin, 0);
        }
Beispiel #12
0
        public void NearWinForPlayerYIsLessNegative()
        {
            int playerYWin    = MoveScoreConverter.ConvertWin(Occupied.PlayerY, 1);
            int playerYFarWin = MoveScoreConverter.ConvertWin(Occupied.PlayerY, 2);

            Assert.Less(playerYWin, playerYFarWin);
            Assert.Less(playerYFarWin, 0);
            Assert.Less(playerYWin, 0);
        }
Beispiel #13
0
 public void MoveWins()
 {
     if (MoveScoreConverter.IsWinForPlayer(this.Score, Occupied.PlayerX))
     {
         this.Score--;
     }
     else if (MoveScoreConverter.IsWinForPlayer(this.Score, Occupied.PlayerY))
     {
         this.Score++;
     }
 }
Beispiel #14
0
        private static void TestBestMove(HexGame game, int level, Location expectedBestMove)
        {
            Minimax       hexPlayer = new Minimax(game.Board, game.GoodMoves, new CandidateMovesAll());
            MinimaxResult bestMove  = hexPlayer.DoMinimax(level, true);

            // test the location of the move
            Assert.AreEqual(expectedBestMove, bestMove.Move, "Wrong move at level " + level);

            // test the expected score
            if (level >= 3)
            {
                Assert.AreEqual(Occupied.PlayerX, MoveScoreConverter.Winner(bestMove.Score));
            }
        }
Beispiel #15
0
        public void TestCalculateMove2MinimaxPlayerY()
        {
            HexBoard board = new HexBoard(3);

            PlayTwoMoves(board);

            Minimax       minimax            = MakeMinimaxForBoard(board);
            MinimaxResult secondPlayerResult = minimax.DoMinimax(2, false);

            Location expectedPlay = new Location(0, 2);

            Assert.AreEqual(expectedPlay, secondPlayerResult.Move, "Wrong play location");
            Assert.IsFalse(MoveScoreConverter.IsWin(secondPlayerResult.Score));
        }
Beispiel #16
0
        public MinimaxResult DoMinimax(int depth, bool isComputer)
        {
            // megmondja, hogy ki a jatekos, ha a gep, akkor az isComputerben true van, es akkor a plyaerben xPlayer lesz.
            Occupied player = isComputer.ToPlayer();

            // a gep az alpha
            this.alpha = MoveScoreConverter.ConvertWin(player.Opponent(), 0);
            // ember a beta
            this.beta = MoveScoreConverter.ConvertWin(player, 0);
            // a minimax algoritmus magaban
            MinimaxResult bestMove = this.MiniMaxAlg(depth, isComputer, board);

            if (bestMove.Move != Location.Null)
            {
                // killer heurisztika
                GoodMoves.AddGoodMove(0, bestMove.Move);
            }
            return(bestMove);
        }
Beispiel #17
0
        public void TestMinimax3()
        {
            HexBoard board   = new HexBoard(5);
            Minimax  minimax = MakeMinimaxForBoard(board);

            /*
             *  on a 5 * 5 board, red(playerx) has 3, 0 and 1, 4
             *  needs to play 2,2 to win - should know this at look ahead 5
             */

            board.PlayMove(3, 0, true);
            board.PlayMove(1, 4, true);

            MinimaxResult bestMove     = minimax.DoMinimax(5, true);
            Location      expectedMove = new Location(2, 2);

            Assert.IsTrue(MoveScoreConverter.IsWin(bestMove.Score), "No win " + bestMove.Score);
            Assert.AreEqual(expectedMove, bestMove.Move, "Wrong expected move");
        }
Beispiel #18
0
        public int SituationScore()
        {
            int playerXScore = this.PlayerScore(true);

            if (playerXScore == 0)
            {
                // player x wins
                return(MoveScoreConverter.ConvertWin(Occupied.PlayerX, 0));
            }

            if (playerXScore == PathLengthConstants.OffPath)
            {
                // player X loses -> player y wins
                return(MoveScoreConverter.ConvertWin(Occupied.PlayerY, 0));
            }

            // no win yet. score for the situation
            int playerYScore = this.PlayerScore(false);

            return(playerYScore - playerXScore);
        }
        private Location GetBestMove(MinimaxResult playResult)
        {
            Location result = playResult.Move;

            int moveScore = playResult.Score;

            this.IsGameWon = MoveScoreConverter.IsWin(moveScore) && MoveScoreConverter.WinDepth(moveScore) == 1;

            Occupied opponent   = (!this.hexGame.PlayerX).ToPlayer();
            bool     losingMove = MoveScoreConverter.Winner(playResult.Score) == opponent;

            if (losingMove)
            {
                Location losingLocation = this.MakeLosingMove();
                if (losingLocation != Location.Null)
                {
                    result = losingLocation;
                }
            }

            return(result);
        }
Beispiel #20
0
 private static void AssertWinner(int score, Occupied winner)
 {
     Assert.IsTrue(MoveScoreConverter.IsWin(score), "Should have winner");
     Assert.AreEqual(winner, MoveScoreConverter.Winner(score), "Wrong winner");
 }
Beispiel #21
0
        /// <summary>
        /// private recursive worker - does the minimax algorithm
        /// </summary>
        /// <param name="lookahead">the current ply, counts down to zero</param>
        /// <param name="stateBoard">the current board</param>
        /// <param name="isPlayerX">player X or player Y</param>
        /// <param name="alpha">alpha value used in alpha-beta pruning</param>
        /// <param name="beta">beta value used in alpha-beta pruning</param>
        /// <returns>the score of the board and best move location</returns>
        private MinimaxResult ScoreBoard(
            int lookahead,
            HexBoard stateBoard,
            bool isPlayerX,
            int alpha,
            int beta)
        {
            this.CountBoards++;

            MinimaxResult bestResult = null;
            Location      cutoffMove = Location.Null;

            var possibleMoves = this.candidateMovesFinder.CandidateMoves(stateBoard, lookahead);

            foreach (Location move in possibleMoves)
            {
                // end on null loc
                if (move.IsNull())
                {
                    break;
                }

                if (this.GenerateDebugData)
                {
                    this.AddDebugDataItem(lookahead, move, isPlayerX, alpha, beta);
                }

                // make a speculative board, like the current, but with this cell played
                HexBoard testBoard = this.boardCache.GetBoard();
                testBoard.CopyStateFrom(stateBoard);

                testBoard.PlayMove(move, isPlayerX);
                MinimaxResult moveScore;

                PathLengthBase staticAnalysis = this.pathLengthFactory.CreatePathLength(testBoard);
                int            situationScore = staticAnalysis.SituationScore();

                if (lookahead <= 1)
                {
                    // we have reached the limits of lookahead - return the situation score
                    moveScore = new MinimaxResult(situationScore);
                }
                else if (MoveScoreConverter.IsWin(situationScore))
                {
                    // stop - someone has won
                    moveScore = new MinimaxResult(situationScore);
                }
                else
                {
                    // recurse
                    moveScore = this.ScoreBoard(lookahead - 1, testBoard, !isPlayerX, beta, alpha);
                    moveScore.MoveWins();
                }

                moveScore.Move = move;

                this.boardCache.Release(testBoard);

                // higher scores are good for player x, lower scores for player y
                if (bestResult == null || MoveScoreConverter.IsBetterFor(moveScore.Score, bestResult.Score, isPlayerX))
                {
                    bestResult = new MinimaxResult(move, moveScore);
                }

                // do the alpha-beta pruning
                alpha = CheckAlpha(alpha, moveScore.Score, isPlayerX);

                if (IsAlphaBetaCutoff(isPlayerX, alpha, beta))
                {
                    cutoffMove       = move;
                    bestResult.Score = alpha;
                    break;
                }

                // end a-b pruning
            }

            if (bestResult != null)
            {
                GoodMoves.AddGoodMove(lookahead, bestResult.Move);
            }

            if (cutoffMove != Location.Null)
            {
                GoodMoves.AddGoodMove(lookahead, cutoffMove);
            }

            return(bestResult);
        }
Beispiel #22
0
        public void DescribeNegativeScore()
        {
            string description = MoveScoreConverter.DescribeScore(-13);

            Assert.AreEqual("Y ahead with -13", description);
        }
Beispiel #23
0
        public void DescribePositiveScore()
        {
            string description = MoveScoreConverter.DescribeScore(12);

            Assert.AreEqual("X ahead with 12", description);
        }
Beispiel #24
0
        public void DescribeZeroScore()
        {
            string description = MoveScoreConverter.DescribeScore(0);

            Assert.AreEqual("Score: 0", description);
        }
Beispiel #25
0
        private MinimaxResult MiniMaxAlg(int depth, bool isComputer, HexBoard board)
        {
            BoardCache    boardCache = new BoardCache(board.Size);
            MinimaxResult bestResult = null;
            Location      cutOffMove = Location.Null;
            // az ures cellakat tartalmazza
            var possibleMoves = candidateMovesFinder.CandidateMoves(board, depth);

            foreach (Location move in possibleMoves)
            {
                if (!move.IsNull())
                {
                    // nem az eredetit modositom meg, hanem letrehozok egyet a peldajara
                    HexBoard board1 = new HexBoard(board.Size);
                    board1.CopyStateFrom(board);
                    board1.PlayMove(move, isComputer);


                    // itt szamolja ki az allast
                    PathLengthBase staticAnalysis = this.pathLengthFactory.CreatePathLength(board1);
                    int            situationScore = staticAnalysis.SituationScore();
                    MinimaxResult  moveScore      = new MinimaxResult(situationScore);

                    if (depth <= 1 || MoveScoreConverter.IsWin(situationScore))
                    {
                        moveScore = new MinimaxResult(situationScore);
                    }
                    else
                    {
                        if (depth > 1)
                        {
                            // rekurzio
                            moveScore = MiniMaxAlg(depth--, !isComputer, board1);
                            moveScore.MoveWins();
                        }
                    }

                    moveScore.Move = move;
                    // Itt nezem meg, hogy a minimum kell nekunk, vagy a maximum
                    if (bestResult == null || MoveScoreConverter.MinOrMax(moveScore.Score, bestResult.Score, isComputer))
                    {
                        bestResult = new MinimaxResult(move, moveScore);
                    }

                    alpha = CheckAlpha(moveScore.Score, isComputer);
                    if (IsAlphaBetaCutoff(isComputer))
                    {
                        cutOffMove       = move;
                        bestResult.Score = alpha;
                        break;
                    }
                }
                else
                {
                    break;
                }
            }
            if (bestResult != null)
            {
                GoodMoves.AddGoodMove(depth, bestResult.Move);
            }

            if (cutOffMove != Location.Null)
            {
                GoodMoves.AddGoodMove(depth, cutOffMove);
            }

            return(bestResult);
        }
Beispiel #26
0
 public void NoWinner()
 {
     Assert.AreEqual(Occupied.Empty, MoveScoreConverter.Winner(0));
 }
Beispiel #27
0
        public void WinnerYIsWinner()
        {
            int score = MoveScoreConverter.ConvertWin(Occupied.PlayerY, 1);

            Assert.AreEqual(Occupied.PlayerY, MoveScoreConverter.Winner(score));
        }