All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fluxchess.pulse.Evaluation Maven / Gradle / Ivy

/*
 * Copyright (C) 2013-2019 Phokham Nonava
 *
 * Use of this source code is governed by the MIT license that can be
 * found in the LICENSE file.
 */
package com.fluxchess.pulse;

import static com.fluxchess.pulse.Bitboard.*;
import static com.fluxchess.pulse.Color.opposite;
import static com.fluxchess.pulse.Piece.NOPIECE;
import static com.fluxchess.pulse.PieceType.*;
import static com.fluxchess.pulse.Square.*;

final class Evaluation {

	static final int TEMPO = 1;

	private static final int MATERIAL_WEIGHT = 100;
	private static final int MOBILITY_WEIGHT = 80;
	private static final int MAX_WEIGHT = 100;

	/**
	 * Evaluates the position.
	 *
	 * @param position the position.
	 * @return the evaluation value in centipawns.
	 */
	int evaluate(Position position) {
		// Initialize
		int myColor = position.activeColor;
		int oppositeColor = opposite(myColor);
		int value = 0;

		// Evaluate material
		int materialScore = (evaluateMaterial(myColor, position) - evaluateMaterial(oppositeColor, position))
				* MATERIAL_WEIGHT / MAX_WEIGHT;
		value += materialScore;

		// Evaluate mobility
		int mobilityScore = (evaluateMobility(myColor, position) - evaluateMobility(oppositeColor, position))
				* MOBILITY_WEIGHT / MAX_WEIGHT;
		value += mobilityScore;

		// Add Tempo
		value += TEMPO;

		return value;
	}

	private int evaluateMaterial(int color, Position position) {
		int material = position.material[color];

		// Add bonus for bishop pair
		if (size(position.pieces[color][BISHOP]) >= 2) {
			material += 50;
		}

		return material;
	}

	private int evaluateMobility(int color, Position position) {
		int knightMobility = 0;
		for (long squares = position.pieces[color][KNIGHT]; squares != 0; squares = remainder(squares)) {
			int square = next(squares);
			knightMobility += evaluateMobility(position, square, knightDirections);
		}

		int bishopMobility = 0;
		for (long squares = position.pieces[color][BISHOP]; squares != 0; squares = remainder(squares)) {
			int square = next(squares);
			bishopMobility += evaluateMobility(position, square, bishopDirections);
		}

		int rookMobility = 0;
		for (long squares = position.pieces[color][ROOK]; squares != 0; squares = remainder(squares)) {
			int square = next(squares);
			rookMobility += evaluateMobility(position, square, rookDirections);
		}

		int queenMobility = 0;
		for (long squares = position.pieces[color][QUEEN]; squares != 0; squares = remainder(squares)) {
			int square = next(squares);
			queenMobility += evaluateMobility(position, square, queenDirections);
		}

		return knightMobility * 4
				+ bishopMobility * 5
				+ rookMobility * 2
				+ queenMobility;
	}

	private int evaluateMobility(Position position, int square, int[] directions) {
		int mobility = 0;
		boolean sliding = isSliding(Piece.getType(position.board[square]));

		for (int direction : directions) {
			int targetSquare = square + direction;

			while (Square.isValid(targetSquare)) {
				mobility++;

				if (sliding && position.board[targetSquare] == NOPIECE) {
					targetSquare += direction;
				} else {
					break;
				}
			}
		}

		return mobility;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy