public static MovementState CreateMovementState(MovementTypes type, Vector3 hoz, Vector3 left)
    {
        MovementState toCreate = null;

        switch (type)
        {
        case MovementTypes.AI:
            throw new NotImplementedException();
            break;

        case MovementTypes.Null:
            toCreate = new NullMove();
            break;

        case MovementTypes.OneAxis:
            toCreate = new HorizontalAxisMove(DEFAULT_SPEED, hoz);
            break;

        case MovementTypes.TwoAxis:
            toCreate = new TwoAxisMove(DEFAULT_SPEED, hoz, left);
            break;

        default:
            //Only reached if a new type is added, but there is also no corresponding case
            throw new NotImplementedException();
        }
        return(toCreate);
    }
Пример #2
0
        public void NullMoveTest()
        {
            IPosition current  = new Position(new Coordinate(1, 1), Business.Enums.Direction.North);
            IPosition expected = new Position(new Coordinate(1, 1), Business.Enums.Direction.North);

            IMove     nullMove = new NullMove();
            IPosition output   = nullMove.Move(current);

            Assert.AreEqual(expected.Coordinate.X, output.Coordinate.X);
            Assert.AreEqual(expected.Coordinate.Y, output.Coordinate.Y);
            Assert.AreEqual(expected.Direction, output.Direction);
        }
Пример #3
0
        /// <summary>
        /// AlphaBeta algorithm.Calculates best line in given depth
        /// </summary>
        /// <param name="alpha">Lowest value</param>
        /// <param name="beta">highest value</param>
        /// <param name="ply"></param>
        /// <param name="depth"></param>
        /// <param name="pv">Holds principal variation</param>
        /// <param name="nullmove"></param>
        /// <param name="nodeCount">Holds value of calculated moves</param>
        /// <returns>Returning value is the score of best line</returns>
        int AlphaBeta(int alpha, int beta, int ply, int depth, List <Move> pv, NullMove nullmove, ref int nodeCount)
        {
            //if time out or exit requested after 1st iteration,so leave thinking.
            if ((!HaveTime() || Exit) && iterationPly > 1)
            {
                return(0);
            }
            nodeCount++;

            var moves = Board.GenerateMoves();

            if (!moves.Any())
            {
                return(-Board.GetCheckMateOrStaleMateScore(ply));
            }
            if (ply <= 0)
            {
                return(QuiescenceSearch(alpha, beta, ref nodeCount));
            }
            var localpv  = new List <Move>();
            var pvSearch = false;

            #region Null Move Prunning
            if (nullmove == NullMove.Enabled && !Board.IsInCheck())
            {
                int R = 2;
                Board.ToggleSide();
                int score = -AlphaBeta(-beta, -beta + 1, ply - 1 - R, depth + 1, localpv, NullMove.Disabled, ref nodeCount);
                Board.ToggleSide();
                if (score >= beta)
                {
                    return(score);
                }
            }
            #endregion
            var sortedMoves = SortMoves(moves, depth);
            foreach (var move in sortedMoves)
            {
                Board.MakeMove(move);
                int score;
                if (Board.threeFoldRepetetion.IsThreeFoldRepetetion)
                {
                    score = Board.Draw;
                }
                else
                {
                    #region Late Move Reduction

                    if (!Board.IsInCheck())
                    {
                        score = -AlphaBeta(-alpha - 1, -alpha, ply - 2, depth + 1, localpv, NullMove.Enabled, ref nodeCount);
                    }
                    else
                    {
                        score = alpha + 1;
                    }
                    #endregion
                    if (score > alpha)
                    {
                        if (pvSearch)
                        {
                            score = -AlphaBeta(-alpha - 1, -alpha, ply - 1, depth + 1, localpv, NullMove.Enabled, ref nodeCount);

                            if (score > alpha && score < beta)
                            {
                                score = -AlphaBeta(-beta, -alpha, ply - 1, depth + 1, localpv, NullMove.Enabled, ref nodeCount);
                            }
                        }
                        else
                        {
                            score = -AlphaBeta(-beta, -alpha, ply - 1, depth + 1, localpv, NullMove.Enabled, ref nodeCount);
                        }
                    }
                }



                Board.TakeBackMove(move);

                if (score >= beta)
                {
                    killerMoves.Add(move, depth);

                    return(beta);//beta cut-off
                }
                if (score > alpha)
                {
                    historyMoves.AddMove(move);
                    pvSearch = true;
                    alpha    = score;

                    pv.Clear();
                    pv.Add(move);
                    pv.AddRange(localpv);
                }
            }
            return(alpha);
        }
