【问题标题】:Need some ideas on how to implement an evaluation function需要一些关于如何实现评估功能的想法
【发布时间】:2014-07-13 07:06:15
【问题描述】:

我正在开发一个国际象棋游戏,现在尝试实现一个极小极大算法,该算法使用一个棋子方表和棋子值来计算分数。我已经能够创建以下显示的方法,但不知道如何在 CalculateScore()evaluatePieceScore() 方法中计算计件分数。拜托,我真的很困惑,需要帮助。

1) getPieceValue() 该方法返回分配给每个棋子的常量值 2) getScoreForPiecePosition() 获取指定位置的评价奖励 3) CalculateScore() 使用棋盘表计算并返回分数。 4) evaluatePieceScore() 根据轮到谁,将CalculateScore() 计算出的分数加到原始分数上。

public class MinimaxPlayer implements IPlayerHandler, EvaluationAlgorithm{

private Game chessgame;
private MoveChecker checker;
private BoardGUI boardgui;

private static int maxDepth = 2;

public MinimaxPlayer(Game chessgame){
    this.chessgame = chessgame;
    this.checker = chessgame.getMoveChecker();
    this.boardgui = new BoardGUI(chessgame);
}

@Override
public int getPieceValue(int type) {
    switch(type){
    case Piece.TYPE_PAWN: return 100;
    case Piece.TYPE_KNIGHT: return 320;
    case Piece.TYPE_BISHOP: return 325;
    case Piece.TYPE_ROOK: return 500;
    case Piece.TYPE_QUEEN: return 975;
    case Piece.TYPE_KING: return 32767;
    default: throw new IllegalArgumentException("Unknown piece type: "+ type);
    }
}



@Override
public int evaluatePieceScore() {
    int scoreBrown = 0;
    int scoreYellow = 0;
    for (Piece piece : this.chessgame.getPieces()) {
        if(piece.getColor() == Piece.BROWN_COLOR){
            scoreBrown +=
                getScoreForPieceType(piece.getType());
            scoreBrown +=
                getScoreForPiecePosition(piece.getRow(),piece.getColumn());
        }else if( piece.getColor() == Piece.YELLOW_COLOR){
            scoreYellow +=
                getScoreForPieceType(piece.getType());
            scoreYellow +=
                getScoreForPiecePosition(piece.getRow(),piece.getColumn());
        }else{
            throw new IllegalStateException(
                    "unknown piece color found: "+piece.getColor());
        }
    }

    // return evaluation result depending on who's turn it is
    int gameState = this.chessgame.getGameState();

    if( gameState == Game.GAME_STATE_BROWN){
        return scoreBrwon - scoreYellow;

    }else if(gameState == Game.GAME_STATE_YELLOW){
        return scoreYellow - scoreBrown;

    }else if(gameState == Game.GAME_STATE_END_YELLOW_WON
            || gameState == Game.GAME_STATE_END_BROWN_WON){
        return Integer.MIN_VALUE + 1;

    }else{
        throw new IllegalStateException("unknown game state: "+gameState);
    }
}

public int CalculateScore(int index, int pieceValue, int[] SquareTable ){
    int score = pieceValue;

    for(int i = 0; i < SquareTable.length; i++){
        score += getPieceValue(index.get(SquareTable[i]));

    }

    return 0;
}

@Override
public int getScoreForPiecePosition(int row, int column) {
    byte[][] positionWeight =
    { {1,1,1,1,1,1,1,1}
     ,{2,2,2,2,2,2,2,2}
     ,{2,2,3,3,3,3,2,2}
     ,{2,2,3,4,4,3,2,2}
     ,{2,2,3,4,4,3,2,2}
     ,{2,2,3,3,3,3,2,2}
     ,{2,2,2,2,2,2,2,2}
     ,{1,1,1,1,1,1,1,1}
     };
    return positionWeight[row][column];
}



private static int[] PawnSquareTable = new int[]
{
    0,  0,  0,  0,  0,  0,  0,  0,
    50, 50, 50, 50, 50, 50, 50, 50,
    10, 10, 20, 30, 30, 20, 10, 10,
     5,  5, 10, 25, 25, 10,  5,  5,
     0,  0,  0, 20, 20,  0,  0,  0,
     5, -5,-10,  0,  0,-10, -5,  5,
     5, 10, 10,-20,-20, 10, 10,  5,
     0,  0,  0,  0,  0,  0,  0,  0
};


private static int[] KnightSquareTable = new int[]
{
    -50,-40,-30,-30,-30,-30,-40,-50,
    -40,-20,  0,  0,  0,  0,-20,-40,
    -30,  0, 10, 15, 15, 10,  0,-30,
    -30,  5, 15, 20, 20, 15,  5,-30,
    -30,  0, 15, 20, 20, 15,  0,-30,
    -30,  5, 10, 15, 15, 10,  5,-30,
    -40,-20,  0,  5,  5,  0,-20,-40,
    -50,-40,-30,-30,-30,-30,-40,-50,
};


private static int[] BishopSquareTable = new int[]
{
    -20,-10,-10,-10,-10,-10,-10,-20,
    -10,  0,  0,  0,  0,  0,  0,-10,
    -10,  0,  5, 10, 10,  5,  0,-10,
    -10,  5,  5, 10, 10,  5,  5,-10,
    -10,  0, 10, 10, 10, 10,  0,-10,
    -10, 10, 10, 10, 10, 10, 10,-10,
    -10,  5,  0,  0,  0,  0,  5,-10,
    -20,-10,-10,-10,-10,-10,-10,-20,
};

