diff --git a/README.md b/README.md
index a8eb77c..e4a9f61 100644
--- a/README.md
+++ b/README.md
@@ -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.
\ No newline at end of file
+- 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).
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 7696b25..588835a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
1.0.8
chesslib-uci-engine
- 0.0.1
+ 0.0.2
chesslib-uci-engine
A basic uci engine plugin for jchess-uci.
@@ -50,12 +50,12 @@
com.fathzer
games-core
- 0.0.11-SNAPSHOT
+ 0.0.12-SNAPSHOT
com.fathzer
jchess-uci
- 2.0.3-SNAPSHOT
+ 2.0.4-SNAPSHOT
org.json
@@ -84,6 +84,12 @@
5.10.2
test
+
+ org.awaitility
+ awaitility
+ 4.2.2
+ test
+
diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/ChessLibDeepeningPolicy.java b/src/main/java/com/fathzer/jchess/chesslib/ai/ChessLibDeepeningPolicy.java
index 45f3b63..12de2a7 100644
--- a/src/main/java/com/fathzer/jchess/chesslib/ai/ChessLibDeepeningPolicy.java
+++ b/src/main/java/com/fathzer/jchess/chesslib/ai/ChessLibDeepeningPolicy.java
@@ -16,6 +16,7 @@ public int getNextDepth(int currentDepth) {
@Override
public boolean isEnoughTimeToDeepen(int depth) {
- return depth<5 || getSpent() implements TestableMoveGeneratorBuilder, Displayable {
private static final List> EVALUATORS = Arrays.asList(new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new));
- private final MoveLibrary ownBook;
+ private final DeferredReadMoveLibrary ownBook;
public ChessLibEngine() {
this (null);
}
- public ChessLibEngine(MoveLibrary ownBook) {
+ public ChessLibEngine(DeferredReadMoveLibrary ownBook) {
super (buildEngine(EVALUATORS.get(0).getBuilder(), 20), new BasicTimeManager<>(RemainingMoveOracle.INSTANCE));
setEvaluators(EVALUATORS);
this.ownBook = ownBook;
@@ -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 getOwnBook() {
+ return ownBook;
+ }
@Override
public boolean hasOwnBook() {
@@ -111,7 +115,7 @@ public String getBoardAsString() {
@Override
public String getFEN() {
- return board.getBoard().getFen();
+ return board==null ? null : board.getBoard().getFen();
}
@Override
diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/Main.java b/src/main/java/com/fathzer/jchess/chesslib/uci/Main.java
index 8314f47..194ddd1 100644
--- a/src/main/java/com/fathzer/jchess/chesslib/uci/Main.java
+++ b/src/main/java/com/fathzer/jchess/chesslib/uci/Main.java
@@ -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;
@@ -23,6 +20,7 @@
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 {
@@ -30,49 +28,42 @@ public class Main extends ExtendedUCI {
public static void main(String[] args) {
final String pathProperty = System.getProperty("openingsUrl");
- final MoveLibrary openings = pathProperty==null ? null : readOpenings(pathProperty);
+ final DeferredReadMoveLibrary 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 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 tokens) {
+ if (engine instanceof ChessLibEngine cle) {
+ final DeferredReadMoveLibrary 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 readOpenings(String url, final URL location) throws IOException {
+
+ static MoveLibrary 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 readTestData() {
try (InputStream stream = Main.class.getResourceAsStream("/Perft.txt")) {
@@ -83,10 +74,20 @@ protected Collection readTestData() {
}
private void speedTest(Deque 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);
+ }
}
diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/ChessLibDeepeningPolicyTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/ChessLibDeepeningPolicyTest.java
new file mode 100644
index 0000000..02599d1
--- /dev/null
+++ b/src/test/java/com/fathzer/jchess/chesslib/ai/ChessLibDeepeningPolicyTest.java
@@ -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();
+ }
+
+
+}