Пример #4
0
        /// <summary>
        /// AlphaBeta algorithm.Calculates best line in given depth
        /// </summary>
        /// <param name="alpha">Lowest value</param>
        /// <param name="beta">highest value</param>
        /// <param name="ply"></param>
        /// <param name="depth"></param>
        /// <param name="pv">Holds principal variation</param>
        /// <param name="nullmove"></param>
        /// <param name="nodeCount">Holds value of calculated moves</param>
        /// <returns>Returning value is the score of best line</returns>
        int AlphaBeta(int alpha, int beta, int ply, int depth, List<Move> pv, NullMove nullmove, ref int nodeCount)
        {
            //if time out or exit requested after 1st iteration,so leave thinking.
            if ((!HaveTime() || Exit) && iterationPly > 1) return 0;
            nodeCount++;

            var moves = Board.GenerateMoves();
            if (moves.Count == 0) return -Board.IsCheckMateOrStaleMate(ply);
            if (ply <= 0) return QuiescenceSearch(alpha, beta, ref nodeCount);
            var localpv = new List<Move>();
            var pvSearch = false;
            #region Null Move Prunning
            if (nullmove == NullMove.Enabled && !Board.IsInCheck())
            {
                int R = 2;
                Board.ToggleSide();
                int score = -AlphaBeta(-beta, -beta + 1, ply - 1 - R, depth + 1, localpv, NullMove.Disabled, ref nodeCount);
                Board.ToggleSide();
                if (score >= beta) return score;
            }
            #endregion
            var sortedMoves = SortMoves(moves, depth);
            foreach (var move in sortedMoves)
            {
                Board.MakeMove(move);
                int score;
                if (Board.threeFoldRepetetion.IsThreeFoldRepetetion) score = Board.Draw;
                else
                {
                    #region Late Move Reduction

                    if (!Board.IsInCheck())
                    {
                        score = -AlphaBeta(-alpha - 1, -alpha, ply - 2, depth + 1, localpv, NullMove.Enabled, ref nodeCount);
                    }
                    else score = alpha + 1;
                    #endregion
                    if (score > alpha)
                    {
                        if (pvSearch)
                        {
                            score = -AlphaBeta(-alpha - 1, -alpha, ply - 1, depth + 1, localpv, NullMove.Enabled, ref nodeCount);

                            if (score > alpha && score < beta)
                            {
                                score = -AlphaBeta(-beta, -alpha, ply - 1, depth + 1, localpv, NullMove.Enabled, ref nodeCount);
                            }
                        }
                        else
                        {
                            score = -AlphaBeta(-beta, -alpha, ply - 1, depth + 1, localpv, NullMove.Enabled, ref nodeCount);
                        }

                    }
                }

                Board.TakeBackMove(move);

                if (score >= beta)
                {
                    killerMoves.Add(move, depth);

                    return beta;//beta cut-off
                }
                if (score > alpha)
                {
                    historyMoves.AddMove(move);
                    pvSearch = true;
                    alpha = score;
                    #region Collect principal variation
                    pv.Clear();
                    pv.Add(move);
                    pv.AddRange(localpv);
                    #endregion
                }
            }
            return alpha;
        }