    private static int[] RookSquareTable = new int[]
{
    0,  0,  0,  0,  0,  0,  0,  0,
    5, 10, 10, 10, 10, 10, 10,  5,
   -5,  0,  0,  0,  0,  0,  0, -5,
   -5,  0,  0,  0,  0,  0,  0, -5,
   -5,  0,  0,  0,  0,  0,  0, -5,
   -5,  0,  0,  0,  0,  0,  0, -5,
   -5,  0,  0,  0,  0,  0,  0, -5,
    0,  0,  0,  5,  5,  0,  0,  0,
};

    private static int[] QueenSquareTable = new int[]
{
    -20,-10,-10, -5, -5,-10,-10,-20,
    -10,  0,  0,  0,  0,  0,  0,-10,
    -10,  0,  5,  5,  5,  5,  0,-10,
     -5,  0,  5,  5,  5,  5,  0, -5,
      0,  0,  5,  5,  5,  5,  0, -5,
    -10,  5,  5,  5,  5,  5,  0,-10,
    -10,  0,  5,  0,  0,  0,  0,-10,
    -20,-10,-10, -5, -5,-10,-10,-20,
};


private static int[] KingMiddleGameSquareTable = new int[]
{
    -30,-40,-40,-50,-50,-40,-40,-30,
    -30,-40,-40,-50,-50,-40,-40,-30,
    -30,-40,-40,-50,-50,-40,-40,-30,
    -30,-40,-40,-50,-50,-40,-40,-30,
    -20,-30,-30,-40,-40,-30,-30,-20,
    -10,-20,-20,-20,-20,-20,-20,-10,
     20, 20,  0,  0,  0,  0, 20, 20,
     20, 30, 10,  0,  0, 10, 30, 20,
};


private static int[] KingEndGameSquareTable = new int[]
{
    -50,-40,-30,-20,-20,-30,-40,-50,
    -30,-20,-10,  0,  0,-10,-20,-30,
    -30,-10, 20, 30, 30, 20,-10,-30,
    -30,-10, 30, 40, 40, 30,-10,-30,
    -30,-10, 30, 40, 40, 30,-10,-30,
    -30,-10, 20, 30, 30, 20,-10,-30,
    -30,-30,  0,  0,  0,  0,-30,-30,
    -50,-30,-30,-30,-30,-30,-30,-50,
};


public static int[] reverse(int[] arr){
    ArrayUtils.reverse(arr);
    return arr;
}

}

