Exemplo n.º 1
0
    public int EvaluateTerminalBoard(FastBoardNode node, int plyFromRoot)
    {
        diagnostics.terminalBoardEvaluations++;
        bool whiteIsChecking = node.currentMove != Team.White && node.IsChecking(Team.White);

        if (whiteIsChecking)
        {
            return(CheckmateValue - plyFromRoot);
        }

        bool blackIsChecking = node.currentMove != Team.Black && node.IsChecking(Team.Black);

        if (blackIsChecking)
        {
            return(-CheckmateValue + plyFromRoot);
        }

        // Either stalemate, or 50 move rule draw
        return(DrawValue);
    }
Exemplo n.º 2
0
    int Search(FastBoardNode node, int searchDepth, int plyFromRoot, int alpha, int beta, int color)
    {
        if (searchDepth == 0)
        {
            using (diagnostics.quiescence.Measure())
                return(QuiescenceSearch(node, plyFromRoot, alpha, beta, color));
        }

        List <FastMove> moves;

        using (diagnostics.moveGen.Measure())
        {
            moves = moveCache[searchDepth];
            moves.Clear();
            node.AddAllPossibleMoves(moves, node.currentMove);
        }

        evaluationData.Prepare(node);

        using (diagnostics.moveSort.Measure())
        {
            OrderMoves(node, moves, plyFromRoot);
        }

        bool isTerminal = true;
        int  value      = int.MinValue;

        foreach (var move in moves)
        {
            if (cancellationRequested)
            {
                return(0);
            }

            using (diagnostics.apply.Measure())
                node.DoMove(move);

            bool isKingVulnerable;
            using (diagnostics.moveValidate.Measure())
                isKingVulnerable = node.IsChecking(node.currentMove);

            if (isKingVulnerable)
            {
                diagnostics.invalidMoves++;
                using (diagnostics.apply.Measure())
                    node.UndoMove(move);
                continue;
            }

            isTerminal = false;
            int currentValue = -Search(node, searchDepth - 1, plyFromRoot + 1, -beta, -alpha, -color);

            if (previousOrderingEnabled && plyFromRoot == 0)
            {
                previousScores[move] = currentValue;
            }

            using (diagnostics.apply.Measure())
                node.UndoMove(move);

            if (currentValue > value)
            {
                if (plyFromRoot == 0)
                {
                    bestMoveThisIteration = move;
                }
                value = currentValue;
            }
            alpha = Math.Max(alpha, value);
            if (alpha >= beta)
            {
                diagnostics.searchCutoff++;
                break;
            }
        }

        if (isTerminal)
        {
            value = color * EvaluateTerminalBoard(node, plyFromRoot);
        }

        return(value);
    }
Exemplo n.º 3
0
    public int EvaluateBoard(FastBoardNode node, int plyFromRoot)
    {
        if (node.plySincePawnMovedOrPieceTaken >= 100)
        {
            return(0); // automatic draw due to 50 move rule.
        }
        int  boardValue      = 0;
        bool whiteIsChecking = node.currentMove != Team.White && node.IsChecking(Team.White);

        if (whiteIsChecking)
        {
            boardValue += CheckBonusValue;
        }

        bool blackIsChecking = node.currentMove != Team.Black && node.IsChecking(Team.Black);

        if (blackIsChecking)
        {
            boardValue -= CheckBonusValue;
        }

        if (!node.HasAnyValidMoves(node.currentMove))
        {
            if (whiteIsChecking)
            {
                return(CheckmateValue - plyFromRoot);
            }
            else if (blackIsChecking)
            {
                return(-CheckmateValue + plyFromRoot);
            }
            else
            {
                return(DrawValue);
            }
        }

        /*
         * for (byte i = 0; i < node.positions.Length; i++)
         * {
         *  var piece = node.positions[i];
         *  if (piece.team == Team.None)
         *      continue;
         *
         *  var valuedPosition = FastIndex.FromByte(i);
         *  if (piece.team == Team.Black)
         *      valuedPosition = valuedPosition.Mirror();
         *
         *  int pieceValue = GetPieceValue(piece.piece);
         *
         *  if (pawnValueMapEnabled && piece.piece == FastPiece.Pawn)
         *  {
         *      pieceValue += pawnValueMap[valuedPosition.HexId];
         *  }
         *
         *  boardValue += TeamMults[(byte)piece.team] * pieceValue;
         * }
         */

        using (diagnostics.evalThreats.Measure())
        {
            boardValue += evaluationData.White.Threats.Count - evaluationData.Black.Threats.Count;
            boardValue += (evaluationData.White.PawnThreats.Count * 2) - (evaluationData.Black.PawnThreats.Count * 2);
            boardValue += evaluationData.White.MaterialValue - evaluationData.Black.MaterialValue;

            var whiteAttacks = evaluationData.Black.Pieces & evaluationData.White.Threats;
            var blackAttacks = evaluationData.White.Pieces & evaluationData.Black.Threats;
            boardValue += whiteAttacks.Count - blackAttacks.Count;

            var whiteDefended = evaluationData.White.Pieces & evaluationData.White.Threats;
            var blackDefended = evaluationData.Black.Pieces & evaluationData.Black.Threats;
            boardValue += whiteDefended.Count - blackDefended.Count;

            var whiteHangingPieces = blackAttacks & ~evaluationData.White.Threats;
            var blackHangingPieces = whiteAttacks & ~evaluationData.Black.Threats;
            boardValue += (blackHangingPieces.Count - whiteHangingPieces.Count) * 100;
        }

        return(boardValue);
    }
Exemplo n.º 4
0
    int QuiescenceSearch(FastBoardNode node, int plyFromRoot, int alpha, int beta, int color)
    {
        int eval;

        evaluationData.Prepare(node);

        using (diagnostics.quiescenceEval.Measure())
            eval = color * EvaluateBoard(node, plyFromRoot);

        if (!quiescenceSearchEnabled)
        {
            return(eval);
        }

        if (eval >= beta)
        {
            diagnostics.quiescenceCutoff++;
            return(beta);
        }

        if (eval > alpha)
        {
            alpha = eval;
        }

        List <FastMove> moves;

        using (diagnostics.quiescenceMoveGen.Measure())
        {
            moves = new List <FastMove>(10);
            node.AddAllPossibleMoves(moves, node.currentMove, generateQuiet: false);
        }

        using (diagnostics.quiescenceMoveSort.Measure())
            OrderMoves(node, moves, -1);

        bool maybeTerminal = true;
        int  value         = int.MinValue;

        foreach (var move in moves)
        {
            if (cancellationRequested)
            {
                return(0);
            }

            using (diagnostics.quiescenceApply.Measure())
                node.DoMove(move);

            bool isKingVulnerable;
            using (diagnostics.quiescenceMoveValidate.Measure())
                isKingVulnerable = node.IsChecking(node.currentMove);
            if (isKingVulnerable)
            {
                diagnostics.invalidMoves++;
                using (diagnostics.quiescenceApply.Measure())
                    node.UndoMove(move);
                continue;
            }

            maybeTerminal = false;
            int currentValue = -QuiescenceSearch(node, plyFromRoot + 1, -beta, -alpha, -color);

            using (diagnostics.quiescenceApply.Measure())
                node.UndoMove(move);

            if (currentValue > value)
            {
                value = currentValue;
            }
            alpha = Math.Max(alpha, value);
            if (alpha >= beta)
            {
                diagnostics.quiescenceCutoff++;
                break;
            }
        }

        // No non-quiet moves were found from this position
        if (maybeTerminal)
        {
            return(eval);
        }

        return(value);
    }