Ejemplo n.º 1
0
    private int Evaluate(HexAIMove move, Game game)
    {
        int  score   = random.Next(0, 25); // avoid making every run the same
        var  state   = game.GetCurrentBoardState();
        Team ourTeam = state.currentMove;
        Team enemy   = ourTeam.Enemy();

        (BoardState newState, List <Promotion> newPromotions) = move.Speculate(game);

        bool weAreChecking = MoveValidator.IsChecking(ourTeam, newState, newPromotions);
        bool enemyHasMoves = MoveValidator.HasAnyValidMoves(enemy, newPromotions, newState, state);

        if (weAreChecking && !enemyHasMoves)
        {
            return(int.MaxValue);
        }

        if (weAreChecking)
        {
            score += CheckBonus;
        }

        if (!enemyHasMoves)
        {
            score -= StalematePenalty;
        }

        if (move.moveType == MoveType.Attack)
        {
            var attacker = HexachessagonEngine.GetRealPiece(move.start, state, game.promotions);
            var victim   = HexachessagonEngine.GetRealPiece(move.target, state, game.promotions);
            score += AttackBonus;
            score += GetPieceValue(victim) - GetPieceValue(attacker);
        }
        else if (move.moveType == MoveType.EnPassant)
        {
            score += EnPassantBonus;
        }
        else if (move.moveType == MoveType.Move)
        {
            var mover = state.allPiecePositions[move.start];
            if (mover.piece.IsPawn())
            {
                int ranksForward = move.target.GetNumber() - move.start.GetNumber();
                if (ourTeam == Team.Black)
                {
                    ranksForward = -ranksForward;
                }

                ranksForward *= 5;

                score *= ranksForward;
            }
        }
        else
        {
            // Defend is pretty worthless for a bloodthirsty AI
            score -= 10;
        }

        return(score);
    }
Ejemplo n.º 2
0
    /// <summary>
    /// Is a piece from <paramref name="checkForTeam"/> attacking the enemy king?
    /// </summary>
    /// <param name="checkForTeam"></param>
    /// <returns>true if the enemy king is threatened</returns>
    public static bool IsChecking(Team checkForTeam, BoardState state, List <Promotion> promotions)
    {
        Team enemy = checkForTeam.Enemy();

        if (!state.allPiecePositions.TryGetValue((enemy, Piece.King), out Index enemyKingLoc))
        {
            return(false);
        }

        foreach (var rayDirection in EnumArray <HexNeighborDirection> .Values)
        {
            Index?hex = enemyKingLoc;
            (Team team, Piece piece)occupier;
            bool isBishopDirection = rayDirection switch
            {
                HexNeighborDirection.Up => false,
                HexNeighborDirection.Down => false,
                _ => true
            };

            bool isRookDirection = !isBishopDirection;

            bool isPawnDirection = rayDirection switch
            {
                HexNeighborDirection.DownLeft => checkForTeam == Team.White,
                HexNeighborDirection.DownRight => checkForTeam == Team.White,
                HexNeighborDirection.UpLeft => checkForTeam != Team.White,
                HexNeighborDirection.UpRight => checkForTeam != Team.White,
                _ => false
            };

            for (int distance = 1; distance < 20; distance++)
            {
                hex = hex.Value.GetNeighborAt(rayDirection);
                if (!hex.HasValue)
                {
                    break;
                }

                if (state.allPiecePositions.TryGetValue(hex.Value, out occupier))
                {
                    if (occupier.team == checkForTeam)
                    {
                        Piece realPiece = HexachessagonEngine.GetRealPiece(occupier, promotions);

                        if (distance == 1)
                        {
                            if (isPawnDirection && realPiece.IsPawn())
                            {
                                return(true);
                            }

                            if (realPiece == Piece.King)
                            {
                                return(true);
                            }
                        }

                        if (isBishopDirection && (realPiece.IsBishop() || realPiece == Piece.Queen))
                        {
                            return(true);
                        }

                        if (isRookDirection && (realPiece.IsRook() || realPiece == Piece.Queen))
                        {
                            return(true);
                        }
                    }
                    break;
                }
            }
        }

        foreach ((Index target, MoveType moveType)move in MoveGenerator.GetAllPossibleMoves(enemyKingLoc, Piece.BlackSquire, enemy, state, promotions))
        {
            if (move.moveType == MoveType.Attack && state.TryGetPiece(move.target, out var occupier))
            {
                Piece realPiece = HexachessagonEngine.GetRealPiece(occupier, promotions);
                if (realPiece.IsSquire())
                {
                    return(true);
                }
            }
        }

        foreach ((Index target, MoveType moveType)move in MoveGenerator.GetAllPossibleMoves(enemyKingLoc, Piece.KingsKnight, enemy, state, promotions))
        {
            if (move.moveType == MoveType.Attack && state.TryGetPiece(move.target, out var occupier))
            {
                Piece realPiece = HexachessagonEngine.GetRealPiece(occupier, promotions);
                if (realPiece.IsKnight())
                {
                    return(true);
                }
            }
        }

        for (int i = 1; i < 20; ++i) // Queen/Rook slide left
        {
            Index hex = new Index(enemyKingLoc.row, enemyKingLoc.col - i);
            if (!hex.IsInBounds)
            {
                break;
            }

            if (state.TryGetPiece(hex, out (Team team, Piece piece)occupier))
            {
                if (occupier.team == checkForTeam)
                {
                    Piece realPiece = HexachessagonEngine.GetRealPiece(occupier, promotions);
                    if (realPiece.IsRook() || realPiece == Piece.Queen)
                    {
                        return(true);
                    }
                }
                break;
            }
        }

        for (int i = 1; i < 20; i++) // Queen/Rook slide right
        {
            Index hex = new Index(enemyKingLoc.row, enemyKingLoc.col + i);
            if (!hex.IsInBounds)
            {
                break;
            }

            if (state.TryGetPiece(hex, out (Team team, Piece piece)occupier))
            {
                if (occupier.team == checkForTeam)
                {
                    Piece realPiece = HexachessagonEngine.GetRealPiece(occupier, promotions);
                    if (realPiece.IsRook() || realPiece == Piece.Queen)
                    {
                        return(true);
                    }
                }
                break;
            }
        }

        return(false);
    }