예제 #1
0
        public void EqualScoresAreNotBetterForEitherPlayer()
        {
            const int Score = 0;

            Assert.IsFalse(MoveScoreConverter.IsBetterFor(Score, Score, true));
            Assert.IsFalse(MoveScoreConverter.IsBetterFor(Score, Score, false));
        }
예제 #2
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));
        }
예제 #3
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));
        }
예제 #4
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);
        }