Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .project
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,15 @@
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
<filteredResources>
<filter>
<id>1737039058705</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
# chesslib-uci-engine
A basic [UCI](https://en.wikipedia.org/wiki/Universal_Chess_Interface) engine based on the [bhlangonijr/chesslib](https://github.com/bhlangonijr/chesslib) move generator, and the [games-core](https://github.com/fathzer-games/games-core) alpha beta search algorithm implementation. It uses the evaluation functions, the remaining move oracle and some other things from the [chess-utils](https://github.com/fathzer-games/chess-utils) library.

You can play against it on [Lichess](https://lichess.org/@/fathzer-jchess). It runs on a Minisforum U300 with [3867U processor](https://www.cpubenchmark.net/cpu.php?cpu=Intel+Celeron+3867U+%40+1.80GHz&id=3442).
You can play against it on [Lichess](https://lichess.org/@/fathzer-jchess). It runs on a Nipogi e2 with N97 processor](https://www.passmark.com/baselines/V11/display.php?id=284967660181).

## How to run the engine
It requires a Java 17+ virtual machine.

Download the jar [here](https://fathzer-games.github.io/chesslib-uci-engine/chesslib-uci-engine.jar), then Launch the engine with the following command: ```java -jar chesslib-uci-engine.jar```
Download the jar [here](https://fathzer-games.github.io/chesslib-uci-engine/chesslib-uci-engine.jar), then launch the engine with the following command: ```java -jar chesslib-uci-engine.jar```

### Openings library
You can use an opening library located at a URL using the ```openingsUrl``` system property.
Expand Down
60 changes: 43 additions & 17 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
<parent>
<groupId>com.fathzer</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.8</version>
<version>1.0.9</version>
</parent>
<artifactId>chesslib-uci-engine</artifactId>
<version>0.0.3</version>
<version>0.0.4</version>

<name>chesslib-uci-engine</name>
<description>A basic uci engine plugin for jchess-uci.</description>
<description>A basic uci engine based on chesslib move generator.</description>
<url>https://github.com/fathzer-games/chesslib-uci-engine</url>

<scm>
Expand All @@ -27,6 +27,7 @@
<maven.compiler.release>17</maven.compiler.release>
<sonar.organization>fathzer-games</sonar.organization>
<customized.jar.name>chesslib-uci-engine</customized.jar.name>
<maven.build.timestamp.format>yyyyMMdd HH-mm-ss</maven.build.timestamp.format>
</properties>

<repositories>
Expand All @@ -40,60 +41,85 @@
<dependency>
<groupId>com.github.bhlangonijr</groupId>
<artifactId>chesslib</artifactId>
<version>1.3.3</version>
<version>1.3.4</version>
</dependency>
<dependency>
<groupId>com.fathzer</groupId>
<artifactId>chess-utils</artifactId>
<version>0.0.5-SNAPSHOT</version>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>com.fathzer</groupId>
<artifactId>games-core</artifactId>
<version>0.0.12-SNAPSHOT</version>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>com.fathzer</groupId>
<artifactId>jchess-uci</artifactId>
<version>2.0.4-SNAPSHOT</version>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20240205</version>
<version>20250107</version>
</dependency>
<dependency>
<groupId>com.fathzer</groupId>
<artifactId>jchess-perft-dataset</artifactId>
<version>1.0.0</version>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.7</version>
<version>2.0.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.7</version>
<version>2.0.16</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fathzer</groupId>
<artifactId>chess-test-utils</artifactId>
<version>0.0.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>generate-build-info</id>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<echo message="Generating build-info.properties"/>
<mkdir dir="${project.build.outputDirectory}"/>
<propertyfile file="${project.build.outputDirectory}/build-info.properties" comment="Build information">
<entry key="name" value="${project.groupId}:${project.artifactId}"/>
<entry key="version" value="${project.version}"/>
<entry key="build" value="${maven.build.timestamp}"/>
</propertyfile>
</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
Expand Down
3 changes: 2 additions & 1 deletion runConfigs/ChessLib-uci-engine (PerfTTest).launch
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<mapAttribute key="org.eclipse.debug.core.environmentVariables"/>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
Expand All @@ -19,5 +20,5 @@
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.fathzer.jchess.chesslib.PerfTTest"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="chesslib-uci-engine"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -DperftDepth=4"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/>
</launchConfiguration>
15 changes: 6 additions & 9 deletions src/main/java/com/fathzer/jchess/chesslib/ai/DefaultLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,15 @@ public void logEndedByPolicy(int depth) {

@Override
public void logSearchEnd(ChessLibMoveGenerator board, SearchHistory<Move> result) {
log.info("--- End of iterative evaluation returns: {}", result.getBestMoves());
}

@Override
public void logMoveChosen(ChessLibMoveGenerator board, EvaluatedMove<Move> evaluatedMove) {
if (evaluatedMove==null) {
log.info("--- End of iterative evaluation returns: {}", result.getAccurateMoves());
if (result.isEmpty()) {
log.info("No valid move found");
} else {
Move move = evaluatedMove.getContent();
//TODO Not the right place, the engine could return another move, especially when there is tie moves
EvaluatedMove<Move> evaluatedMove = result.getAccurateMoves().get(0);
Move move = evaluatedMove.getMove();
log.info("Move chosen :{}", move);
final List<Move> pv = evaluatedMove.getPrincipalVariation();
log.info("pv: {}", pv);
log.info("pv: {}", engine.getTranspositionTable().collectPV(board, move, result.getLastDepth()));
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/fathzer/jchess/chesslib/ai/TT.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

import com.fathzer.games.ai.transposition.OneLongEntryTranspositionTable;
import com.fathzer.games.ai.transposition.SizeUnit;
import com.fathzer.jchess.chesslib.ChessLibMoveGenerator;
import com.github.bhlangonijr.chesslib.Piece;
import com.github.bhlangonijr.chesslib.Square;
import com.github.bhlangonijr.chesslib.move.Move;

public class TT extends OneLongEntryTranspositionTable<Move> {
public class TT extends OneLongEntryTranspositionTable<Move, ChessLibMoveGenerator> {
// Move is encoded as an int:
// 12 bits for source, 12 bits for destination
// 8 bits for promotion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import com.fathzer.games.ai.time.BasicTimeManager;
import com.fathzer.games.ai.transposition.SizeUnit;
import com.fathzer.games.ai.transposition.TranspositionTable;
import com.fathzer.games.perft.TestableMoveGeneratorBuilder;
import com.fathzer.games.perft.FromPositionMoveGeneratorBuilder;
import com.fathzer.games.util.PhysicalCores;
import com.fathzer.games.util.exec.ExecutionContext;
import com.fathzer.jchess.chesslib.ChessLibMoveGenerator;
Expand All @@ -40,7 +40,7 @@
import com.github.bhlangonijr.chesslib.Square;
import com.github.bhlangonijr.chesslib.move.Move;

public class ChessLibEngine extends AbstractEngine<Move, ChessLibMoveGenerator> implements TestableMoveGeneratorBuilder<Move, ChessLibMoveGenerator>, Displayable {
public class ChessLibEngine extends AbstractEngine<Move, ChessLibMoveGenerator> implements FromPositionMoveGeneratorBuilder<Move, ChessLibMoveGenerator>, Displayable {
private static final List<EvaluatorConfiguration<Move, ChessLibMoveGenerator>> EVALUATORS = Arrays.asList(
new EvaluatorConfiguration<>("pesto",PestoEvaluator::new),
new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),
Expand All @@ -54,7 +54,7 @@ public ChessLibEngine() {
}

public ChessLibEngine(DeferredReadMoveLibrary<Move, ChessLibMoveGenerator> ownBook) {
super (buildEngine(EVALUATORS.get(0).getBuilder(), 20), new BasicTimeManager<>(RemainingMoveOracle.INSTANCE));
super (buildEngine(EVALUATORS.get(0).evaluatorBuilder(), 20), new BasicTimeManager<>(RemainingMoveOracle.INSTANCE));
setEvaluators(EVALUATORS);
this.ownBook = ownBook;
}
Expand Down Expand Up @@ -85,7 +85,7 @@ public void setOwnBook(boolean activate) {

@Override
public void setStartPosition(String fen) {
board = fromFEN(fen);
board = fromPosition(fen);
board.setMoveComparatorBuilder(BasicMoveComparator::new);
}

Expand Down Expand Up @@ -124,7 +124,7 @@ public String getFEN() {
}

@Override
public ChessLibMoveGenerator fromFEN(String fen) {
public ChessLibMoveGenerator fromPosition(String fen) {
final Board internalBoard = new Board();
internalBoard.loadFromFen(fen);
return new ChessLibMoveGenerator(internalBoard);
Expand All @@ -133,8 +133,8 @@ public ChessLibMoveGenerator fromFEN(String fen) {
public static IterativeDeepeningEngine<Move, ChessLibMoveGenerator> buildEngine(Supplier<Evaluator<Move, ChessLibMoveGenerator>> evaluatorBuilder, int maxDepth) {
final IterativeDeepeningEngine<Move, ChessLibMoveGenerator> engine = new IterativeDeepeningEngine<>(new ChessLibDeepeningPolicy(maxDepth), new TT(16, SizeUnit.MB), evaluatorBuilder) {
@Override
protected Negamax<Move, ChessLibMoveGenerator> buildAi(ExecutionContext<SearchContext<Move, ChessLibMoveGenerator>> context) {
final Negamax<Move, ChessLibMoveGenerator> negaMax = (Negamax<Move, ChessLibMoveGenerator>) super.buildAi(context);
protected Negamax<Move, ChessLibMoveGenerator> buildAI(ExecutionContext<SearchContext<Move, ChessLibMoveGenerator>> context) {
final Negamax<Move, ChessLibMoveGenerator> negaMax = (Negamax<Move, ChessLibMoveGenerator>) super.buildAI(context);
negaMax.setQuiesceEvaluator(new BasicQuiesceSearch());
return negaMax;
}
Expand All @@ -156,7 +156,7 @@ protected EvaluatedMove<Move> getSelected(ChessLibMoveGenerator b, SearchHistory
}

@Override
protected TranspositionTable<Move> buildTranspositionTable(int sizeInMB) {
protected TranspositionTable<Move, ChessLibMoveGenerator> buildTranspositionTable(int sizeInMB) {
return new TT(sizeInMB, SizeUnit.MB);
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/fathzer/jchess/chesslib/uci/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ static MoveLibrary<Move, ChessLibMoveGenerator> readOpenings(final URL location)

@Override
protected Collection<PerfTTestData> readTestData() {
try (InputStream stream = Main.class.getResourceAsStream("/Perft.txt")) {
try (InputStream stream = Main.class.getResourceAsStream("/com/fathzer/jchess/perft/Perft.txt")) {
return new PerfTParser().withStartPositionPrefix("position fen").withStartPositionCustomizer(s -> s+" 0 1").read(stream, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new UncheckedIOException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.zip.GZIPInputStream;

Expand Down Expand Up @@ -38,18 +38,18 @@ private String toReducedXFen(B board) {
}

@Override
protected Optional<List<JSONObject>> getRecord(B board) {
protected List<JSONObject> getRecords(B board) {
final String fen = toReducedXFen(board);
final JSONObject theRecord = db.optJSONObject(fen);
final JSONArray moves = theRecord==null ? null : theRecord.optJSONArray("moves");
if (moves==null) {
return Optional.empty();
return Collections.emptyList();
}
final List<JSONObject> result = new LinkedList<>();
for (int i=0;i<moves.length();i++) {
result.add(moves.getJSONObject(i));
}
return Optional.of(result);
return result;
}

@Override
Expand Down
15 changes: 15 additions & 0 deletions src/test/java/com/fathzer/chess/test/utils/ChessLibAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.fathzer.chess.test.utils;

import com.fathzer.jchess.chesslib.ChessLibMoveGenerator;
import com.fathzer.chess.utils.model.TestAdapter;
import com.fathzer.chess.utils.model.Variant;
import com.github.bhlangonijr.chesslib.move.Move;

public class ChessLibAdapter implements TestAdapter<ChessLibBoard, Move> {

@Override
public ChessLibBoard fenToBoard(String fen, Variant variant) {
final ChessLibMoveGenerator from = FENUtils.from(fen);
return new ChessLibBoard(from);
}
}
35 changes: 35 additions & 0 deletions src/test/java/com/fathzer/chess/test/utils/ChessLibBoard.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.fathzer.chess.test.utils;

import java.util.List;

import com.fathzer.jchess.chesslib.ChessLibMoveGenerator;
import com.fathzer.chess.utils.model.IBoard;
import com.fathzer.games.MoveGenerator.MoveConfidence;
import com.github.bhlangonijr.chesslib.move.Move;

public class ChessLibBoard implements IBoard<Move>{
private final ChessLibMoveGenerator board;

public ChessLibBoard(ChessLibMoveGenerator board) {
this.board = board;
}

@Override
public List<Move> getMoves() {
return board.getMoves();
}

@Override
public boolean makeMove(Move mv) {
return board.makeMove(mv, MoveConfidence.LEGAL);
}

@Override
public void unmakeMove() {
board.unmakeMove();
}

public ChessLibMoveGenerator getBoard() {
return board;
}
}
13 changes: 13 additions & 0 deletions src/test/java/com/fathzer/chess/test/utils/SuiteTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.fathzer.chess.test.utils;

import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;

import com.fathzer.chess.utils.test.PerftTest;

@Suite
@SuiteDisplayName("Tests from chess-test-utils")
@SelectClasses({PerftTest.class})
public class SuiteTest {
}
Loading