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

com.fathzer.games.movelibrary.AbstractMoveLibrary Maven / Gradle / Ivy

The newest version!
package com.fathzer.games.movelibrary;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.function.Function;

import com.fathzer.games.ai.evaluation.EvaluatedMove;

/** An abstract move library based on searching records in a local or remote database
 * @param  The type of the database records. Those records contain the information about a move
 * @param  The type of moves
 * @param  The type of the keys that allow to retrieve the moves from the library (typically, the game board)
 */
public abstract class AbstractMoveLibrary implements MoveLibrary {
	@SuppressWarnings("java:S2245") //Ignores Sonar security hot spot, here Random is safe
	// Warning, due to limitations introduced in java 12+, making the field final would no more allow testing the class
	// as it would be no more possible to mock the random generator.
	private static Random rnd = new Random();

	/** A function that always select the first element of a list.
	 * @param  The list element type
	 * @return A function that always select the first element of the list
	 */
	public static  Function, T> firstMoveSelector() {
		return l -> l.get(0);
	}

	/** A function that randomly selects an element of a list.
	 * @param  The list element type
	 * @return A function that randomly selects an element of a list.
	 */
	public static  Function,T> randomMoveSelector() {
		return l -> l.get(rnd.nextInt(l.size()));
	}
	
	private Function, R> moveSelector = randomMoveSelector();
	private MoveLibrary other;
	
	/** A function that randomly selects an element of a list with a probability proportional to its relative weight.
	 * @return A function.
	 * @see #getWeight(Object)
	 */
	public Function, R> weightedMoveSelector() {
		return values -> {
			long count = values.stream().mapToLong(AbstractMoveLibrary.this::getWeight).sum();
			long value = rnd.nextLong(count);
			count = 0;
			int index = values.size()-1;
			for (int i=0;i getRecords(B board);

	/** Converts a database record that describes an evaluated move to a move instance.
	 * @param board The position
	 * @param moveRecord The move database record
	 * @return An evaluated move instance
	 */
	protected abstract EvaluatedMove toEvaluatedMove(B board, R moveRecord);
	
	/** Sets the move selector (the function that selects a move in the list of move records returned by {@link #getRecords(Object)}
	 * 
By default, the move is randomly chosen in the list. * @param moveSelector A move selector */ public void setMoveSelector(Function, R> moveSelector) { this.moveSelector = moveSelector; } /** Sets another library to search when no moves are available in this one. * @param next Another library or null to remove the current 'next' library. */ public void setNext(MoveLibrary next) { this.other = next; } @Override public List> getMoves(B board) { final List moves = getRecords(board); if (moves.isEmpty()) { return other==null ? Collections.emptyList() : other.getMoves(board); } return moves.stream().map(r -> toEvaluatedMove(board, r)).toList(); } /** {@inheritDoc} *
If this library can't find a move for this position, and a 'next' library was linked with this using {@link #setNext(MoveLibrary)}, * its apply method's result is returned. */ @Override public Optional> apply(B board) { final List moves = getRecords(board); if (moves.isEmpty()) { return other==null ? Optional.empty() : other.apply(board); } final R selectedRecord = moveSelector.apply(moves); return Optional.of(toEvaluatedMove(board, selectedRecord)); } /** Gets the weight of a move. * @param move A database record that represents the move. * @return a long, typically, the number of times best players played this move. *
The default implementation returns 1, making all the moves equiprobable. */ protected long getWeight(R move) { return 1; } @Override public void newGame() { if (other!=null) { other.newGame(); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy