Skip to content

Commit

Permalink
Merge pull request #1 from fathzer-games/uci_fix
Browse files Browse the repository at this point in the history
Some fixes
  • Loading branch information
fathzer authored Jan 2, 2025
2 parents ba55c0c + fe8a6be commit 36192ab
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 43 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ The duration and accuracy of this test greatly depends on its search depth.
This depth is 1 by default (to limit Github's resources consumption - Every push trigger a mvn test action). In order to perform better test, you can set the **perftDepth** system property to a higher value.

### TODO
- The detection of invalid UNSAFE move does not work.
- The detection of invalid UNSAFE move does not work (An [issue](https://github.com/bhlangonijr/chesslib/issues/114) is opened in Chesslib project about this problem).
12 changes: 9 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<version>1.0.8</version>
</parent>
<artifactId>chesslib-uci-engine</artifactId>
<version>0.0.1</version>
<version>0.0.2</version>

<name>chesslib-uci-engine</name>
<description>A basic uci engine plugin for jchess-uci.</description>
Expand Down Expand Up @@ -50,12 +50,12 @@
<dependency>
<groupId>com.fathzer</groupId>
<artifactId>games-core</artifactId>
<version>0.0.11-SNAPSHOT</version>
<version>0.0.12-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.fathzer</groupId>
<artifactId>jchess-uci</artifactId>
<version>2.0.3-SNAPSHOT</version>
<version>2.0.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
Expand Down Expand Up @@ -84,6 +84,12 @@
<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>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public int getNextDepth(int currentDepth) {

@Override
public boolean isEnoughTimeToDeepen(int depth) {
return depth<5 || getSpent()<getMaxTime()/3;
final long spent = getSpent();
return spent<getMaxTime() && (depth<5 || spent<getMaxTime()/3);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
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.movelibrary.MoveLibrary;
import com.fathzer.games.perft.TestableMoveGeneratorBuilder;
import com.fathzer.games.util.PhysicalCores;
import com.fathzer.games.util.exec.ExecutionContext;
Expand All @@ -33,6 +32,7 @@
import com.fathzer.jchess.uci.UCIMove;
import com.fathzer.jchess.uci.extended.Displayable;
import com.fathzer.jchess.uci.helper.AbstractEngine;
import com.fathzer.jchess.uci.helper.DeferredReadMoveLibrary;
import com.fathzer.jchess.uci.helper.EvaluatorConfiguration;
import com.github.bhlangonijr.chesslib.Board;
import com.github.bhlangonijr.chesslib.Piece;
Expand All @@ -42,13 +42,13 @@
public class ChessLibEngine extends AbstractEngine<Move, ChessLibMoveGenerator> implements TestableMoveGeneratorBuilder<Move, ChessLibMoveGenerator>, Displayable {
private static final List<EvaluatorConfiguration<Move, ChessLibMoveGenerator>> EVALUATORS = Arrays.asList(new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new));

private final MoveLibrary<Move, ChessLibMoveGenerator> ownBook;
private final DeferredReadMoveLibrary<Move, ChessLibMoveGenerator> ownBook;

public ChessLibEngine() {
this (null);
}

public ChessLibEngine(MoveLibrary<Move, ChessLibMoveGenerator> ownBook) {
public ChessLibEngine(DeferredReadMoveLibrary<Move, ChessLibMoveGenerator> ownBook) {
super (buildEngine(EVALUATORS.get(0).getBuilder(), 20), new BasicTimeManager<>(RemainingMoveOracle.INSTANCE));
setEvaluators(EVALUATORS);
this.ownBook = ownBook;
Expand All @@ -63,6 +63,10 @@ public String getId() {
public String getAuthor() {
return "Jean-Marc Astesana (Fathzer), Move generator is from Ben-Hur Carlos Vieira Langoni Junior";
}

DeferredReadMoveLibrary<Move, ChessLibMoveGenerator> getOwnBook() {
return ownBook;
}

@Override
public boolean hasOwnBook() {
Expand Down Expand Up @@ -111,7 +115,7 @@ public String getBoardAsString() {

@Override
public String getFEN() {
return board.getBoard().getFen();
return board==null ? null : board.getBoard().getFen();
}

@Override
Expand Down
69 changes: 35 additions & 34 deletions src/main/java/com/fathzer/jchess/chesslib/uci/Main.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package com.fathzer.jchess.chesslib.uci;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
Expand All @@ -23,56 +20,50 @@
import com.fathzer.jchess.uci.UCI;
import com.fathzer.jchess.uci.extended.ExtendedUCI;
import com.fathzer.jchess.uci.extended.SpeedTest;
import com.fathzer.jchess.uci.helper.DeferredReadMoveLibrary;
import com.github.bhlangonijr.chesslib.move.Move;

public class Main extends ExtendedUCI {
private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);

public static void main(String[] args) {
final String pathProperty = System.getProperty("openingsUrl");
final MoveLibrary<Move, ChessLibMoveGenerator> openings = pathProperty==null ? null : readOpenings(pathProperty);
final DeferredReadMoveLibrary<Move, ChessLibMoveGenerator> openings = pathProperty==null ? null : new DeferredReadMoveLibrary<>(pathProperty, Main::readOpenings);
try (UCI uci = new Main(new ChessLibEngine(openings))) {
uci.run();
}
}

private static URL toURL(String path) throws IOException {
URL url;
try {
url = new URL(path);
} catch (MalformedURLException e) {
File file = new File(path);
if (!file.exists()) {
throw new FileNotFoundException();
}
url = file.toURI().toURL();
}
return url;
public Main(Engine defaultEngine) {
super(defaultEngine);
addCommand(this::speedTest, "st");
}

private static MoveLibrary<Move, ChessLibMoveGenerator> readOpenings(String url) {
try {
return readOpenings(url, toURL(url));
} catch (IOException e) {
LOGGER.error("Unable to load opening library at "+url, e);
return null;
@Override
protected void doIsReady(Deque<String> tokens) {
if (engine instanceof ChessLibEngine cle) {
final DeferredReadMoveLibrary<Move, ChessLibMoveGenerator> book = cle.getOwnBook();
if (book!=null && book.isInitRequired()) {
LOGGER.debug("Start reading opening library from {}", book.getUrl());
try {
book.init();
LOGGER.debug("Opening library read from {}", book.getUrl());
} catch (IOException e) {
LOGGER.error("Unable to load opening library at {}", book.getUrl(), e);
debug("An error occurred while reading opening book");
}
}
}
super.doIsReady(tokens);
}

private static MoveLibrary<Move, ChessLibMoveGenerator> readOpenings(String url, final URL location) throws IOException {
static MoveLibrary<Move, ChessLibMoveGenerator> readOpenings(final URL location) throws IOException {
final boolean compressed = location.getFile().endsWith(".gz");
try (InputStream stream = location.openStream()) {
final DefaultOpenings result = new DefaultOpenings(()->stream, compressed);
LOGGER.info("Opening library read from {}", url);
return result;
return new DefaultOpenings(()->stream, compressed);
}
}

public Main(Engine defaultEngine) {
super(defaultEngine);
addCommand(this::speedTest, "st");
}

@Override
protected Collection<PerfTTestData> readTestData() {
try (InputStream stream = Main.class.getResourceAsStream("/Perft.txt")) {
Expand All @@ -83,10 +74,20 @@ protected Collection<PerfTTestData> readTestData() {
}

private void speedTest(Deque<String> args) {
if (engine instanceof ChessLibEngine) {
out("completed in "+new SpeedTest<>((ChessLibEngine)engine).run()+"ms");
if (engine instanceof ChessLibEngine chesslibEngine) {
out("completed in "+new SpeedTest<>(chesslibEngine, this::out).run()+"ms");
} else {
debug("This engine does not support this command");
}
}

@Override
protected void err(String tag, Throwable e) {
LOGGER.error("An error occurred in {}", tag, e);
}

@Override
protected void err(CharSequence message) {
LOGGER.error("{}", message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.fathzer.jchess.chesslib.ai;

import static org.junit.jupiter.api.Assertions.*;

import java.util.concurrent.TimeUnit;

import static org.awaitility.Awaitility.*;

import org.junit.jupiter.api.Test;

import com.fathzer.games.ai.iterativedeepening.DeepeningPolicy;

class ChessLibDeepeningPolicyTest {
@Test
void test() {
final DeepeningPolicy policy = new ChessLibDeepeningPolicy(10);
assertEquals(10, policy.getDepth());
assertEquals(2, policy.getStartDepth());
assertEquals(4, policy.getNextDepth(2));
assertEquals(6, policy.getNextDepth(4));
assertEquals(7, policy.getNextDepth(6));
assertEquals(10, policy.getNextDepth(10));
}

@Test
void bug20241127() {
// isEnoughTimeToDeepen returned true when time was spent and depth was < 5
final DeepeningPolicy policy = new ChessLibDeepeningPolicy(10);
policy.setMaxTime(1);
assertThrows(IllegalStateException.class, () -> policy.getSpent());
policy.start();
await().atLeast(10, TimeUnit.MILLISECONDS);
assertFalse(policy.isEnoughTimeToDeepen(4));

policy.setMaxTime(10000);
policy.start();
}


}

0 comments on commit 36192ab

Please sign in to comment.