Need some ideas on how to implement an evaluation function

I am working on a chessgame and now trying to implement a minimax algorithm which calculates a score using a piece square table and Piece value. I have been able to create to following methods show below, but don't know how to go about calculating the piece score within the CalculateScore() and evaluatePieceScore() methods. Please, I am really confused and need assistances.

1) getPieceValue() this method returns a constant values assigned to each chess piece 2) getScoreForPiecePosition() gets the evaluation bonus for the specified position 3) CalculateScore() calculates and returns a score using the piece square table. 4) evaluatePieceScore() adds the calculated score from the CalculateScore() to the original score depending on whos's turn.

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;
}

}

Upvotes: 0

Views: 754

Answers (2)

philippe lhardy
philippe lhardy

Reputation: 3286

Your missing part is a function taking type, row and column as arguments :

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);
     } }

and use that method in overall computation.

[ not tested ]

It might not be enough for tables that are not symetrical like Pawn, then you need to give BROWN or WHITE argument and call function with ( 7 - row ) instead of row for BROWN by example.

( googling = http://chessprogramming.wikispaces.com/Simplified+evaluation+function )

Upvotes: 1

Romain
Romain

Reputation: 1445

If you feel confused, I would recommend starting with an simple evaluation function taking into account only the value of the pieces (1 point for a pawn, 3 points for a bishop and a knight, 5 points for a rook, 9 points for a queen and a lot of points for a king, let's say 200)

and then your function becomes:

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

The function getMaterial() will be the sum of all your pieces points.

Example: black has 1 pawn, 1 queen and a king, then blackPlayer.getMaterial() will return = 1 + 9 + 200 = 210

After if you want to take into account the position of the piece into the evalution function, you can do something like that:

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

The function getBonusPosition() will return the sum of all the bonus position score of all your pieces:

Example: blackPlayer has 1 pawn at position (0,0), 1 queen at position (0,1) and a king at position (2,2):

  • the bonus position of the pawn at (0,0) is 0
  • the bonus position of the queen at (0,1) is -10
  • the bonus position of the king (in the endgame) at (2,2) is -20

blackPlayer.getBonusPosition() will return = 0 - 10 -20 = -30

You can change your coefficients to give more importance to material value or to the position on the board. For instance, in the previous examples the position score was way much too important compared to the material score.

Example: You want give more importance (let's say 10 times more) to the material value and you don't really care about the position of the pieces on the board, then you new calculate score function will be:

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

Upvotes: 1

Related Questions