Пример #5
0
        /// <summary>
        /// Recursively carries out a full width alpha beta search untill the bottom is reached.
        /// From then a Quiescent search is carried out to avoid horrison effects.
        /// </summary>
        /// <param name="alpha">This is the best score that can be forced by some means. Anything worth less than this is of no use, because there is a strategy that is known to result in a score of alpha.</param>
        /// <param name="beta">Beta is the worst thing that the opponent has to endure. If the search finds something that returns a score of beta or better, it's too good, so the side to move is not going to get a chance to use this strategy.</param>
        /// <param name="remainingDepth">Remaining depth to search before bottom is reached.</param>
        /// <param name="allowNullMove">Is a null move allowed at this search depth.</param>
        /// <param name="allowTranspotitionTable">Is it allowed to use the transpotition table to probe for scores.</param>
        /// <returns>The score of a board.</returns>
        private int AlphaBetaSearch(int alpha, int beta, int remainingDepth, bool allowNullMove, bool allowTranspotitionTable)
        {
            if (m_searchRollback)
            {
                return(beta);
            }

            //At interval check if time is up and rollback if so.
            if (m_nodesVisited == m_nextRollbackCheck)
            {
                if (AbortingSearch())
                {
                    m_alphaBetaTable.Close();
                    m_quiescentTable.Close();
                    m_searchRollback = true;
                    return(beta);
                }

                m_nextRollbackCheck += ROLLBACK_INTERVAL_COUNT;
            }
            ++m_nodesVisited;

            int           score         = 0;
            Move          pvMove        = null;
            AlphaBetaFlag alphaBetaFlag = AlphaBetaFlag.AlphaScore;

            if (m_board.State.NonHitAndPawnMovesPlayed >= 100)
            {
                return(0);
            }

            if (m_board.BoardHistoryFrequency() >= 3)
            {
                return(0);
            }

            //don't allow transposition table before both players has passed the above repetetion draw checks.
            if (allowTranspotitionTable && (m_searchDepth - remainingDepth) > 0)
            {
                if (m_alphaBetaTable.ProbeScore(m_board.BoardHash(false), alpha, beta, remainingDepth, ref score))
                {
                    if (Math.Abs(score) != Math.Abs(m_evaluator.MateValue)) //don't probe a mate value as this actuall might be a mate far down in the tree, and we want to find the mate at lowest depth.
                    {
                        return(score);
                    }
                }
            }

            if (remainingDepth == 0)
            {
                score = QuiescentSearch(alpha, beta);

                if (allowTranspotitionTable)
                {
                    m_alphaBetaTable.RecordHash(m_board.BoardHash(false), AlphaBetaFlag.ExactScore, remainingDepth, score, pvMove);
                }

                return(score);
            }

            if (allowNullMove)
            {
                //Carry out a null move which is a move where nothing is actually moved. This makes the opponent move
                //twice in a row. The idea is then to search to a reduced depth and if nothing good come out of this
                //(for the opponent) the move is considered garbage and we cut it off.
                NullMove nullMove = new NullMove(m_board, m_evaluator);
                if (nullMove.Execute())
                {
                    int remDepth = (remainingDepth > NULL_REDUCTION) ? remainingDepth - 1 - NULL_REDUCTION : 0;
                    score = -AlphaBetaSearch(-beta, -beta + 1, remDepth, false, false);
                    nullMove.UnExecute();

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

            MoveOrganizer currentMoves = new MoveOrganizer(m_alphaBetaTable.ProbePvMove(m_board.BoardHash(false)));

            m_board.GeneratePseudoLegalMoves(currentMoves);
            currentMoves.Sort(m_captureMoveCompare);

            bool validMoveFound = false;

            foreach (Move move in currentMoves)
            {
                if (move.Execute(m_board))
                {
                    validMoveFound = true;

                    if (pvMove == null)
                    {
                        score = -AlphaBetaSearch(-beta, -alpha, remainingDepth - 1, true, allowTranspotitionTable);
                    }
                    else
                    {
                        score = -AlphaBetaSearch(-alpha - 1, -alpha, remainingDepth - 1, true, false);
                        if ((score > alpha) && (score < beta))
                        {
                            score = -AlphaBetaSearch(-beta, -alpha, remainingDepth - 1, true, allowTranspotitionTable);
                        }
                    }
                    move.UnExecute(m_board);

                    if (score >= beta)
                    {
                        if (allowTranspotitionTable)
                        {
                            m_alphaBetaTable.RecordHash(m_board.BoardHash(false), AlphaBetaFlag.BetaScore, remainingDepth, beta, pvMove);
                        }

                        return(beta);
                    }

                    if (score > alpha)
                    {
                        alpha         = score;
                        pvMove        = move;
                        alphaBetaFlag = AlphaBetaFlag.ExactScore;
                    }
                }
            }

            if (!validMoveFound)
            {
                if (m_board.ColorToPlayIsCheck())
                {
                    alpha = m_evaluator.MateValue; //Checkmate
                }
                else
                {
                    alpha = 0; //Stalemate
                }
            }

            if (allowTranspotitionTable)
            {
                m_alphaBetaTable.RecordHash(m_board.BoardHash(false), alphaBetaFlag, remainingDepth, alpha, pvMove);
            }

            return(alpha);
        }