【问题讨论】:

  • 你能用文字逐行描述这些方法应该做什么吗?
  • @ChiefTwoPencils,我已经更新了问题。
  • 您对在计算中使用 PawnSquareTable、KnightSquareTable 等有疑问吗?
  • @philippelhardy,是的,这是我的问题。

标签: java artificial-intelligence chess


【解决方案1】:

如果您感到困惑,我建议您从一个简单的评估函数开始,仅考虑棋子的价值(棋子 1 分,主教和马 3 分,车 5 分,9 分女王和国王的很多积分,比如说200)

然后你的函数变成:

    public int calculateScore()
    {
        return blackPlayer.getMaterial() - whitePlayer.getMaterial()
    }

getMaterial() 函数将是您所有棋子点数的总和。

示例:黑方有 1 兵、1 后和 1 王,则 blackPlayer.getMaterial() 将返回 = 1 + 9 + 200 = 210

如果你想在评估函数中考虑到棋子的位置,你可以这样做:

    public int calculateScore()
    {
        int blackScore = blackPlayer.getMaterial() + blackPlayer.getBonusPosition();
        int whiteScore = whitePlayer.getMaterial() + whitePlayer.getBonusPosition();
        return blackScore - whiteScore; 
    }

getBonusPosition() 函数将返回您所有棋子的所有奖金位置得分的总和:

示例:blackPlayer 在 (0,0) 位置有 1 个棋子,在 (0,1) 位置有 1 个后,在 (2,2) 位置有一个国王:

  • 棋子在 (0,0) 的奖励位置是 0
  • 女王在 (0,1) 的奖金位置是 -10
  • 国王(在最后阶段)在 (2,2) 的奖励位置是 -20

blackPlayer.getBonusPosition() 将返回 = 0 - 10 -20 = -30

您可以更改系数,以更加重视材料价值或在棋盘上的位置。例如,在前面的示例中,位置分数与材料分数相比太重要了。

示例:您想更加重视(假设是 10 倍)材料价值,并且您并不真正关心棋子在棋盘上的位置,然后您重新计算分数函数将是:

    public int calculateScore()
    {
        int blackScore = 10*blackPlayer.getMaterial() + blackPlayer.getBonusPosition();
        int whiteScore = 10*whitePlayer.getMaterial() + whitePlayer.getBonusPosition();
        return blackScore - whiteScore; 
    }

【讨论】:

  • 我理解这一点,只是对如何使用方格表计算分数以在我的算法中控制移动性和中心控制感到困惑。
  • 现在我为每件作品准备了一块方桌,并希望在我的 calcultateScore() 中使用它,请问如何添加该位。
【解决方案2】:

您缺少的部分是一个以 typerowcolumn 作为参数的函数:

public int getScoreForPieceTypeAndPosition(int type, int row, int
 column) { public int getPieceValue(int type) {
     switch(type){
     case Piece.TYPE_PAWN: return PawnSquareTable[row * 8 + column ];
     case Piece.TYPE_KNIGHT: return KnightSquareTable[row * 8 + column ];
     case Piece.TYPE_BISHOP: return BishopSquareTable[row * 8 + column ];
     case Piece.TYPE_ROOK: return RookSquareTable[row * 8 + column ];
     case Piece.TYPE_QUEEN: return QueendSquareTable[row * 8 + column ]; 
     case Piece.TYPE_KING: return KingSquareTable[row *8 + column];
     default: throw new IllegalArgumentException("Unknown piece type: "+ type);
     } }

并在整体计算中使用该方法。

[未测试]

对于像 Pawn 这样非对称的表可能还不够,那么您需要提供 BROWN 或 WHITE 参数并使用 ( 7 - row ) 调用函数,而不是 BROWN 的 row 示例。

(谷歌搜索 = http://chessprogramming.wikispaces.com/Simplified+evaluation+function

【讨论】:

  • 感谢您的回答。
  • 我需要颠倒一块方桌的位置,因为我的代码中的那个是轮到棕色的
  • 编辑我的帖子,因为反转信息是错误的:行应该被反转调用函数(7-行)而不是行。
猜你喜欢
  • 2013-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
  • 2011-04-05
  • 1970-01-01
相关资源
最近更新 更多