From cb51affe2f2221169622d8a1d395358d19e07d43 Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 11:03:22 +0100 Subject: [PATCH 01/55] An example of calling engine to have three best moves with their pv --- .../jchess/chesslib/ai/HBThreeMovesTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java new file mode 100644 index 0000000..7aaecf8 --- /dev/null +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java @@ -0,0 +1,34 @@ +package com.fathzer.jchess.chesslib.ai; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fathzer.games.ai.evaluation.EvaluatedMove; +import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.uci.ChessLibEngine; +import com.github.bhlangonijr.chesslib.move.Move; + +class HBThreeMovesTest { + + @Test + void test() { + final int depth = 6; + final int bestMoveCount = 3; + final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(SimplifiedEvaluator::new, depth); + engine.getDeepeningPolicy().setSize(bestMoveCount); + final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)); + System.out.println(moves); + for (int i=0;i<3;i++) { + EvaluatedMove move = moves.get(i); + List principalVariation = move.getPrincipalVariation(); + System.out.println(move+" -> "+principalVariation); + } + } + +} From 3f9a979d2ed3e1d65ffe69fc049f0dc8ea47cbcf Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 12:12:47 +0100 Subject: [PATCH 02/55] =?UTF-8?q?squelette=20d'=C3=A9valuateur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 16 ++++++++++++++++ .../jchess/chesslib/uci/ChessLibEngine.java | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java new file mode 100644 index 0000000..952ac9c --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -0,0 +1,16 @@ +package com.fathzer.jchess.chesslib.ai.eval; + +import com.fathzer.games.ai.evaluation.StaticEvaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.move.Move; + +public class MyTinyEvaluator implements StaticEvaluator, ZeroSumEvaluator { + + @Override + public int evaluateAsWhite(ChessLibMoveGenerator board) { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index c46d39d..8240747 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -19,6 +19,7 @@ import com.fathzer.jchess.chesslib.ai.ChessLibDeepeningPolicy; import com.fathzer.jchess.chesslib.ai.DefaultLogger; import com.fathzer.jchess.chesslib.ai.TT; +import com.fathzer.jchess.chesslib.ai.eval.MyTinyEvaluator; import com.fathzer.jchess.chesslib.ai.eval.NaiveEvaluator; import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; import com.fathzer.jchess.chesslib.time.RemainingMoveOracle; @@ -32,7 +33,8 @@ import com.github.bhlangonijr.chesslib.move.Move; public class ChessLibEngine extends AbstractEngine implements TestableMoveGeneratorBuilder, Displayable { - private static final List> EVALUATORS = Arrays.asList(new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); + private static final List> EVALUATORS = + Arrays.asList(new EvaluatorConfiguration<>("hb",MyTinyEvaluator::new),new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); public ChessLibEngine() { super (buildEngine(EVALUATORS.get(0).getBuilder(), 8), new BasicTimeManager<>(RemainingMoveOracle.INSTANCE)); From 1f95cd2bae46540bd73529b01d74537682be3936 Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 11:03:22 +0100 Subject: [PATCH 03/55] An example of calling engine to have three best moves with their pv --- .../jchess/chesslib/ai/HBThreeMovesTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java new file mode 100644 index 0000000..7aaecf8 --- /dev/null +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java @@ -0,0 +1,34 @@ +package com.fathzer.jchess.chesslib.ai; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fathzer.games.ai.evaluation.EvaluatedMove; +import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.uci.ChessLibEngine; +import com.github.bhlangonijr.chesslib.move.Move; + +class HBThreeMovesTest { + + @Test + void test() { + final int depth = 6; + final int bestMoveCount = 3; + final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(SimplifiedEvaluator::new, depth); + engine.getDeepeningPolicy().setSize(bestMoveCount); + final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)); + System.out.println(moves); + for (int i=0;i<3;i++) { + EvaluatedMove move = moves.get(i); + List principalVariation = move.getPrincipalVariation(); + System.out.println(move+" -> "+principalVariation); + } + } + +} From 31f501a26fbc43b4f296c7172fc03688a0fd28f4 Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 12:12:47 +0100 Subject: [PATCH 04/55] =?UTF-8?q?squelette=20d'=C3=A9valuateur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 16 ++++++++++++++++ .../jchess/chesslib/uci/ChessLibEngine.java | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java new file mode 100644 index 0000000..952ac9c --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -0,0 +1,16 @@ +package com.fathzer.jchess.chesslib.ai.eval; + +import com.fathzer.games.ai.evaluation.StaticEvaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.move.Move; + +public class MyTinyEvaluator implements StaticEvaluator, ZeroSumEvaluator { + + @Override + public int evaluateAsWhite(ChessLibMoveGenerator board) { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index f9feeb8..7210c0f 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -20,6 +20,7 @@ import com.fathzer.jchess.chesslib.ai.ChessLibDeepeningPolicy; import com.fathzer.jchess.chesslib.ai.DefaultLogger; import com.fathzer.jchess.chesslib.ai.TT; +import com.fathzer.jchess.chesslib.ai.eval.MyTinyEvaluator; import com.fathzer.jchess.chesslib.ai.eval.NaiveEvaluator; import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; import com.fathzer.jchess.chesslib.time.RemainingMoveOracle; @@ -33,7 +34,8 @@ import com.github.bhlangonijr.chesslib.move.Move; public class ChessLibEngine extends AbstractEngine implements TestableMoveGeneratorBuilder, Displayable { - private static final List> EVALUATORS = Arrays.asList(new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); + private static final List> EVALUATORS = + Arrays.asList(new EvaluatorConfiguration<>("hb",MyTinyEvaluator::new),new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); public ChessLibEngine() { super (buildEngine(EVALUATORS.get(0).getBuilder(), 20), new BasicTimeManager<>(RemainingMoveOracle.INSTANCE)); From 4c3d9b3e59d020d1c5e3487d1d45bca86847b86f Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 11:03:22 +0100 Subject: [PATCH 05/55] An example of calling engine to have three best moves with their pv --- .../jchess/chesslib/ai/HBThreeMovesTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java new file mode 100644 index 0000000..7aaecf8 --- /dev/null +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java @@ -0,0 +1,34 @@ +package com.fathzer.jchess.chesslib.ai; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fathzer.games.ai.evaluation.EvaluatedMove; +import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.uci.ChessLibEngine; +import com.github.bhlangonijr.chesslib.move.Move; + +class HBThreeMovesTest { + + @Test + void test() { + final int depth = 6; + final int bestMoveCount = 3; + final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(SimplifiedEvaluator::new, depth); + engine.getDeepeningPolicy().setSize(bestMoveCount); + final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)); + System.out.println(moves); + for (int i=0;i<3;i++) { + EvaluatedMove move = moves.get(i); + List principalVariation = move.getPrincipalVariation(); + System.out.println(move+" -> "+principalVariation); + } + } + +} From bf384ddcb62a9c97d9c0373debc80b0a6ac2a15e Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 12:12:47 +0100 Subject: [PATCH 06/55] =?UTF-8?q?squelette=20d'=C3=A9valuateur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 16 ++++++++++++++++ .../jchess/chesslib/uci/ChessLibEngine.java | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java new file mode 100644 index 0000000..952ac9c --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -0,0 +1,16 @@ +package com.fathzer.jchess.chesslib.ai.eval; + +import com.fathzer.games.ai.evaluation.StaticEvaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.move.Move; + +public class MyTinyEvaluator implements StaticEvaluator, ZeroSumEvaluator { + + @Override + public int evaluateAsWhite(ChessLibMoveGenerator board) { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index e7279a7..0e07c76 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -24,6 +24,7 @@ import com.fathzer.jchess.chesslib.ai.ChessLibDeepeningPolicy; import com.fathzer.jchess.chesslib.ai.DefaultLogger; import com.fathzer.jchess.chesslib.ai.TT; +import com.fathzer.jchess.chesslib.ai.eval.MyTinyEvaluator; import com.fathzer.jchess.chesslib.ai.eval.NaiveEvaluator; import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; import com.fathzer.jchess.chesslib.time.RemainingMoveOracle; @@ -37,7 +38,8 @@ import com.github.bhlangonijr.chesslib.move.Move; public class ChessLibEngine extends AbstractEngine implements TestableMoveGeneratorBuilder, Displayable { - private static final List> EVALUATORS = Arrays.asList(new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); + private static final List> EVALUATORS = + Arrays.asList(new EvaluatorConfiguration<>("hb",MyTinyEvaluator::new),new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); public ChessLibEngine() { super (buildEngine(EVALUATORS.get(0).getBuilder(), 20), new BasicTimeManager<>(RemainingMoveOracle.INSTANCE)); From 949a18033da9e67e7c81e6f4d39b8c5fccd3106c Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 11:03:22 +0100 Subject: [PATCH 07/55] An example of calling engine to have three best moves with their pv --- .../jchess/chesslib/ai/HBThreeMovesTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java new file mode 100644 index 0000000..7aaecf8 --- /dev/null +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java @@ -0,0 +1,34 @@ +package com.fathzer.jchess.chesslib.ai; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fathzer.games.ai.evaluation.EvaluatedMove; +import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.uci.ChessLibEngine; +import com.github.bhlangonijr.chesslib.move.Move; + +class HBThreeMovesTest { + + @Test + void test() { + final int depth = 6; + final int bestMoveCount = 3; + final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(SimplifiedEvaluator::new, depth); + engine.getDeepeningPolicy().setSize(bestMoveCount); + final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)); + System.out.println(moves); + for (int i=0;i<3;i++) { + EvaluatedMove move = moves.get(i); + List principalVariation = move.getPrincipalVariation(); + System.out.println(move+" -> "+principalVariation); + } + } + +} From e44b9b1c269b37c9f87f96c1a93aa2c26f61f760 Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 12:12:47 +0100 Subject: [PATCH 08/55] =?UTF-8?q?squelette=20d'=C3=A9valuateur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 16 ++++++++++++++++ .../jchess/chesslib/uci/ChessLibEngine.java | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java new file mode 100644 index 0000000..952ac9c --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -0,0 +1,16 @@ +package com.fathzer.jchess.chesslib.ai.eval; + +import com.fathzer.games.ai.evaluation.StaticEvaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.move.Move; + +public class MyTinyEvaluator implements StaticEvaluator, ZeroSumEvaluator { + + @Override + public int evaluateAsWhite(ChessLibMoveGenerator board) { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index af8ab0e..49e8c08 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -25,6 +25,7 @@ import com.fathzer.jchess.chesslib.ai.ChessLibDeepeningPolicy; import com.fathzer.jchess.chesslib.ai.DefaultLogger; import com.fathzer.jchess.chesslib.ai.TT; +import com.fathzer.jchess.chesslib.ai.eval.MyTinyEvaluator; import com.fathzer.jchess.chesslib.ai.eval.NaiveEvaluator; import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; import com.fathzer.jchess.chesslib.time.RemainingMoveOracle; @@ -38,7 +39,8 @@ import com.github.bhlangonijr.chesslib.move.Move; public class ChessLibEngine extends AbstractEngine implements TestableMoveGeneratorBuilder, Displayable { - private static final List> EVALUATORS = Arrays.asList(new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); + private static final List> EVALUATORS = + Arrays.asList(new EvaluatorConfiguration<>("hb",MyTinyEvaluator::new),new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); private final Function ownBook; From 2a04678981b1f13a5811c3fe8cc0956e70d9db06 Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 7 Mar 2024 19:24:17 +0100 Subject: [PATCH 09/55] MyTinyEvaluator => example of static reuse of SimplifiedEvaluator --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java index 952ac9c..079ce41 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -3,14 +3,25 @@ import com.fathzer.games.ai.evaluation.StaticEvaluator; import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.Board; import com.github.bhlangonijr.chesslib.move.Move; public class MyTinyEvaluator implements StaticEvaluator, ZeroSumEvaluator { + private final SimplifiedEvaluator ev = new SimplifiedEvaluator(); @Override public int evaluateAsWhite(ChessLibMoveGenerator board) { - // TODO Auto-generated method stub - return 0; + // Calculer l'évaluation de base + ev.init(board); + int baseEvaluation = ev.evaluate(board); + // Tu peux ajouter ce qui concerne les chaines de pions, mauvais/bon fous, etc à l'évaluation de base ... + return baseEvaluation; } + public static void main(String[] args) { + // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer + ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(new Board()); + mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); + System.out.println(new MyTinyEvaluator().evaluate(mvg)); + } } From 40ea64a776b874f045d08ee5c262b78392d96b8f Mon Sep 17 00:00:00 2001 From: Fathzer Date: Sat, 9 Mar 2024 15:53:51 +0100 Subject: [PATCH 10/55] Fixes MyTinyEvaluator hang + search deepen on forced moves --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 15 +++++++++++++-- .../jchess/chesslib/uci/ChessLibEngine.java | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java index 079ce41..a66ca21 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -12,11 +12,22 @@ public class MyTinyEvaluator implements StaticEvaluator fork() { + // Attention : SimplifiedEvaluator n'est pas thread safe, ce qui est généralement le cas des évaluateurs statiques (d'où l'implémentation par défaut de fork qui renvoie this). + // Pour éviter les pb de threading, soit on crée un évaluateur par thread comme ici, soit l'usage du SimplifiedEvaluator doit être protégé par un synchronized (pas performant). + return new MyTinyEvaluator(); + } + public static void main(String[] args) { // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index 49e8c08..3165d6b 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -141,6 +141,7 @@ protected Negamax buildNegaMax(ExecutionContext1 ? 2 : 1); engine.getDeepeningPolicy().setMaxTime(60000); + engine.getDeepeningPolicy().setDeepenOnForced(false); return engine; } From 2a0a7bc52e5b6d7301c22c54a44a8e7e94b78d84 Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 11:03:22 +0100 Subject: [PATCH 11/55] An example of calling engine to have three best moves with their pv --- .../jchess/chesslib/ai/HBThreeMovesTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java new file mode 100644 index 0000000..7aaecf8 --- /dev/null +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java @@ -0,0 +1,34 @@ +package com.fathzer.jchess.chesslib.ai; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fathzer.games.ai.evaluation.EvaluatedMove; +import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.uci.ChessLibEngine; +import com.github.bhlangonijr.chesslib.move.Move; + +class HBThreeMovesTest { + + @Test + void test() { + final int depth = 6; + final int bestMoveCount = 3; + final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(SimplifiedEvaluator::new, depth); + engine.getDeepeningPolicy().setSize(bestMoveCount); + final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)); + System.out.println(moves); + for (int i=0;i<3;i++) { + EvaluatedMove move = moves.get(i); + List principalVariation = move.getPrincipalVariation(); + System.out.println(move+" -> "+principalVariation); + } + } + +} From f86bfc5b99422548ba123b8d10028d1d7beb4bc0 Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 12:12:47 +0100 Subject: [PATCH 12/55] =?UTF-8?q?squelette=20d'=C3=A9valuateur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 16 ++++++++++++++++ .../jchess/chesslib/uci/ChessLibEngine.java | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java new file mode 100644 index 0000000..952ac9c --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -0,0 +1,16 @@ +package com.fathzer.jchess.chesslib.ai.eval; + +import com.fathzer.games.ai.evaluation.StaticEvaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.move.Move; + +public class MyTinyEvaluator implements StaticEvaluator, ZeroSumEvaluator { + + @Override + public int evaluateAsWhite(ChessLibMoveGenerator board) { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index 17305b0..1bb2628 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -25,6 +25,7 @@ import com.fathzer.jchess.chesslib.ai.ChessLibDeepeningPolicy; import com.fathzer.jchess.chesslib.ai.DefaultLogger; import com.fathzer.jchess.chesslib.ai.TT; +import com.fathzer.jchess.chesslib.ai.eval.MyTinyEvaluator; import com.fathzer.jchess.chesslib.ai.eval.NaiveEvaluator; import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; import com.fathzer.jchess.chesslib.time.RemainingMoveOracle; @@ -38,7 +39,8 @@ import com.github.bhlangonijr.chesslib.move.Move; public class ChessLibEngine extends AbstractEngine implements TestableMoveGeneratorBuilder, Displayable { - private static final List> EVALUATORS = Arrays.asList(new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); + private static final List> EVALUATORS = + Arrays.asList(new EvaluatorConfiguration<>("hb",MyTinyEvaluator::new),new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); private final MoveLibrary ownBook; From b2e1bf75c8e79f744d7399afb01df342e53ce50f Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 7 Mar 2024 19:24:17 +0100 Subject: [PATCH 13/55] MyTinyEvaluator => example of static reuse of SimplifiedEvaluator --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java index 952ac9c..079ce41 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -3,14 +3,25 @@ import com.fathzer.games.ai.evaluation.StaticEvaluator; import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.Board; import com.github.bhlangonijr.chesslib.move.Move; public class MyTinyEvaluator implements StaticEvaluator, ZeroSumEvaluator { + private final SimplifiedEvaluator ev = new SimplifiedEvaluator(); @Override public int evaluateAsWhite(ChessLibMoveGenerator board) { - // TODO Auto-generated method stub - return 0; + // Calculer l'évaluation de base + ev.init(board); + int baseEvaluation = ev.evaluate(board); + // Tu peux ajouter ce qui concerne les chaines de pions, mauvais/bon fous, etc à l'évaluation de base ... + return baseEvaluation; } + public static void main(String[] args) { + // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer + ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(new Board()); + mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); + System.out.println(new MyTinyEvaluator().evaluate(mvg)); + } } From 2320dd0d41de5a2c8243b374699d6f48fc49ffc3 Mon Sep 17 00:00:00 2001 From: Fathzer Date: Sat, 9 Mar 2024 15:53:51 +0100 Subject: [PATCH 14/55] Fixes MyTinyEvaluator hang + search deepen on forced moves --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 15 +++++++++++++-- .../jchess/chesslib/uci/ChessLibEngine.java | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java index 079ce41..a66ca21 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -12,11 +12,22 @@ public class MyTinyEvaluator implements StaticEvaluator fork() { + // Attention : SimplifiedEvaluator n'est pas thread safe, ce qui est généralement le cas des évaluateurs statiques (d'où l'implémentation par défaut de fork qui renvoie this). + // Pour éviter les pb de threading, soit on crée un évaluateur par thread comme ici, soit l'usage du SimplifiedEvaluator doit être protégé par un synchronized (pas performant). + return new MyTinyEvaluator(); + } + public static void main(String[] args) { // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index 1bb2628..381e0f0 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -140,6 +140,7 @@ protected Negamax buildNegaMax(ExecutionContext1 ? 2 : 1); engine.getDeepeningPolicy().setMaxTime(60000); + engine.getDeepeningPolicy().setDeepenOnForced(false); return engine; } From c132cc09f6386e4a740c30040262d05318ccec30 Mon Sep 17 00:00:00 2001 From: herve Date: Sat, 16 Mar 2024 09:53:29 +0100 Subject: [PATCH 15/55] =?UTF-8?q?Classes=20pour=20ma=20premi=C3=A8re=20fon?= =?UTF-8?q?ction=20d'=C3=A9valuation=20s'appuyant=20sur=20SimplifiedEvalua?= =?UTF-8?q?tor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...bstractIncrementalSimplifiedEvaluator.java | 89 +++++++++++++ .../chesslib/ai/eval/hbpg/HbBasicState.java | 52 ++++++++ .../ai/eval/hbpg/HbFastPhaseDetector.java | 64 ++++++++++ .../ai/eval/hbpg/HbIncrementalState.java | 73 +++++++++++ .../ai/eval/hbpg/HbMyFirstEvaluator.java | 40 ++++++ .../jchess/chesslib/ai/eval/hbpg/HbPhase.java | 13 ++ .../ai/eval/hbpg/HbSimplifiedEvaluator.java | 27 ++++ .../eval/hbpg/HbSimplifiedEvaluatorBase.java | 120 ++++++++++++++++++ .../chesslib/ai/eval/hbpg/package-info.java | 1 + 9 files changed, 479 insertions(+) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java new file mode 100644 index 0000000..bb291b9 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java @@ -0,0 +1,89 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import java.util.function.Supplier; + +import com.fathzer.chess.utils.adapters.MoveData; +import com.fathzer.games.MoveGenerator; +import com.fathzer.games.ai.evaluation.Evaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.games.util.Stack; + +/** An incremental implementation of the simplified evaluator described at https://www.chessprogramming.org/Simplified_Evaluation_Function + *
This only works with 8*8 games and exactly one king per Color. + */ +public abstract class HbAbstractIncrementalSimplifiedEvaluator> extends HbSimplifiedEvaluatorBase implements ZeroSumEvaluator, Supplier> { + private final Stack states; + private HbIncrementalState toCommit; + private MoveData moveData; + + /** Default constructor + */ + protected HbAbstractIncrementalSimplifiedEvaluator() { + this.states = new Stack<>(HbIncrementalState::new); + this.moveData = get(); + } + + /** Constructor. + * @param state The state to initialize the evaluator + */ + protected HbAbstractIncrementalSimplifiedEvaluator(HbIncrementalState state) { + this(); + HbIncrementalState other = new HbIncrementalState(); + state.copyTo(other); + states.set(state); + } + + + @Override + public Evaluator fork() { + return fork(states.get()); + } + + /** Creates a new instance initialized with current state that will become the initial state of created instance. + * @param state The initial state. + * @return a new evaluator of the same class as this, this the same view point, and initialized with the state. + */ + protected abstract HbAbstractIncrementalSimplifiedEvaluator fork(HbIncrementalState state); + + @Override + public void init(B board) { + states.clear(); + states.set(new HbIncrementalState(getExplorer(board))); + } + + @Override + public void prepareMove(B board, M move) { + if (moveData.update(move, board)) { + buildToCommit(); + toCommit.update(moveData); + } + } + + private void buildToCommit() { + final HbIncrementalState current = states.get(); + states.next(); + toCommit = states.get(); + states.previous(); + current.copyTo(toCommit); + } + + @Override + public void commitMove() { + states.next(); + states.set(toCommit); + } + + @Override + public void unmakeMove() { + states.previous(); + } + + @Override + public int evaluateAsWhite(B board) { + return states.get().evaluateAsWhite(); + } + + HbIncrementalState getState() { + return states.get(); + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java new file mode 100644 index 0000000..ecd3e71 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java @@ -0,0 +1,52 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import static com.fathzer.chess.utils.Pieces.KING; + +import com.fathzer.chess.utils.adapters.BoardExplorer; + +/** The state of the evaluator. + */ +class HbBasicState extends HbFastPhaseDetector { + int points; + int whiteKingIndex; + int blackKingIndex; + + HbBasicState() { + super(); + } + + void copyTo(HbBasicState other) { + super.copyTo(other); + other.points = points; + other.blackKingIndex = blackKingIndex; + other.whiteKingIndex = whiteKingIndex; + } + + HbBasicState(BoardExplorer explorer) { + this.points = 0; + do { + final int p = explorer.getPiece(); + add(p); + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind!=KING) { + int inc = HbSimplifiedEvaluatorBase.getRawValue(kind); + inc += HbSimplifiedEvaluatorBase.getPositionValue(kind, isBlack, index); + if (isBlack) { + points -= inc; + } else { + points += inc; + } + } else if (isBlack) { + this.blackKingIndex = index; + } else { + this.whiteKingIndex = index; + } + } while (explorer.next()); + } + + int evaluateAsWhite() { + return points + HbSimplifiedEvaluatorBase.getKingPositionsValue(whiteKingIndex, blackKingIndex, getPhase()); + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java new file mode 100644 index 0000000..14beee7 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java @@ -0,0 +1,64 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import static com.fathzer.chess.utils.Pieces.KING; + +/** A class that tracks the current phase. + */ +class HbFastPhaseDetector { + private static final long BLACK_QUEEN_VALUE = 0x01L; + private static final long BLACK_QUEEN_MASK = 0xFFL; + private static final long WHITE_QUEEN_VALUE = 0x0100L; + private static final long WHITE_QUEEN_MASK = 0xFF00L; + private static final long BLACK_ROOK_VALUE = 0x010000L; + private static final long BLACK_ROOK_MASK = 0xFF0000L; + private static final long WHITE_ROOK_VALUE = 0x01000000L; + private static final long WHITE_ROOK_MASK = 0xFF000000L; + private static final long BLACK_MINOR_VALUE = 0x0100000000L; + private static final long BLACK_MINOR_MASK = 0xFF00000000L; + private static final long WHITE_MINOR_VALUE = 0x010000000000L; + private static final long WHITE_MINOR_MASK = 0xFF0000000000L; + + private static final long[] PIECE_KIND_TO_VALUES = new long[] {0L, BLACK_QUEEN_VALUE, BLACK_ROOK_VALUE, BLACK_MINOR_VALUE, BLACK_MINOR_VALUE, 0L, 0L, 0L, WHITE_MINOR_VALUE, WHITE_MINOR_VALUE, WHITE_ROOK_VALUE, WHITE_QUEEN_VALUE, 0L}; + + private long state; + + void add(int piece) { + state += PIECE_KIND_TO_VALUES[piece + KING]; + } + + void remove(int piece) { + state -= PIECE_KIND_TO_VALUES[piece + KING]; + } + + HbPhase getPhase() { + final boolean whiteQueen = (state & WHITE_QUEEN_MASK) != 0L; + final boolean blackQueen = (state & BLACK_QUEEN_MASK) != 0L; + if (!blackQueen && !whiteQueen) { + return HbPhase.END_GAME; + } + if ((blackQueen && (hasBlackRook() || hasManyBlackMinor())) || (whiteQueen && (hasWhiteRook() || hasManyWhiteMinor()))) { + return HbPhase.MIDDLE_GAME; + } + return HbPhase.END_GAME; + } + + boolean hasWhiteRook() { + return (state & WHITE_ROOK_MASK) != 0; + } + + boolean hasBlackRook() { + return (state & BLACK_ROOK_MASK) != 0; + } + + boolean hasManyBlackMinor() { + return (state & BLACK_MINOR_MASK) > BLACK_MINOR_VALUE; + } + + boolean hasManyWhiteMinor() { + return (state & WHITE_MINOR_MASK) > WHITE_MINOR_VALUE; + } + + void copyTo(HbFastPhaseDetector other) { + other.state = state; + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java new file mode 100644 index 0000000..8caafc0 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java @@ -0,0 +1,73 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import static com.fathzer.chess.utils.Pieces.*; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg.HbSimplifiedEvaluatorBase.*; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.chess.utils.adapters.MoveData; + +/** The current state of a {@link HbAbstractIncrementalSimplifiedEvaluator} + */ +public class HbIncrementalState extends HbBasicState { + HbIncrementalState() { + super(); + } + + HbIncrementalState(BoardExplorer exp) { + super(exp); + } + + void update(MoveData move) { + points += getIncrement(move); + } + + private int getIncrement(MoveData move) { + final boolean isBlack = move.getMovingPiece()<0; + int moving = Math.abs(move.getMovingPiece()); + final int movingIndex = move.getMovingIndex(); + int inc; + if (moving==KING) { + // The position value of kings is not evaluated incrementally + int rookIndex = move.getCastlingRookIndex(); + if (rookIndex>=0) { + // It's a castling move, update rook positions values + inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); + } else { + inc = doCapture(isBlack, move); + } + // Update king's position + if (isBlack) { + this.blackKingIndex = move.getMovingDestination(); + } else { + this.whiteKingIndex = move.getMovingDestination(); + } + } else { + // Remove the position value of the moving piece + inc = - getPositionValue(moving, isBlack, movingIndex); + final int promoType = move.getPromotionType(); + if (promoType!=0) { + // If promotion, add raw value points, update phase + inc += getRawValue(promoType)-getRawValue(PAWN); + moving = promoType; + add(isBlack ? -promoType : promoType); + } + inc += doCapture(isBlack, move); + // Adds the position value of the + inc += getPositionValue(moving, isBlack, move.getMovingDestination()); + } + return isBlack ? -inc : +inc; + } + + private int doCapture(boolean isBlack, MoveData move) { + int captured = move.getCapturedType(); + if (captured!=0) { + // A piece was captured + // Update the phase detector + remove(isBlack ? captured : -captured); + // Then add its raw value and its position value + return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); + } else { + return 0; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java new file mode 100644 index 0000000..dc7c43a --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java @@ -0,0 +1,40 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import com.fathzer.games.ai.evaluation.StaticEvaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.move.Move; + + +public class HbMyFirstEvaluator implements StaticEvaluator, ZeroSumEvaluator { + private final SimplifiedEvaluator ev = new SimplifiedEvaluator(); + + @Override + public int evaluateAsWhite(ChessLibMoveGenerator board) { + // Calculer l'évaluation de base + int baseEvaluation; +// synchronized (this) { // Alternative à la méthode fork + ev.init(board); + baseEvaluation = ev.evaluateAsWhite(board); +// } + // Tu peux ajouter ce qui concerne les chaines de pions, mauvais/bon fous, etc à l'évaluation de base ... + return baseEvaluation; + } + + @Override + public StaticEvaluator fork() { + // Attention : SimplifiedEvaluator n'est pas thread safe, ce qui est généralement le cas des évaluateurs statiques (d'où l'implémentation par défaut de fork qui renvoie this). + // Pour éviter les pb de threading, soit on crée un évaluateur par thread comme ici, soit l'usage du SimplifiedEvaluator doit être protégé par un synchronized (pas performant). + return new HbMyFirstEvaluator(); + } + + + public static void main(String[] args) { + // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer + ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(new Board()); + mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); + System.out.println(new HbMyFirstEvaluator().evaluate(mvg)); + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java new file mode 100644 index 0000000..d75ca9d --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java @@ -0,0 +1,13 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +/** The phases of a game. + *
There's only two phases in the simplified evaluator, and not three as we could expect. + * The idea is, in the opening phase, the evaluation function should be replaced by an opening library, the middle game starts when the position + * is no more in the library. + */ +enum HbPhase { + /** Middle of the game.*/ + MIDDLE_GAME, + /** End of the game */ + END_GAME +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java new file mode 100644 index 0000000..7dbb502 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java @@ -0,0 +1,27 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import com.fathzer.chess.utils.adapters.MoveData; +import com.fathzer.jchess.chesslib.ChessLibExplorerBuilder; +import com.fathzer.jchess.chesslib.ChessLibMoveData; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.move.Move; + +public class HbSimplifiedEvaluator extends HbAbstractIncrementalSimplifiedEvaluator implements ChessLibExplorerBuilder { + private HbSimplifiedEvaluator(HbIncrementalState state) { + super(state); + } + + public HbSimplifiedEvaluator() { + super(); + } + + @Override + public MoveData get() { + return new ChessLibMoveData(); + } + + @Override + protected HbAbstractIncrementalSimplifiedEvaluator fork(HbIncrementalState state) { + return new HbSimplifiedEvaluator(state); + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java new file mode 100644 index 0000000..0ef0c26 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java @@ -0,0 +1,120 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.chess.utils.adapters.BoardExplorerBuilder; + +import com.fathzer.chess.utils.Pieces; +import com.fathzer.games.MoveGenerator; + +abstract class HbSimplifiedEvaluatorBase> implements BoardExplorerBuilder { + private static final int[] PIECE_VALUES = {0, 100, 320, 330, 500, 900, 20000}; + private static final int[] KING_MID_GAME_EVAL = new int[] { + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -20,-30,-30,-40,-40,-30,-30,-20, + -10,-20,-20,-20,-20,-20,-20,-10, + 20, 20, 0, 0, 0, 0, 20, 20, + 20, 30, 10, 0, 0, 10, 30, 20}; + + private static final int[] KING_END_GAME_EVAL = new int[] { + -50,-40,-30,-20,-20,-30,-40,-50, + -30,-20,-10, 0, 0,-10,-20,-30, + -30,-10, 20, 30, 30, 20,-10,-30, + -30,-10, 30, 40, 40, 30,-10,-30, + -30,-10, 30, 40, 40, 30,-10,-30, + -30,-10, 20, 30, 30, 20,-10,-30, + -30,-30, 0, 0, 0, 0,-30,-30, + -50,-30,-30,-30,-30,-30,-30,-50}; + + private static final int [][] PIECE_POSITION_VALUES = new int[][] { + // Just to have index equals to piece type codes + new int[0], + // PAWN + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 50, 50, 50, 50, 50, 50, 50, 50, + 10, 10, 20, 30, 30, 20, 10, 10, + 5, 5, 10, 25, 25, 10, 5, 5, + 0, 0, 0, 20, 20, 0, 0, 0, + 5, -5,-10, 0, 0,-10, -5, 5, + 5, 10, 10,-20,-20, 10, 10, 5, + 0, 0, 0, 0, 0, 0, 0, 0}, + // KNIGHT + new int[] { + -50,-40,-30,-30,-30,-30,-40,-50, + -40,-20, 0, 0, 0, 0,-20,-40, + -30, 0, 10, 15, 15, 10, 0,-30, + -30, 5, 15, 20, 20, 15, 5,-30, + -30, 0, 15, 20, 20, 15, 0,-30, + -30, 5, 10, 15, 15, 10, 5,-30, + -40,-20, 0, 5, 5, 0,-20,-40, + -50,-40,-30,-30,-30,-30,-40,-50}, + // BISHOP + new int[] { + -20,-10,-10,-10,-10,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 10, 10, 5, 0,-10, + -10, 5, 5, 10, 10, 5, 5,-10, + -10, 0, 10, 10, 10, 10, 0,-10, + -10, 10, 10, 10, 10, 10, 10,-10, + -10, 5, 0, 0, 0, 0, 5,-10, + -20,-10,-10,-10,-10,-10,-10,-20}, + // ROOK + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 10, 10, 10, 10, 10, 10, 5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + 0, 0, 0, 5, 5, 0, 0, 0}, + // QUEEN + new int[] { + -20,-10,-10, -5, -5,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 5, 5, 5, 0,-10, + -5, 0, 5, 5, 5, 5, 0, -5, + 0, 0, 5, 5, 5, 5, 0, -5, + -10, 5, 5, 5, 5, 5, 0,-10, + -10, 0, 5, 0, 0, 0, 0,-10, + -20,-10,-10, -5, -5,-10,-10,-20 + }}; + + HbSimplifiedEvaluatorBase() { + super(); + } + + static int getPositionValue(int type, boolean black, int index) { + return getPositionValue(PIECE_POSITION_VALUES[type], index, black); + } + + static int getRawValue(int type) { + return PIECE_VALUES[type]; + } + + static int getKingPositionsValue(int whiteIndex, int blackIndex, HbPhase phase) { + final int[] kingMap = phase==HbPhase.MIDDLE_GAME ? KING_MID_GAME_EVAL : KING_END_GAME_EVAL; + return getPositionValue(kingMap, whiteIndex, false) - getPositionValue(kingMap, blackIndex, true); + } + + private static int getPositionValue(int[] positionMap, int index, boolean black) { + if (black) { + final int row = 7 - index/8; + final int col = index%8; + index = row*8 + col; + } + return positionMap[index]; + } + + /** Gets the position value associated with a type of piece and an index. + * @param type The piece type as define in {@link Pieces} + * @param index The index of the piece on the board as defined in {@link BoardExplorer} + * @return an integer + */ + static int getPositionValue(int type, int index) { + return PIECE_POSITION_VALUES[type][index]; + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java new file mode 100644 index 0000000..327ea90 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java @@ -0,0 +1 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; \ No newline at end of file From 587c0c9fcbf125ac31114a366c5f1d314f791218 Mon Sep 17 00:00:00 2001 From: herve Date: Tue, 26 Mar 2024 07:29:05 +0100 Subject: [PATCH 16/55] HbMyFirstEvaluator uses Hb Classes, from now on. Correction. --- .../jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java index dc7c43a..1d0046c 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java @@ -9,7 +9,7 @@ public class HbMyFirstEvaluator implements StaticEvaluator, ZeroSumEvaluator { - private final SimplifiedEvaluator ev = new SimplifiedEvaluator(); + private final HbSimplifiedEvaluator ev = new HbSimplifiedEvaluator(); @Override public int evaluateAsWhite(ChessLibMoveGenerator board) { From 1477ae6638726df6eeebb22a50467cf0716a6bed Mon Sep 17 00:00:00 2001 From: herve Date: Fri, 29 Mar 2024 08:38:16 +0100 Subject: [PATCH 17/55] Hb2MyFirstEvaluator: the beginning. Compared to the SimplifiedEvaluator the evaluation function is tapered (scale = 64) --- .../ai/eval/hbpg/HbIncrementalState.java | 7 +- .../ai/eval/hbpg/HbMyFirstEvaluator.java | 1 - .../eval/hbpg/HbSimplifiedEvaluatorBase.java | 3 +- ...bstractIncrementalSimplifiedEvaluator.java | 89 ++++++++++++ .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 65 +++++++++ .../ai/eval/hbpg2/Hb2FastPhaseDetector.java | 29 ++++ .../ai/eval/hbpg2/Hb2IncrementalState.java | 76 +++++++++++ .../ai/eval/hbpg2/Hb2MyFirstEvaluator.java | 39 ++++++ .../chesslib/ai/eval/hbpg2/Hb2Phase.java | 41 ++++++ .../ai/eval/hbpg2/Hb2SimplifiedEvaluator.java | 27 ++++ .../hbpg2/Hb2SimplifiedEvaluatorBase.java | 127 ++++++++++++++++++ .../chesslib/ai/eval/hbpg2/package-info.java | 1 + .../jchess/chesslib/uci/ChessLibEngine.java | 8 +- .../jchess/chesslib/ai/HBThreeMovesTest.java | 2 - 14 files changed, 507 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/package-info.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java index 8caafc0..5c37359 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java @@ -1,7 +1,10 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg; -import static com.fathzer.chess.utils.Pieces.*; -import static com.fathzer.jchess.chesslib.ai.eval.hbpg.HbSimplifiedEvaluatorBase.*; +import static com.fathzer.chess.utils.Pieces.KING; +import static com.fathzer.chess.utils.Pieces.PAWN; +import static com.fathzer.chess.utils.Pieces.ROOK; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg.HbSimplifiedEvaluatorBase.getPositionValue; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg.HbSimplifiedEvaluatorBase.getRawValue; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java index 1d0046c..276d5cd 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java @@ -3,7 +3,6 @@ import com.fathzer.games.ai.evaluation.StaticEvaluator; import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; -import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; import com.github.bhlangonijr.chesslib.Board; import com.github.bhlangonijr.chesslib.move.Move; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java index 0ef0c26..102da40 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java @@ -1,9 +1,8 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg; +import com.fathzer.chess.utils.Pieces; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.BoardExplorerBuilder; - -import com.fathzer.chess.utils.Pieces; import com.fathzer.games.MoveGenerator; abstract class HbSimplifiedEvaluatorBase> implements BoardExplorerBuilder { diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java new file mode 100644 index 0000000..c609422 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java @@ -0,0 +1,89 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import java.util.function.Supplier; + +import com.fathzer.chess.utils.adapters.MoveData; +import com.fathzer.games.MoveGenerator; +import com.fathzer.games.ai.evaluation.Evaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.games.util.Stack; + +/** An incremental implementation of the simplified evaluator described at https://www.chessprogramming.org/Simplified_Evaluation_Function + *
This only works with 8*8 games and exactly one king per Color. + */ +public abstract class Hb2AbstractIncrementalSimplifiedEvaluator> extends Hb2SimplifiedEvaluatorBase implements ZeroSumEvaluator, Supplier> { + private final Stack states; + private Hb2IncrementalState toCommit; + private MoveData moveData; + + /** Default constructor + */ + protected Hb2AbstractIncrementalSimplifiedEvaluator() { + this.states = new Stack<>(Hb2IncrementalState::new); + this.moveData = get(); + } + + /** Constructor. + * @param state The state to initialize the evaluator + */ + protected Hb2AbstractIncrementalSimplifiedEvaluator(Hb2IncrementalState state) { + this(); + Hb2IncrementalState other = new Hb2IncrementalState(); + state.copyTo(other); + states.set(state); + } + + + @Override + public Evaluator fork() { + return fork(states.get()); + } + + /** Creates a new instance initialized with current state that will become the initial state of created instance. + * @param state The initial state. + * @return a new evaluator of the same class as this, this the same view point, and initialized with the state. + */ + protected abstract Hb2AbstractIncrementalSimplifiedEvaluator fork(Hb2IncrementalState state); + + @Override + public void init(B board) { + states.clear(); + states.set(new Hb2IncrementalState(getExplorer(board))); + } + + @Override + public void prepareMove(B board, M move) { + if (moveData.update(move, board)) { + buildToCommit(); + toCommit.update(moveData); + } + } + + private void buildToCommit() { + final Hb2IncrementalState current = states.get(); + states.next(); + toCommit = states.get(); + states.previous(); + current.copyTo(toCommit); + } + + @Override + public void commitMove() { + states.next(); + states.set(toCommit); + } + + @Override + public void unmakeMove() { + states.previous(); + } + + @Override + public int evaluateAsWhite(B board) { + return states.get().evaluateAsWhite(); + } + + Hb2IncrementalState getState() { + return states.get(); + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java new file mode 100644 index 0000000..4b623c1 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -0,0 +1,65 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import static com.fathzer.chess.utils.Pieces.KING; + +import com.fathzer.chess.utils.adapters.BoardExplorer; + +/** The state of the evaluator. + */ +class Hb2BasicState extends Hb2FastPhaseDetector { + int points; + int whiteKingIndex; + int blackKingIndex; + int computedPhase; + + + Hb2BasicState() { + super(); + } + + void copyTo(Hb2BasicState other) { + super.copyTo(other); + other.points = points; + other.blackKingIndex = blackKingIndex; + other.whiteKingIndex = whiteKingIndex; + other.computedPhase = computedPhase; + } + + Hb2BasicState(BoardExplorer explorer) { + + this.points = 0; + this.computedPhase = 0; + do { + final int p = explorer.getPiece(); + add(p); + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind!=KING) { + int inc = Hb2SimplifiedEvaluatorBase.getRawValue(kind); + inc += Hb2SimplifiedEvaluatorBase.getPositionValue(kind, isBlack, index); + if (isBlack) { + points -= inc; + } else { + points += inc; + } + } else if (isBlack) { + this.blackKingIndex = index; + } else { + this.whiteKingIndex = index; + } + + computedPhase += Hb2Phase.getPhaseValue(kind); + } while (explorer.next()); + } + + + int evaluateAsWhite() { + // for the time being (29/03/2024) points are the same in Mg and Eg except for the king preferred squares + // but it's gonna change very soon + int phase = getPhaseForTaperedEval(computedPhase); + int evalMg = points + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); + int evalEg = points + Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); + return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java new file mode 100644 index 0000000..4cf848e --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java @@ -0,0 +1,29 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +/** A class that tracks the current phase. + */ +class Hb2FastPhaseDetector { + +// private long state; + + + void add(int piece) { +// state += PIECE_KIND_TO_VALUES[piece + KING]; + } + + void remove(int piece) { +// state -= PIECE_KIND_TO_VALUES[piece + KING]; + } + + int getPhaseForTaperedEval(int computedPhaseValue) { + return (Math.min(computedPhaseValue, Hb2Phase.PHASE_UPPER_BOUND)); + } + + + + + + void copyTo(Hb2FastPhaseDetector other) { +// other.state = state; + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java new file mode 100644 index 0000000..a33ac4c --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -0,0 +1,76 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import static com.fathzer.chess.utils.Pieces.KING; +import static com.fathzer.chess.utils.Pieces.PAWN; +import static com.fathzer.chess.utils.Pieces.ROOK; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getPositionValue; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValue; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.chess.utils.adapters.MoveData; + +/** The current state of a {@link Hb2AbstractIncrementalSimplifiedEvaluator} + */ +public class Hb2IncrementalState extends Hb2BasicState { + Hb2IncrementalState() { + super(); + } + + Hb2IncrementalState(BoardExplorer exp) { + super(exp); + } + + void update(MoveData move) { + points += getIncrement(move); + } + + private int getIncrement(MoveData move) { + final boolean isBlack = move.getMovingPiece()<0; + int moving = Math.abs(move.getMovingPiece()); + final int movingIndex = move.getMovingIndex(); + int inc; + if (moving==KING) { + // The position value of kings is not evaluated incrementally + int rookIndex = move.getCastlingRookIndex(); + if (rookIndex>=0) { + // It's a castling move, update rook positions values + inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); + } else { + inc = doCapture(isBlack, move); + } + // Update king's position + if (isBlack) { + this.blackKingIndex = move.getMovingDestination(); + } else { + this.whiteKingIndex = move.getMovingDestination(); + } + } else { + // Remove the position value of the moving piece + inc = - getPositionValue(moving, isBlack, movingIndex); + final int promoType = move.getPromotionType(); + if (promoType!=0) { + // If promotion, add raw value points, update phase + inc += getRawValue(promoType)-getRawValue(PAWN); + moving = promoType; + add(isBlack ? -promoType : promoType); + } + inc += doCapture(isBlack, move); + // Adds the position value of the + inc += getPositionValue(moving, isBlack, move.getMovingDestination()); + } + return isBlack ? -inc : +inc; + } + + private int doCapture(boolean isBlack, MoveData move) { + int captured = move.getCapturedType(); + if (captured!=0) { + // A piece was captured + // Update the phase detector + remove(isBlack ? captured : -captured); + // Then add its raw value and its position value + return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); + } else { + return 0; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java new file mode 100644 index 0000000..70ccd41 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java @@ -0,0 +1,39 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import com.fathzer.games.ai.evaluation.StaticEvaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.move.Move; + + +public class Hb2MyFirstEvaluator implements StaticEvaluator, ZeroSumEvaluator { + private final Hb2SimplifiedEvaluator ev = new Hb2SimplifiedEvaluator(); + + @Override + public int evaluateAsWhite(ChessLibMoveGenerator board) { + // Calculer l'évaluation de base + int baseEvaluation; +// synchronized (this) { // Alternative à la méthode fork + ev.init(board); + baseEvaluation = ev.evaluateAsWhite(board); +// } + // Tu peux ajouter ce qui concerne les chaines de pions, mauvais/bon fous, etc à l'évaluation de base ... + return baseEvaluation; + } + + @Override + public StaticEvaluator fork() { + // Attention : SimplifiedEvaluator n'est pas thread safe, ce qui est généralement le cas des évaluateurs statiques (d'où l'implémentation par défaut de fork qui renvoie this). + // Pour éviter les pb de threading, soit on crée un évaluateur par thread comme ici, soit l'usage du SimplifiedEvaluator doit être protégé par un synchronized (pas performant). + return new Hb2MyFirstEvaluator(); + } + + + public static void main(String[] args) { + // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer + ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(new Board()); + mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); + System.out.println(new Hb2MyFirstEvaluator().evaluate(mvg)); + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java new file mode 100644 index 0000000..125f670 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java @@ -0,0 +1,41 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +public class Hb2Phase { + + // Beware, what follows has nothing to do with com.fathzer.chess.utils.Pieces.VALUES, since the Queen is evaluated 9 instead of 10, in Pieces.VALUES + // Pieces.VALUE is useful only for comparing / ordering moves, by the way + protected static final int[] PHASE_VALUES = new int[] {0,1,3,3,5,10,0}; + + // The game phase will be an int value in the [0,64] interval + public static final int NB_INCR_PHASE = 64; // Pawns do not count. 3 for B and N, 5 for the R, 10 for the Q. White has therefore 32, and black likewise. Total = 64. + + // Very useful for the tapered evaluation + // Ethereal did not even think about it. But many others engines do. + // For example, If white or black or both have 2 queens for example, without an upper bound, the phase could exceed NB_INCR_PHASE, which would ruin the tapered evaluation + public static final int PHASE_UPPER_BOUND = NB_INCR_PHASE; + + + private int phase; + + public Hb2Phase(int computedPhaseValue) { + this.phase = computedPhaseValue; + } + + + public static int getPhaseValue(int indexPieceType) { + return(PHASE_VALUES[indexPieceType]); + } + + + public int getPhase() { + return phase; + } + + + public void setPhase(int phase) { + this.phase = phase; + } + + + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluator.java new file mode 100644 index 0000000..fdf1af9 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluator.java @@ -0,0 +1,27 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import com.fathzer.chess.utils.adapters.MoveData; +import com.fathzer.jchess.chesslib.ChessLibExplorerBuilder; +import com.fathzer.jchess.chesslib.ChessLibMoveData; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.move.Move; + +public class Hb2SimplifiedEvaluator extends Hb2AbstractIncrementalSimplifiedEvaluator implements ChessLibExplorerBuilder { + private Hb2SimplifiedEvaluator(Hb2IncrementalState state) { + super(state); + } + + public Hb2SimplifiedEvaluator() { + super(); + } + + @Override + public MoveData get() { + return new ChessLibMoveData(); + } + + @Override + protected Hb2AbstractIncrementalSimplifiedEvaluator fork(Hb2IncrementalState state) { + return new Hb2SimplifiedEvaluator(state); + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java new file mode 100644 index 0000000..3b3cd57 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java @@ -0,0 +1,127 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import com.fathzer.chess.utils.Pieces; +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.chess.utils.adapters.BoardExplorerBuilder; +import com.fathzer.games.MoveGenerator; + + +abstract class Hb2SimplifiedEvaluatorBase> implements BoardExplorerBuilder { + private static final int[] PIECE_VALUES = {0, 100, 320, 330, 500, 900, 20000}; + private static final int[] KING_MID_GAME_EVAL = new int[] { + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -20,-30,-30,-40,-40,-30,-30,-20, + -10,-20,-20,-20,-20,-20,-20,-10, + 20, 20, 0, 0, 0, 0, 20, 20, + 20, 30, 10, 0, 0, 10, 30, 20}; + + private static final int[] KING_END_GAME_EVAL = new int[] { + -50,-40,-30,-20,-20,-30,-40,-50, + -30,-20,-10, 0, 0,-10,-20,-30, + -30,-10, 20, 30, 30, 20,-10,-30, + -30,-10, 30, 40, 40, 30,-10,-30, + -30,-10, 30, 40, 40, 30,-10,-30, + -30,-10, 20, 30, 30, 20,-10,-30, + -30,-30, 0, 0, 0, 0,-30,-30, + -50,-30,-30,-30,-30,-30,-30,-50}; + + private static final int [][] PIECE_POSITION_VALUES = new int[][] { + // Just to have index equals to piece type codes + new int[0], + // PAWN + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 50, 50, 50, 50, 50, 50, 50, 50, + 10, 10, 20, 30, 30, 20, 10, 10, + 5, 5, 10, 25, 25, 10, 5, 5, + 0, 0, 0, 20, 20, 0, 0, 0, + 5, -5,-10, 0, 0,-10, -5, 5, + 5, 10, 10,-20,-20, 10, 10, 5, + 0, 0, 0, 0, 0, 0, 0, 0}, + // KNIGHT + new int[] { + -50,-40,-30,-30,-30,-30,-40,-50, + -40,-20, 0, 0, 0, 0,-20,-40, + -30, 0, 10, 15, 15, 10, 0,-30, + -30, 5, 15, 20, 20, 15, 5,-30, + -30, 0, 15, 20, 20, 15, 0,-30, + -30, 5, 10, 15, 15, 10, 5,-30, + -40,-20, 0, 5, 5, 0,-20,-40, + -50,-40,-30,-30,-30,-30,-40,-50}, + // BISHOP + new int[] { + -20,-10,-10,-10,-10,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 10, 10, 5, 0,-10, + -10, 5, 5, 10, 10, 5, 5,-10, + -10, 0, 10, 10, 10, 10, 0,-10, + -10, 10, 10, 10, 10, 10, 10,-10, + -10, 5, 0, 0, 0, 0, 5,-10, + -20,-10,-10,-10,-10,-10,-10,-20}, + // ROOK + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 10, 10, 10, 10, 10, 10, 5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + 0, 0, 0, 5, 5, 0, 0, 0}, + // QUEEN + new int[] { + -20,-10,-10, -5, -5,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 5, 5, 5, 0,-10, + -5, 0, 5, 5, 5, 5, 0, -5, + 0, 0, 5, 5, 5, 5, 0, -5, + -10, 5, 5, 5, 5, 5, 0,-10, + -10, 0, 5, 0, 0, 0, 0,-10, + -20,-10,-10, -5, -5,-10,-10,-20 + }}; + + Hb2SimplifiedEvaluatorBase() { + super(); + } + + static int getPositionValue(int type, boolean black, int index) { + return getPositionValue(PIECE_POSITION_VALUES[type], index, black); + } + + static int getRawValue(int type) { + return PIECE_VALUES[type]; + } + + + + static int getKingPositionsValueMg(int whiteIndex, int blackIndex) { + + return getPositionValue(KING_MID_GAME_EVAL, whiteIndex, false) - getPositionValue(KING_MID_GAME_EVAL, blackIndex, true); + } + + static int getKingPositionsValueEg(int whiteIndex, int blackIndex) { + + return getPositionValue(KING_END_GAME_EVAL, whiteIndex, false) - getPositionValue(KING_END_GAME_EVAL, blackIndex, true); + } + + private static int getPositionValue(int[] positionMap, int index, boolean black) { + if (black) { + final int row = 7 - index/8; + final int col = index%8; + index = row*8 + col; + } + return positionMap[index]; + } + + /** Gets the position value associated with a type of piece and an index. + * @param type The piece type as define in {@link Pieces} + * @param index The index of the piece on the board as defined in {@link BoardExplorer} + * @return an integer + */ + static int getPositionValue(int type, int index) { + return PIECE_POSITION_VALUES[type][index]; + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/package-info.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/package-info.java new file mode 100644 index 0000000..08be1cb --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/package-info.java @@ -0,0 +1 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index 381e0f0..c43fff7 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -28,6 +28,7 @@ import com.fathzer.jchess.chesslib.ai.eval.MyTinyEvaluator; import com.fathzer.jchess.chesslib.ai.eval.NaiveEvaluator; import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2MyFirstEvaluator; import com.fathzer.jchess.chesslib.time.RemainingMoveOracle; import com.fathzer.jchess.uci.UCIMove; import com.fathzer.jchess.uci.extended.Displayable; @@ -40,7 +41,12 @@ public class ChessLibEngine extends AbstractEngine implements TestableMoveGeneratorBuilder, Displayable { private static final List> EVALUATORS = - Arrays.asList(new EvaluatorConfiguration<>("hb",MyTinyEvaluator::new),new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); + Arrays.asList( + new EvaluatorConfiguration<>("hbfirst2",Hb2MyFirstEvaluator::new), + new EvaluatorConfiguration<>("hbtiny",MyTinyEvaluator::new), + new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new), + new EvaluatorConfiguration<>("naive",NaiveEvaluator::new) + ); private final MoveLibrary ownBook; diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java index 7aaecf8..6db2757 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java @@ -1,7 +1,5 @@ package com.fathzer.jchess.chesslib.ai; -import static org.junit.jupiter.api.Assertions.*; - import java.util.List; import org.junit.jupiter.api.Test; From 7fec468fb77476a9ca8a5457daff8f1f694c13e6 Mon Sep 17 00:00:00 2001 From: herve Date: Sat, 30 Mar 2024 07:19:09 +0100 Subject: [PATCH 18/55] =?UTF-8?q?Valeurs=20diff=C3=A9rentes=20pour=20les?= =?UTF-8?q?=20positions=20des=20pions=20en=20Mg=20et=20Eg.=20L'incr=C3=A9m?= =?UTF-8?q?ental=20concerne=20d=C3=A9sormais=20seulement=20le=20mat=C3=A9r?= =?UTF-8?q?iel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chesslib/ChessLibMoveGenerator.java | 2 +- ...bstractIncrementalSimplifiedEvaluator.java | 4 +- .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 17 +- .../ai/eval/hbpg2/Hb2IncrementalState.java | 20 +- .../hbpg2/Hb2SimplifiedEvaluatorBase.java | 186 +++++++++++++++++- 5 files changed, 208 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveGenerator.java b/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveGenerator.java index 58b7eb8..5a029d5 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveGenerator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveGenerator.java @@ -3,8 +3,8 @@ import java.util.List; import java.util.function.Function; -import com.fathzer.games.MoveGenerator; import com.fathzer.games.HashProvider; +import com.fathzer.games.MoveGenerator; import com.fathzer.games.Status; import com.fathzer.games.util.MoveList; import com.fathzer.games.util.SelectiveComparator; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java index c609422..3c1fdc3 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java @@ -7,6 +7,7 @@ import com.fathzer.games.ai.evaluation.Evaluator; import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; import com.fathzer.games.util.Stack; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; /** An incremental implementation of the simplified evaluator described at https://www.chessprogramming.org/Simplified_Evaluation_Function *
This only works with 8*8 games and exactly one king per Color. @@ -48,7 +49,8 @@ public Evaluator fork() { @Override public void init(B board) { states.clear(); - states.set(new Hb2IncrementalState(getExplorer(board))); + states.set(new Hb2IncrementalState(getExplorer(board), ((ChessLibMoveGenerator)board).getBoard())); + } @Override diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index 4b623c1..216b090 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -3,6 +3,7 @@ import static com.fathzer.chess.utils.Pieces.KING; import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.github.bhlangonijr.chesslib.Board; /** The state of the evaluator. */ @@ -11,6 +12,7 @@ class Hb2BasicState extends Hb2FastPhaseDetector { int whiteKingIndex; int blackKingIndex; int computedPhase; + Board board; Hb2BasicState() { @@ -23,10 +25,12 @@ void copyTo(Hb2BasicState other) { other.blackKingIndex = blackKingIndex; other.whiteKingIndex = whiteKingIndex; other.computedPhase = computedPhase; + other.board = board; + } - Hb2BasicState(BoardExplorer explorer) { - + Hb2BasicState(BoardExplorer explorer, Board board) { + this.board = board; this.points = 0; this.computedPhase = 0; do { @@ -37,7 +41,7 @@ void copyTo(Hb2BasicState other) { final boolean isBlack = p<0; if (kind!=KING) { int inc = Hb2SimplifiedEvaluatorBase.getRawValue(kind); - inc += Hb2SimplifiedEvaluatorBase.getPositionValue(kind, isBlack, index); +// inc += Hb2SimplifiedEvaluatorBase.getPositionValue(kind, isBlack, index); if (isBlack) { points -= inc; } else { @@ -57,9 +61,12 @@ void copyTo(Hb2BasicState other) { int evaluateAsWhite() { // for the time being (29/03/2024) points are the same in Mg and Eg except for the king preferred squares // but it's gonna change very soon + // points = material only, from now on. int phase = getPhaseForTaperedEval(computedPhase); - int evalMg = points + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); - int evalEg = points + Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); + int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); + int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); + int evalMg = points + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); + int evalEg = points + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); } } \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index a33ac4c..3e7d7ca 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -2,12 +2,12 @@ import static com.fathzer.chess.utils.Pieces.KING; import static com.fathzer.chess.utils.Pieces.PAWN; -import static com.fathzer.chess.utils.Pieces.ROOK; -import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getPositionValue; +//import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getPositionValue; import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValue; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; +import com.github.bhlangonijr.chesslib.Board; /** The current state of a {@link Hb2AbstractIncrementalSimplifiedEvaluator} */ @@ -16,8 +16,8 @@ public class Hb2IncrementalState extends Hb2BasicState { super(); } - Hb2IncrementalState(BoardExplorer exp) { - super(exp); + Hb2IncrementalState(BoardExplorer exp, Board board) { + super(exp, board); } void update(MoveData move) { @@ -28,13 +28,14 @@ private int getIncrement(MoveData move) { final boolean isBlack = move.getMovingPiece()<0; int moving = Math.abs(move.getMovingPiece()); final int movingIndex = move.getMovingIndex(); - int inc; +// int inc; + int inc = 0; if (moving==KING) { // The position value of kings is not evaluated incrementally int rookIndex = move.getCastlingRookIndex(); if (rookIndex>=0) { // It's a castling move, update rook positions values - inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); +// inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); } else { inc = doCapture(isBlack, move); } @@ -46,7 +47,7 @@ private int getIncrement(MoveData move) { } } else { // Remove the position value of the moving piece - inc = - getPositionValue(moving, isBlack, movingIndex); +// inc = - getPositionValue(moving, isBlack, movingIndex); final int promoType = move.getPromotionType(); if (promoType!=0) { // If promotion, add raw value points, update phase @@ -56,7 +57,7 @@ private int getIncrement(MoveData move) { } inc += doCapture(isBlack, move); // Adds the position value of the - inc += getPositionValue(moving, isBlack, move.getMovingDestination()); +// inc += getPositionValue(moving, isBlack, move.getMovingDestination()); } return isBlack ? -inc : +inc; } @@ -68,7 +69,8 @@ private int doCapture(boolean isBlack, MoveData move) { // Update the phase detector remove(isBlack ? captured : -captured); // Then add its raw value and its position value - return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); +// return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); + return getRawValue(captured); } else { return 0; } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java index 3b3cd57..162edd9 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java @@ -1,9 +1,13 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg2; +import static com.fathzer.chess.utils.Pieces.KING; + import com.fathzer.chess.utils.Pieces; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.BoardExplorerBuilder; import com.fathzer.games.MoveGenerator; +import com.fathzer.jchess.chesslib.ChessLibBoardExplorer; +import com.github.bhlangonijr.chesslib.Board; abstract class Hb2SimplifiedEvaluatorBase> implements BoardExplorerBuilder { @@ -28,7 +32,62 @@ abstract class Hb2SimplifiedEvaluatorBase> impleme -30,-30, 0, 0, 0, 0,-30,-30, -50,-30,-30,-30,-30,-30,-30,-50}; - private static final int [][] PIECE_POSITION_VALUES = new int[][] { +// private static final int [][] PIECE_POSITION_VALUES = new int[][] { +// // Just to have index equals to piece type codes +// new int[0], +// // PAWN +// new int[] { +// 0, 0, 0, 0, 0, 0, 0, 0, +// 50, 50, 50, 50, 50, 50, 50, 50, +// 10, 10, 20, 30, 30, 20, 10, 10, +// 5, 5, 10, 25, 25, 10, 5, 5, +// 0, 0, 0, 20, 20, 0, 0, 0, +// 5, -5,-10, 0, 0,-10, -5, 5, +// 5, 10, 10,-20,-20, 10, 10, 5, +// 0, 0, 0, 0, 0, 0, 0, 0}, +// // KNIGHT +// new int[] { +// -50,-40,-30,-30,-30,-30,-40,-50, +// -40,-20, 0, 0, 0, 0,-20,-40, +// -30, 0, 10, 15, 15, 10, 0,-30, +// -30, 5, 15, 20, 20, 15, 5,-30, +// -30, 0, 15, 20, 20, 15, 0,-30, +// -30, 5, 10, 15, 15, 10, 5,-30, +// -40,-20, 0, 5, 5, 0,-20,-40, +// -50,-40,-30,-30,-30,-30,-40,-50}, +// // BISHOP +// new int[] { +// -20,-10,-10,-10,-10,-10,-10,-20, +// -10, 0, 0, 0, 0, 0, 0,-10, +// -10, 0, 5, 10, 10, 5, 0,-10, +// -10, 5, 5, 10, 10, 5, 5,-10, +// -10, 0, 10, 10, 10, 10, 0,-10, +// -10, 10, 10, 10, 10, 10, 10,-10, +// -10, 5, 0, 0, 0, 0, 5,-10, +// -20,-10,-10,-10,-10,-10,-10,-20}, +// // ROOK +// new int[] { +// 0, 0, 0, 0, 0, 0, 0, 0, +// 5, 10, 10, 10, 10, 10, 10, 5, +// -5, 0, 0, 0, 0, 0, 0, -5, +// -5, 0, 0, 0, 0, 0, 0, -5, +// -5, 0, 0, 0, 0, 0, 0, -5, +// -5, 0, 0, 0, 0, 0, 0, -5, +// -5, 0, 0, 0, 0, 0, 0, -5, +// 0, 0, 0, 5, 5, 0, 0, 0}, +// // QUEEN +// new int[] { +// -20,-10,-10, -5, -5,-10,-10,-20, +// -10, 0, 0, 0, 0, 0, 0,-10, +// -10, 0, 5, 5, 5, 5, 0,-10, +// -5, 0, 5, 5, 5, 5, 0, -5, +// 0, 0, 5, 5, 5, 5, 0, -5, +// -10, 5, 5, 5, 5, 5, 0,-10, +// -10, 0, 5, 0, 0, 0, 0,-10, +// -20,-10,-10, -5, -5,-10,-10,-20 +// }}; + + private static final int [][] PIECE_POSITION_VALUES_MG = new int[][] { // Just to have index equals to piece type codes new int[0], // PAWN @@ -83,12 +142,75 @@ abstract class Hb2SimplifiedEvaluatorBase> impleme -20,-10,-10, -5, -5,-10,-10,-20 }}; + private static final int [][] PIECE_POSITION_VALUES_EG= new int[][] { + // Just to have index equals to piece type codes + new int[0], + // PAWN + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 90, 90, 90, 90, 90, 90, 90, 90, + 30, 30, 40, 60, 60, 40, 30, 30, + 10, 10, 20, 40, 40, 20, 10, 10, + 0, 0, 0, 20, 20, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 5, + 5, 10, 10,-20,-20, 10, 10, 5, + 0, 0, 0, 0, 0, 0, 0, 0}, + // KNIGHT + new int[] { + -50,-40,-30,-30,-30,-30,-40,-50, + -40,-20, 0, 0, 0, 0,-20,-40, + -30, 0, 10, 15, 15, 10, 0,-30, + -30, 5, 15, 20, 20, 15, 5,-30, + -30, 0, 15, 20, 20, 15, 0,-30, + -30, 5, 10, 15, 15, 10, 5,-30, + -40,-20, 0, 5, 5, 0,-20,-40, + -50,-40,-30,-30,-30,-30,-40,-50}, + // BISHOP + new int[] { + -20,-10,-10,-10,-10,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 10, 10, 5, 0,-10, + -10, 5, 5, 10, 10, 5, 5,-10, + -10, 0, 10, 10, 10, 10, 0,-10, + -10, 10, 10, 10, 10, 10, 10,-10, + -10, 5, 0, 0, 0, 0, 5,-10, + -20,-10,-10,-10,-10,-10,-10,-20}, + // ROOK + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 10, 10, 10, 10, 10, 10, 5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + 0, 0, 0, 5, 5, 0, 0, 0}, + // QUEEN + new int[] { + -20,-10,-10, -5, -5,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 5, 5, 5, 0,-10, + -5, 0, 5, 5, 5, 5, 0, -5, + 0, 0, 5, 5, 5, 5, 0, -5, + -10, 5, 5, 5, 5, 5, 0,-10, + -10, 0, 5, 0, 0, 0, 0,-10, + -20,-10,-10, -5, -5,-10,-10,-20 + }}; + Hb2SimplifiedEvaluatorBase() { super(); } - static int getPositionValue(int type, boolean black, int index) { - return getPositionValue(PIECE_POSITION_VALUES[type], index, black); +// static int getPositionValue(int type, boolean black, int index) { +// return getPositionValue(PIECE_POSITION_VALUES[type], index, black); +// } +// + static int getPositionValueMg(int type, boolean black, int index) { + return getPositionValue(PIECE_POSITION_VALUES_MG[type], index, black); + } + + static int getPositionValueEg(int type, boolean black, int index) { + return getPositionValue(PIECE_POSITION_VALUES_EG[type], index, black); } static int getRawValue(int type) { @@ -121,7 +243,61 @@ private static int getPositionValue(int[] positionMap, int index, boolean black) * @param index The index of the piece on the board as defined in {@link BoardExplorer} * @return an integer */ - static int getPositionValue(int type, int index) { - return PIECE_POSITION_VALUES[type][index]; +// static int getPositionValue(int type, int index) { +// return PIECE_POSITION_VALUES[type][index]; +// } + + static int getPositionValueMg(Board board) { +// BoardExplorer explorer = getExplorer(board); + int pointsPosMg = 0; + BoardExplorer explorer = new ChessLibBoardExplorer(board); + do { + final int p = explorer.getPiece(); + + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind!=KING) { + + int inc = getPositionValueMg(kind, isBlack, index); + if (isBlack) { + pointsPosMg -= inc; + } else { + pointsPosMg += inc; + } + } + + + } while (explorer.next()); + + return (pointsPosMg); + + } + + static int getPositionValueEg(Board board) { +// BoardExplorer explorer = getExplorer(board); + int pointsPosEg = 0; + BoardExplorer explorer = new ChessLibBoardExplorer(board); + do { + final int p = explorer.getPiece(); + + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind!=KING) { + + int inc = getPositionValueEg(kind, isBlack, index); + if (isBlack) { + pointsPosEg -= inc; + } else { + pointsPosEg += inc; + } + } + + + } while (explorer.next()); + + return (pointsPosEg); + } } From a804e85fd176f4b22c0696fae04b10a65169b3b1 Mon Sep 17 00:00:00 2001 From: herve Date: Sat, 30 Mar 2024 07:24:35 +0100 Subject: [PATCH 19/55] oubli du push s'il y a quelques minutes --- .../chesslib/ChessLibBoardExplorer.java | 69 ++++++++++++++++++- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ChessLibBoardExplorer.java b/src/main/java/com/fathzer/jchess/chesslib/ChessLibBoardExplorer.java index 9c1ca61..15a2129 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ChessLibBoardExplorer.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ChessLibBoardExplorer.java @@ -1,6 +1,69 @@ package com.fathzer.jchess.chesslib; -import static com.github.bhlangonijr.chesslib.Square.*; +import static com.github.bhlangonijr.chesslib.Square.A1; +import static com.github.bhlangonijr.chesslib.Square.A2; +import static com.github.bhlangonijr.chesslib.Square.A3; +import static com.github.bhlangonijr.chesslib.Square.A4; +import static com.github.bhlangonijr.chesslib.Square.A5; +import static com.github.bhlangonijr.chesslib.Square.A6; +import static com.github.bhlangonijr.chesslib.Square.A7; +import static com.github.bhlangonijr.chesslib.Square.A8; +import static com.github.bhlangonijr.chesslib.Square.B1; +import static com.github.bhlangonijr.chesslib.Square.B2; +import static com.github.bhlangonijr.chesslib.Square.B3; +import static com.github.bhlangonijr.chesslib.Square.B4; +import static com.github.bhlangonijr.chesslib.Square.B5; +import static com.github.bhlangonijr.chesslib.Square.B6; +import static com.github.bhlangonijr.chesslib.Square.B7; +import static com.github.bhlangonijr.chesslib.Square.B8; +import static com.github.bhlangonijr.chesslib.Square.C1; +import static com.github.bhlangonijr.chesslib.Square.C2; +import static com.github.bhlangonijr.chesslib.Square.C3; +import static com.github.bhlangonijr.chesslib.Square.C4; +import static com.github.bhlangonijr.chesslib.Square.C5; +import static com.github.bhlangonijr.chesslib.Square.C6; +import static com.github.bhlangonijr.chesslib.Square.C7; +import static com.github.bhlangonijr.chesslib.Square.C8; +import static com.github.bhlangonijr.chesslib.Square.D1; +import static com.github.bhlangonijr.chesslib.Square.D2; +import static com.github.bhlangonijr.chesslib.Square.D3; +import static com.github.bhlangonijr.chesslib.Square.D4; +import static com.github.bhlangonijr.chesslib.Square.D5; +import static com.github.bhlangonijr.chesslib.Square.D6; +import static com.github.bhlangonijr.chesslib.Square.D7; +import static com.github.bhlangonijr.chesslib.Square.D8; +import static com.github.bhlangonijr.chesslib.Square.E1; +import static com.github.bhlangonijr.chesslib.Square.E2; +import static com.github.bhlangonijr.chesslib.Square.E3; +import static com.github.bhlangonijr.chesslib.Square.E4; +import static com.github.bhlangonijr.chesslib.Square.E5; +import static com.github.bhlangonijr.chesslib.Square.E6; +import static com.github.bhlangonijr.chesslib.Square.E7; +import static com.github.bhlangonijr.chesslib.Square.E8; +import static com.github.bhlangonijr.chesslib.Square.F1; +import static com.github.bhlangonijr.chesslib.Square.F2; +import static com.github.bhlangonijr.chesslib.Square.F3; +import static com.github.bhlangonijr.chesslib.Square.F4; +import static com.github.bhlangonijr.chesslib.Square.F5; +import static com.github.bhlangonijr.chesslib.Square.F6; +import static com.github.bhlangonijr.chesslib.Square.F7; +import static com.github.bhlangonijr.chesslib.Square.F8; +import static com.github.bhlangonijr.chesslib.Square.G1; +import static com.github.bhlangonijr.chesslib.Square.G2; +import static com.github.bhlangonijr.chesslib.Square.G3; +import static com.github.bhlangonijr.chesslib.Square.G4; +import static com.github.bhlangonijr.chesslib.Square.G5; +import static com.github.bhlangonijr.chesslib.Square.G6; +import static com.github.bhlangonijr.chesslib.Square.G7; +import static com.github.bhlangonijr.chesslib.Square.G8; +import static com.github.bhlangonijr.chesslib.Square.H1; +import static com.github.bhlangonijr.chesslib.Square.H2; +import static com.github.bhlangonijr.chesslib.Square.H3; +import static com.github.bhlangonijr.chesslib.Square.H4; +import static com.github.bhlangonijr.chesslib.Square.H5; +import static com.github.bhlangonijr.chesslib.Square.H6; +import static com.github.bhlangonijr.chesslib.Square.H7; +import static com.github.bhlangonijr.chesslib.Square.H8; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.github.bhlangonijr.chesslib.Board; @@ -9,7 +72,7 @@ import com.github.bhlangonijr.chesslib.Side; import com.github.bhlangonijr.chesslib.Square; -class ChessLibBoardExplorer implements BoardExplorer { +public class ChessLibBoardExplorer implements BoardExplorer { static final Square[] SQUARES; static { @@ -29,7 +92,7 @@ class ChessLibBoardExplorer implements BoardExplorer { private int index; private int piece; - ChessLibBoardExplorer(Board board) { + public ChessLibBoardExplorer(Board board) { this.board = board; this.index = -1; next(); From fec2d1d19c8a8bb63a5a6981e56a590a1310269d Mon Sep 17 00:00:00 2001 From: herve Date: Sat, 13 Apr 2024 11:34:18 +0200 Subject: [PATCH 20/55] =?UTF-8?q?Bon,=20commit=20du=20Hb2MyFirstEvaluator,?= =?UTF-8?q?=20il=20a=20gagn=C3=A9=20contre=20le=20SimplifiedEvaluator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jchess/chesslib/ChessLibMoveData.java | 6 ++-- .../ai/eval/hbpg2/Hb2MyFirstEvaluator.java | 5 +-- .../lichess/AbstractDefaultOpenings.java | 2 +- .../jchess/chesslib/ChessLibMoveDataTest.java | 8 +++-- .../chesslib/ChessLibMoveGeneratorTest.java | 34 ++++++++++++++++--- .../fathzer/jchess/chesslib/PerfTTest.java | 3 +- .../chesslib/ai/BasicMoveComparatorTest.java | 7 ++-- .../jchess/chesslib/ai/MinimaxEngineTest.java | 21 +++++++++--- .../chesslib/ai/StrictMoveEvaluatorTest.java | 15 +++++--- .../chesslib/ai/TranspositionTableTest.java | 2 +- .../chesslib/ai/eval/BasicEvaluatorTest.java | 18 +++++++--- 11 files changed, 90 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveData.java b/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveData.java index acda9d2..43254be 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveData.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveData.java @@ -1,7 +1,9 @@ package com.fathzer.jchess.chesslib; -import static com.github.bhlangonijr.chesslib.PieceType.*; -import static com.github.bhlangonijr.chesslib.CastleRight.*; +import static com.github.bhlangonijr.chesslib.CastleRight.KING_SIDE; +import static com.github.bhlangonijr.chesslib.CastleRight.QUEEN_SIDE; +import static com.github.bhlangonijr.chesslib.PieceType.KING; +import static com.github.bhlangonijr.chesslib.PieceType.PAWN; import com.fathzer.chess.utils.adapters.MoveData; import com.github.bhlangonijr.chesslib.Piece; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java index 70ccd41..b11e6af 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java @@ -3,19 +3,20 @@ import com.fathzer.games.ai.evaluation.StaticEvaluator; import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.NaiveEvaluator; import com.github.bhlangonijr.chesslib.Board; import com.github.bhlangonijr.chesslib.move.Move; public class Hb2MyFirstEvaluator implements StaticEvaluator, ZeroSumEvaluator { private final Hb2SimplifiedEvaluator ev = new Hb2SimplifiedEvaluator(); - + private final NaiveEvaluator enNaive = new NaiveEvaluator(); @Override public int evaluateAsWhite(ChessLibMoveGenerator board) { // Calculer l'évaluation de base int baseEvaluation; // synchronized (this) { // Alternative à la méthode fork - ev.init(board); + ev.init(board); // On n'utilise pas le côté incréemantal baseEvaluation = ev.evaluateAsWhite(board); // } // Tu peux ajouter ce qui concerne les chaines de pions, mauvais/bon fous, etc à l'évaluation de base ... diff --git a/src/main/java/com/fathzer/jchess/lichess/AbstractDefaultOpenings.java b/src/main/java/com/fathzer/jchess/lichess/AbstractDefaultOpenings.java index beec026..32f85f4 100644 --- a/src/main/java/com/fathzer/jchess/lichess/AbstractDefaultOpenings.java +++ b/src/main/java/com/fathzer/jchess/lichess/AbstractDefaultOpenings.java @@ -12,8 +12,8 @@ import org.json.JSONObject; import org.json.JSONTokener; -import com.fathzer.games.movelibrary.AbstractMoveLibrary; import com.fathzer.games.MoveGenerator; +import com.fathzer.games.movelibrary.AbstractMoveLibrary; public abstract class AbstractDefaultOpenings> extends AbstractMoveLibrary { private final JSONObject db; diff --git a/src/test/java/com/fathzer/jchess/chesslib/ChessLibMoveDataTest.java b/src/test/java/com/fathzer/jchess/chesslib/ChessLibMoveDataTest.java index aada8a7..da7c55c 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ChessLibMoveDataTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ChessLibMoveDataTest.java @@ -1,8 +1,10 @@ package com.fathzer.jchess.chesslib; -import static org.junit.jupiter.api.Assertions.*; - -import static com.github.bhlangonijr.chesslib.Square.*; +import static com.github.bhlangonijr.chesslib.Square.A7; +import static com.github.bhlangonijr.chesslib.Square.A8; +import static com.github.bhlangonijr.chesslib.Square.B8; +import static com.github.bhlangonijr.chesslib.Square.H1; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/fathzer/jchess/chesslib/ChessLibMoveGeneratorTest.java b/src/test/java/com/fathzer/jchess/chesslib/ChessLibMoveGeneratorTest.java index b72a685..38ef437 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ChessLibMoveGeneratorTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ChessLibMoveGeneratorTest.java @@ -1,10 +1,34 @@ package com.fathzer.jchess.chesslib; -import static org.junit.jupiter.api.Assertions.*; - -import static com.github.bhlangonijr.chesslib.Square.*; - -import static com.fathzer.games.MoveGenerator.MoveConfidence.*; +import static com.fathzer.games.MoveGenerator.MoveConfidence.UNSAFE; +import static com.github.bhlangonijr.chesslib.Square.A5; +import static com.github.bhlangonijr.chesslib.Square.A7; +import static com.github.bhlangonijr.chesslib.Square.A8; +import static com.github.bhlangonijr.chesslib.Square.B6; +import static com.github.bhlangonijr.chesslib.Square.B7; +import static com.github.bhlangonijr.chesslib.Square.B8; +import static com.github.bhlangonijr.chesslib.Square.C7; +import static com.github.bhlangonijr.chesslib.Square.D1; +import static com.github.bhlangonijr.chesslib.Square.D3; +import static com.github.bhlangonijr.chesslib.Square.D4; +import static com.github.bhlangonijr.chesslib.Square.D5; +import static com.github.bhlangonijr.chesslib.Square.D6; +import static com.github.bhlangonijr.chesslib.Square.E1; +import static com.github.bhlangonijr.chesslib.Square.E2; +import static com.github.bhlangonijr.chesslib.Square.E8; +import static com.github.bhlangonijr.chesslib.Square.F2; +import static com.github.bhlangonijr.chesslib.Square.F3; +import static com.github.bhlangonijr.chesslib.Square.F6; +import static com.github.bhlangonijr.chesslib.Square.F7; +import static com.github.bhlangonijr.chesslib.Square.G1; +import static com.github.bhlangonijr.chesslib.Square.G6; +import static com.github.bhlangonijr.chesslib.Square.G7; +import static com.github.bhlangonijr.chesslib.Square.G8; +import static com.github.bhlangonijr.chesslib.Square.H5; +import static com.github.bhlangonijr.chesslib.Square.H6; +import static com.github.bhlangonijr.chesslib.Square.H7; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; diff --git a/src/test/java/com/fathzer/jchess/chesslib/PerfTTest.java b/src/test/java/com/fathzer/jchess/chesslib/PerfTTest.java index 9db9b50..e245c73 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/PerfTTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/PerfTTest.java @@ -1,6 +1,7 @@ package com.fathzer.jchess.chesslib; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.InputStream; diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/BasicMoveComparatorTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/BasicMoveComparatorTest.java index d583324..5cab582 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ai/BasicMoveComparatorTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/BasicMoveComparatorTest.java @@ -1,11 +1,12 @@ package com.fathzer.jchess.chesslib.ai; -import static org.junit.jupiter.api.Assertions.*; +import static com.fathzer.jchess.chesslib.ai.MinimaxEngineTest.fromFEN; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; -import static com.fathzer.jchess.chesslib.ai.MinimaxEngineTest.fromFEN; - import org.junit.jupiter.api.Test; import com.fathzer.games.util.MoveList; diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/MinimaxEngineTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/MinimaxEngineTest.java index 9b147df..132180d 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ai/MinimaxEngineTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/MinimaxEngineTest.java @@ -1,8 +1,21 @@ package com.fathzer.jchess.chesslib.ai; -import static org.junit.jupiter.api.Assertions.*; - -import static com.github.bhlangonijr.chesslib.Square.*; +import static com.github.bhlangonijr.chesslib.Square.A1; +import static com.github.bhlangonijr.chesslib.Square.B3; +import static com.github.bhlangonijr.chesslib.Square.C2; +import static com.github.bhlangonijr.chesslib.Square.C3; +import static com.github.bhlangonijr.chesslib.Square.D1; +import static com.github.bhlangonijr.chesslib.Square.D7; +import static com.github.bhlangonijr.chesslib.Square.F2; +import static com.github.bhlangonijr.chesslib.Square.F3; +import static com.github.bhlangonijr.chesslib.Square.F4; +import static com.github.bhlangonijr.chesslib.Square.G1; +import static com.github.bhlangonijr.chesslib.Square.G6; +import static com.github.bhlangonijr.chesslib.Square.H1; +import static com.github.bhlangonijr.chesslib.Square.H7; +import static com.github.bhlangonijr.chesslib.Square.H8; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.Collection; @@ -18,8 +31,8 @@ import com.fathzer.games.ai.evaluation.EvaluatedMove; import com.fathzer.games.ai.evaluation.Evaluation; import com.fathzer.games.ai.evaluation.Evaluation.Type; -import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; import com.fathzer.games.ai.evaluation.Evaluator; +import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; import com.fathzer.games.util.SelectiveComparator; import com.fathzer.games.util.exec.ExecutionContext; import com.fathzer.games.util.exec.SingleThreadContext; diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/StrictMoveEvaluatorTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/StrictMoveEvaluatorTest.java index a127778..15f477a 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ai/StrictMoveEvaluatorTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/StrictMoveEvaluatorTest.java @@ -1,14 +1,21 @@ package com.fathzer.jchess.chesslib.ai; -import static org.junit.jupiter.api.Assertions.*; +import static com.fathzer.jchess.chesslib.ai.MinimaxEngineTest.fromFEN; +import static com.github.bhlangonijr.chesslib.Square.A6; +import static com.github.bhlangonijr.chesslib.Square.A7; +import static com.github.bhlangonijr.chesslib.Square.A8; +import static com.github.bhlangonijr.chesslib.Square.B8; +import static com.github.bhlangonijr.chesslib.Square.G8; +import static com.github.bhlangonijr.chesslib.Square.H1; +import static com.github.bhlangonijr.chesslib.Square.H2; +import static com.github.bhlangonijr.chesslib.Square.H6; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -import static com.fathzer.jchess.chesslib.ai.MinimaxEngineTest.fromFEN; -import static com.github.bhlangonijr.chesslib.Square.*; - import org.junit.jupiter.api.Test; import com.fathzer.games.util.MoveList; diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/TranspositionTableTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/TranspositionTableTest.java index 0bdd2ac..cdd95ff 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ai/TranspositionTableTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/TranspositionTableTest.java @@ -1,6 +1,6 @@ package com.fathzer.jchess.chesslib.ai; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/eval/BasicEvaluatorTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/eval/BasicEvaluatorTest.java index 1c3f321..ea17d2a 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ai/eval/BasicEvaluatorTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/eval/BasicEvaluatorTest.java @@ -1,10 +1,18 @@ package com.fathzer.jchess.chesslib.ai.eval; -import static org.junit.jupiter.api.Assertions.*; - -import static com.github.bhlangonijr.chesslib.Square.*; - -import static com.fathzer.games.MoveGenerator.MoveConfidence.*; +import static com.fathzer.games.MoveGenerator.MoveConfidence.UNSAFE; +import static com.github.bhlangonijr.chesslib.Square.A6; +import static com.github.bhlangonijr.chesslib.Square.B1; +import static com.github.bhlangonijr.chesslib.Square.B3; +import static com.github.bhlangonijr.chesslib.Square.B5; +import static com.github.bhlangonijr.chesslib.Square.C7; +import static com.github.bhlangonijr.chesslib.Square.D6; +import static com.github.bhlangonijr.chesslib.Square.E8; +import static com.github.bhlangonijr.chesslib.Square.F4; +import static com.github.bhlangonijr.chesslib.Square.F8; +import static com.github.bhlangonijr.chesslib.Square.G8; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; From a7528cca2be987efe6cd618befc315f6f28ca621 Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 11:03:22 +0100 Subject: [PATCH 21/55] An example of calling engine to have three best moves with their pv --- .../jchess/chesslib/ai/HBThreeMovesTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java new file mode 100644 index 0000000..7aaecf8 --- /dev/null +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java @@ -0,0 +1,34 @@ +package com.fathzer.jchess.chesslib.ai; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fathzer.games.ai.evaluation.EvaluatedMove; +import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.uci.ChessLibEngine; +import com.github.bhlangonijr.chesslib.move.Move; + +class HBThreeMovesTest { + + @Test + void test() { + final int depth = 6; + final int bestMoveCount = 3; + final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(SimplifiedEvaluator::new, depth); + engine.getDeepeningPolicy().setSize(bestMoveCount); + final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)); + System.out.println(moves); + for (int i=0;i<3;i++) { + EvaluatedMove move = moves.get(i); + List principalVariation = move.getPrincipalVariation(); + System.out.println(move+" -> "+principalVariation); + } + } + +} From 021efebc7f1bb6e28a7d18125d4939cec517feb3 Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 25 Jan 2024 12:12:47 +0100 Subject: [PATCH 22/55] =?UTF-8?q?squelette=20d'=C3=A9valuateur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 16 ++++++++++++++++ .../jchess/chesslib/uci/ChessLibEngine.java | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java new file mode 100644 index 0000000..952ac9c --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -0,0 +1,16 @@ +package com.fathzer.jchess.chesslib.ai.eval; + +import com.fathzer.games.ai.evaluation.StaticEvaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.move.Move; + +public class MyTinyEvaluator implements StaticEvaluator, ZeroSumEvaluator { + + @Override + public int evaluateAsWhite(ChessLibMoveGenerator board) { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index 7395907..a605d4e 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -27,6 +27,7 @@ import com.fathzer.jchess.chesslib.ai.ChessLibDeepeningPolicy; import com.fathzer.jchess.chesslib.ai.DefaultLogger; import com.fathzer.jchess.chesslib.ai.TT; +import com.fathzer.jchess.chesslib.ai.eval.MyTinyEvaluator; import com.fathzer.jchess.chesslib.ai.eval.NaiveEvaluator; import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; import com.fathzer.jchess.chesslib.time.RemainingMoveOracle; @@ -40,7 +41,8 @@ import com.github.bhlangonijr.chesslib.move.Move; public class ChessLibEngine extends AbstractEngine implements TestableMoveGeneratorBuilder, Displayable { - private static final List> EVALUATORS = Arrays.asList(new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); + private static final List> EVALUATORS = + Arrays.asList(new EvaluatorConfiguration<>("hb",MyTinyEvaluator::new),new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); private final MoveLibrary ownBook; From d99572c97a14cf961ee8f34c50fdf271f2a4268c Mon Sep 17 00:00:00 2001 From: Fathzer Date: Thu, 7 Mar 2024 19:24:17 +0100 Subject: [PATCH 23/55] MyTinyEvaluator => example of static reuse of SimplifiedEvaluator --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java index 952ac9c..079ce41 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -3,14 +3,25 @@ import com.fathzer.games.ai.evaluation.StaticEvaluator; import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.Board; import com.github.bhlangonijr.chesslib.move.Move; public class MyTinyEvaluator implements StaticEvaluator, ZeroSumEvaluator { + private final SimplifiedEvaluator ev = new SimplifiedEvaluator(); @Override public int evaluateAsWhite(ChessLibMoveGenerator board) { - // TODO Auto-generated method stub - return 0; + // Calculer l'évaluation de base + ev.init(board); + int baseEvaluation = ev.evaluate(board); + // Tu peux ajouter ce qui concerne les chaines de pions, mauvais/bon fous, etc à l'évaluation de base ... + return baseEvaluation; } + public static void main(String[] args) { + // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer + ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(new Board()); + mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); + System.out.println(new MyTinyEvaluator().evaluate(mvg)); + } } From 1a8ef7d0a9cdaad5e845095204592ed190743416 Mon Sep 17 00:00:00 2001 From: Fathzer Date: Sat, 9 Mar 2024 15:53:51 +0100 Subject: [PATCH 24/55] Fixes MyTinyEvaluator hang + search deepen on forced moves --- .../jchess/chesslib/ai/eval/MyTinyEvaluator.java | 15 +++++++++++++-- .../jchess/chesslib/uci/ChessLibEngine.java | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java index 079ce41..a66ca21 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/MyTinyEvaluator.java @@ -12,11 +12,22 @@ public class MyTinyEvaluator implements StaticEvaluator fork() { + // Attention : SimplifiedEvaluator n'est pas thread safe, ce qui est généralement le cas des évaluateurs statiques (d'où l'implémentation par défaut de fork qui renvoie this). + // Pour éviter les pb de threading, soit on crée un évaluateur par thread comme ici, soit l'usage du SimplifiedEvaluator doit être protégé par un synchronized (pas performant). + return new MyTinyEvaluator(); + } + public static void main(String[] args) { // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index a605d4e..da3dd8f 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -136,6 +136,7 @@ protected Negamax buildAi(ExecutionContext1 ? 2 : 1); engine.getDeepeningPolicy().setMaxTime(60000); + engine.getDeepeningPolicy().setDeepenOnForced(false); return engine; } From 51b97a270102dd19ac8dec69474ca713c0956cff Mon Sep 17 00:00:00 2001 From: herve Date: Sat, 16 Mar 2024 09:53:29 +0100 Subject: [PATCH 25/55] =?UTF-8?q?Classes=20pour=20ma=20premi=C3=A8re=20fon?= =?UTF-8?q?ction=20d'=C3=A9valuation=20s'appuyant=20sur=20SimplifiedEvalua?= =?UTF-8?q?tor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...bstractIncrementalSimplifiedEvaluator.java | 89 +++++++++++++ .../chesslib/ai/eval/hbpg/HbBasicState.java | 52 ++++++++ .../ai/eval/hbpg/HbFastPhaseDetector.java | 64 ++++++++++ .../ai/eval/hbpg/HbIncrementalState.java | 73 +++++++++++ .../ai/eval/hbpg/HbMyFirstEvaluator.java | 40 ++++++ .../jchess/chesslib/ai/eval/hbpg/HbPhase.java | 13 ++ .../ai/eval/hbpg/HbSimplifiedEvaluator.java | 27 ++++ .../eval/hbpg/HbSimplifiedEvaluatorBase.java | 120 ++++++++++++++++++ .../chesslib/ai/eval/hbpg/package-info.java | 1 + 9 files changed, 479 insertions(+) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java new file mode 100644 index 0000000..bb291b9 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java @@ -0,0 +1,89 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import java.util.function.Supplier; + +import com.fathzer.chess.utils.adapters.MoveData; +import com.fathzer.games.MoveGenerator; +import com.fathzer.games.ai.evaluation.Evaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.games.util.Stack; + +/** An incremental implementation of the simplified evaluator described at https://www.chessprogramming.org/Simplified_Evaluation_Function + *
This only works with 8*8 games and exactly one king per Color. + */ +public abstract class HbAbstractIncrementalSimplifiedEvaluator> extends HbSimplifiedEvaluatorBase implements ZeroSumEvaluator, Supplier> { + private final Stack states; + private HbIncrementalState toCommit; + private MoveData moveData; + + /** Default constructor + */ + protected HbAbstractIncrementalSimplifiedEvaluator() { + this.states = new Stack<>(HbIncrementalState::new); + this.moveData = get(); + } + + /** Constructor. + * @param state The state to initialize the evaluator + */ + protected HbAbstractIncrementalSimplifiedEvaluator(HbIncrementalState state) { + this(); + HbIncrementalState other = new HbIncrementalState(); + state.copyTo(other); + states.set(state); + } + + + @Override + public Evaluator fork() { + return fork(states.get()); + } + + /** Creates a new instance initialized with current state that will become the initial state of created instance. + * @param state The initial state. + * @return a new evaluator of the same class as this, this the same view point, and initialized with the state. + */ + protected abstract HbAbstractIncrementalSimplifiedEvaluator fork(HbIncrementalState state); + + @Override + public void init(B board) { + states.clear(); + states.set(new HbIncrementalState(getExplorer(board))); + } + + @Override + public void prepareMove(B board, M move) { + if (moveData.update(move, board)) { + buildToCommit(); + toCommit.update(moveData); + } + } + + private void buildToCommit() { + final HbIncrementalState current = states.get(); + states.next(); + toCommit = states.get(); + states.previous(); + current.copyTo(toCommit); + } + + @Override + public void commitMove() { + states.next(); + states.set(toCommit); + } + + @Override + public void unmakeMove() { + states.previous(); + } + + @Override + public int evaluateAsWhite(B board) { + return states.get().evaluateAsWhite(); + } + + HbIncrementalState getState() { + return states.get(); + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java new file mode 100644 index 0000000..ecd3e71 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java @@ -0,0 +1,52 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import static com.fathzer.chess.utils.Pieces.KING; + +import com.fathzer.chess.utils.adapters.BoardExplorer; + +/** The state of the evaluator. + */ +class HbBasicState extends HbFastPhaseDetector { + int points; + int whiteKingIndex; + int blackKingIndex; + + HbBasicState() { + super(); + } + + void copyTo(HbBasicState other) { + super.copyTo(other); + other.points = points; + other.blackKingIndex = blackKingIndex; + other.whiteKingIndex = whiteKingIndex; + } + + HbBasicState(BoardExplorer explorer) { + this.points = 0; + do { + final int p = explorer.getPiece(); + add(p); + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind!=KING) { + int inc = HbSimplifiedEvaluatorBase.getRawValue(kind); + inc += HbSimplifiedEvaluatorBase.getPositionValue(kind, isBlack, index); + if (isBlack) { + points -= inc; + } else { + points += inc; + } + } else if (isBlack) { + this.blackKingIndex = index; + } else { + this.whiteKingIndex = index; + } + } while (explorer.next()); + } + + int evaluateAsWhite() { + return points + HbSimplifiedEvaluatorBase.getKingPositionsValue(whiteKingIndex, blackKingIndex, getPhase()); + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java new file mode 100644 index 0000000..14beee7 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java @@ -0,0 +1,64 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import static com.fathzer.chess.utils.Pieces.KING; + +/** A class that tracks the current phase. + */ +class HbFastPhaseDetector { + private static final long BLACK_QUEEN_VALUE = 0x01L; + private static final long BLACK_QUEEN_MASK = 0xFFL; + private static final long WHITE_QUEEN_VALUE = 0x0100L; + private static final long WHITE_QUEEN_MASK = 0xFF00L; + private static final long BLACK_ROOK_VALUE = 0x010000L; + private static final long BLACK_ROOK_MASK = 0xFF0000L; + private static final long WHITE_ROOK_VALUE = 0x01000000L; + private static final long WHITE_ROOK_MASK = 0xFF000000L; + private static final long BLACK_MINOR_VALUE = 0x0100000000L; + private static final long BLACK_MINOR_MASK = 0xFF00000000L; + private static final long WHITE_MINOR_VALUE = 0x010000000000L; + private static final long WHITE_MINOR_MASK = 0xFF0000000000L; + + private static final long[] PIECE_KIND_TO_VALUES = new long[] {0L, BLACK_QUEEN_VALUE, BLACK_ROOK_VALUE, BLACK_MINOR_VALUE, BLACK_MINOR_VALUE, 0L, 0L, 0L, WHITE_MINOR_VALUE, WHITE_MINOR_VALUE, WHITE_ROOK_VALUE, WHITE_QUEEN_VALUE, 0L}; + + private long state; + + void add(int piece) { + state += PIECE_KIND_TO_VALUES[piece + KING]; + } + + void remove(int piece) { + state -= PIECE_KIND_TO_VALUES[piece + KING]; + } + + HbPhase getPhase() { + final boolean whiteQueen = (state & WHITE_QUEEN_MASK) != 0L; + final boolean blackQueen = (state & BLACK_QUEEN_MASK) != 0L; + if (!blackQueen && !whiteQueen) { + return HbPhase.END_GAME; + } + if ((blackQueen && (hasBlackRook() || hasManyBlackMinor())) || (whiteQueen && (hasWhiteRook() || hasManyWhiteMinor()))) { + return HbPhase.MIDDLE_GAME; + } + return HbPhase.END_GAME; + } + + boolean hasWhiteRook() { + return (state & WHITE_ROOK_MASK) != 0; + } + + boolean hasBlackRook() { + return (state & BLACK_ROOK_MASK) != 0; + } + + boolean hasManyBlackMinor() { + return (state & BLACK_MINOR_MASK) > BLACK_MINOR_VALUE; + } + + boolean hasManyWhiteMinor() { + return (state & WHITE_MINOR_MASK) > WHITE_MINOR_VALUE; + } + + void copyTo(HbFastPhaseDetector other) { + other.state = state; + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java new file mode 100644 index 0000000..8caafc0 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java @@ -0,0 +1,73 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import static com.fathzer.chess.utils.Pieces.*; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg.HbSimplifiedEvaluatorBase.*; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.chess.utils.adapters.MoveData; + +/** The current state of a {@link HbAbstractIncrementalSimplifiedEvaluator} + */ +public class HbIncrementalState extends HbBasicState { + HbIncrementalState() { + super(); + } + + HbIncrementalState(BoardExplorer exp) { + super(exp); + } + + void update(MoveData move) { + points += getIncrement(move); + } + + private int getIncrement(MoveData move) { + final boolean isBlack = move.getMovingPiece()<0; + int moving = Math.abs(move.getMovingPiece()); + final int movingIndex = move.getMovingIndex(); + int inc; + if (moving==KING) { + // The position value of kings is not evaluated incrementally + int rookIndex = move.getCastlingRookIndex(); + if (rookIndex>=0) { + // It's a castling move, update rook positions values + inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); + } else { + inc = doCapture(isBlack, move); + } + // Update king's position + if (isBlack) { + this.blackKingIndex = move.getMovingDestination(); + } else { + this.whiteKingIndex = move.getMovingDestination(); + } + } else { + // Remove the position value of the moving piece + inc = - getPositionValue(moving, isBlack, movingIndex); + final int promoType = move.getPromotionType(); + if (promoType!=0) { + // If promotion, add raw value points, update phase + inc += getRawValue(promoType)-getRawValue(PAWN); + moving = promoType; + add(isBlack ? -promoType : promoType); + } + inc += doCapture(isBlack, move); + // Adds the position value of the + inc += getPositionValue(moving, isBlack, move.getMovingDestination()); + } + return isBlack ? -inc : +inc; + } + + private int doCapture(boolean isBlack, MoveData move) { + int captured = move.getCapturedType(); + if (captured!=0) { + // A piece was captured + // Update the phase detector + remove(isBlack ? captured : -captured); + // Then add its raw value and its position value + return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); + } else { + return 0; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java new file mode 100644 index 0000000..dc7c43a --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java @@ -0,0 +1,40 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import com.fathzer.games.ai.evaluation.StaticEvaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.move.Move; + + +public class HbMyFirstEvaluator implements StaticEvaluator, ZeroSumEvaluator { + private final SimplifiedEvaluator ev = new SimplifiedEvaluator(); + + @Override + public int evaluateAsWhite(ChessLibMoveGenerator board) { + // Calculer l'évaluation de base + int baseEvaluation; +// synchronized (this) { // Alternative à la méthode fork + ev.init(board); + baseEvaluation = ev.evaluateAsWhite(board); +// } + // Tu peux ajouter ce qui concerne les chaines de pions, mauvais/bon fous, etc à l'évaluation de base ... + return baseEvaluation; + } + + @Override + public StaticEvaluator fork() { + // Attention : SimplifiedEvaluator n'est pas thread safe, ce qui est généralement le cas des évaluateurs statiques (d'où l'implémentation par défaut de fork qui renvoie this). + // Pour éviter les pb de threading, soit on crée un évaluateur par thread comme ici, soit l'usage du SimplifiedEvaluator doit être protégé par un synchronized (pas performant). + return new HbMyFirstEvaluator(); + } + + + public static void main(String[] args) { + // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer + ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(new Board()); + mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); + System.out.println(new HbMyFirstEvaluator().evaluate(mvg)); + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java new file mode 100644 index 0000000..d75ca9d --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java @@ -0,0 +1,13 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +/** The phases of a game. + *
There's only two phases in the simplified evaluator, and not three as we could expect. + * The idea is, in the opening phase, the evaluation function should be replaced by an opening library, the middle game starts when the position + * is no more in the library. + */ +enum HbPhase { + /** Middle of the game.*/ + MIDDLE_GAME, + /** End of the game */ + END_GAME +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java new file mode 100644 index 0000000..7dbb502 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java @@ -0,0 +1,27 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import com.fathzer.chess.utils.adapters.MoveData; +import com.fathzer.jchess.chesslib.ChessLibExplorerBuilder; +import com.fathzer.jchess.chesslib.ChessLibMoveData; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.move.Move; + +public class HbSimplifiedEvaluator extends HbAbstractIncrementalSimplifiedEvaluator implements ChessLibExplorerBuilder { + private HbSimplifiedEvaluator(HbIncrementalState state) { + super(state); + } + + public HbSimplifiedEvaluator() { + super(); + } + + @Override + public MoveData get() { + return new ChessLibMoveData(); + } + + @Override + protected HbAbstractIncrementalSimplifiedEvaluator fork(HbIncrementalState state) { + return new HbSimplifiedEvaluator(state); + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java new file mode 100644 index 0000000..0ef0c26 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java @@ -0,0 +1,120 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.chess.utils.adapters.BoardExplorerBuilder; + +import com.fathzer.chess.utils.Pieces; +import com.fathzer.games.MoveGenerator; + +abstract class HbSimplifiedEvaluatorBase> implements BoardExplorerBuilder { + private static final int[] PIECE_VALUES = {0, 100, 320, 330, 500, 900, 20000}; + private static final int[] KING_MID_GAME_EVAL = new int[] { + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -20,-30,-30,-40,-40,-30,-30,-20, + -10,-20,-20,-20,-20,-20,-20,-10, + 20, 20, 0, 0, 0, 0, 20, 20, + 20, 30, 10, 0, 0, 10, 30, 20}; + + private static final int[] KING_END_GAME_EVAL = new int[] { + -50,-40,-30,-20,-20,-30,-40,-50, + -30,-20,-10, 0, 0,-10,-20,-30, + -30,-10, 20, 30, 30, 20,-10,-30, + -30,-10, 30, 40, 40, 30,-10,-30, + -30,-10, 30, 40, 40, 30,-10,-30, + -30,-10, 20, 30, 30, 20,-10,-30, + -30,-30, 0, 0, 0, 0,-30,-30, + -50,-30,-30,-30,-30,-30,-30,-50}; + + private static final int [][] PIECE_POSITION_VALUES = new int[][] { + // Just to have index equals to piece type codes + new int[0], + // PAWN + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 50, 50, 50, 50, 50, 50, 50, 50, + 10, 10, 20, 30, 30, 20, 10, 10, + 5, 5, 10, 25, 25, 10, 5, 5, + 0, 0, 0, 20, 20, 0, 0, 0, + 5, -5,-10, 0, 0,-10, -5, 5, + 5, 10, 10,-20,-20, 10, 10, 5, + 0, 0, 0, 0, 0, 0, 0, 0}, + // KNIGHT + new int[] { + -50,-40,-30,-30,-30,-30,-40,-50, + -40,-20, 0, 0, 0, 0,-20,-40, + -30, 0, 10, 15, 15, 10, 0,-30, + -30, 5, 15, 20, 20, 15, 5,-30, + -30, 0, 15, 20, 20, 15, 0,-30, + -30, 5, 10, 15, 15, 10, 5,-30, + -40,-20, 0, 5, 5, 0,-20,-40, + -50,-40,-30,-30,-30,-30,-40,-50}, + // BISHOP + new int[] { + -20,-10,-10,-10,-10,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 10, 10, 5, 0,-10, + -10, 5, 5, 10, 10, 5, 5,-10, + -10, 0, 10, 10, 10, 10, 0,-10, + -10, 10, 10, 10, 10, 10, 10,-10, + -10, 5, 0, 0, 0, 0, 5,-10, + -20,-10,-10,-10,-10,-10,-10,-20}, + // ROOK + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 10, 10, 10, 10, 10, 10, 5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + 0, 0, 0, 5, 5, 0, 0, 0}, + // QUEEN + new int[] { + -20,-10,-10, -5, -5,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 5, 5, 5, 0,-10, + -5, 0, 5, 5, 5, 5, 0, -5, + 0, 0, 5, 5, 5, 5, 0, -5, + -10, 5, 5, 5, 5, 5, 0,-10, + -10, 0, 5, 0, 0, 0, 0,-10, + -20,-10,-10, -5, -5,-10,-10,-20 + }}; + + HbSimplifiedEvaluatorBase() { + super(); + } + + static int getPositionValue(int type, boolean black, int index) { + return getPositionValue(PIECE_POSITION_VALUES[type], index, black); + } + + static int getRawValue(int type) { + return PIECE_VALUES[type]; + } + + static int getKingPositionsValue(int whiteIndex, int blackIndex, HbPhase phase) { + final int[] kingMap = phase==HbPhase.MIDDLE_GAME ? KING_MID_GAME_EVAL : KING_END_GAME_EVAL; + return getPositionValue(kingMap, whiteIndex, false) - getPositionValue(kingMap, blackIndex, true); + } + + private static int getPositionValue(int[] positionMap, int index, boolean black) { + if (black) { + final int row = 7 - index/8; + final int col = index%8; + index = row*8 + col; + } + return positionMap[index]; + } + + /** Gets the position value associated with a type of piece and an index. + * @param type The piece type as define in {@link Pieces} + * @param index The index of the piece on the board as defined in {@link BoardExplorer} + * @return an integer + */ + static int getPositionValue(int type, int index) { + return PIECE_POSITION_VALUES[type][index]; + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java new file mode 100644 index 0000000..327ea90 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java @@ -0,0 +1 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg; \ No newline at end of file From a1928c4636a1f58914bf1746da50a99ff184b573 Mon Sep 17 00:00:00 2001 From: herve Date: Tue, 26 Mar 2024 07:29:05 +0100 Subject: [PATCH 26/55] HbMyFirstEvaluator uses Hb Classes, from now on. Correction. --- .../jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java index dc7c43a..1d0046c 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java @@ -9,7 +9,7 @@ public class HbMyFirstEvaluator implements StaticEvaluator, ZeroSumEvaluator { - private final SimplifiedEvaluator ev = new SimplifiedEvaluator(); + private final HbSimplifiedEvaluator ev = new HbSimplifiedEvaluator(); @Override public int evaluateAsWhite(ChessLibMoveGenerator board) { From d32a00b47172cc5a5dfffef3d78779d04a79bea0 Mon Sep 17 00:00:00 2001 From: herve Date: Fri, 29 Mar 2024 08:38:16 +0100 Subject: [PATCH 27/55] Hb2MyFirstEvaluator: the beginning. Compared to the SimplifiedEvaluator the evaluation function is tapered (scale = 64) --- .../ai/eval/hbpg/HbIncrementalState.java | 7 +- .../ai/eval/hbpg/HbMyFirstEvaluator.java | 1 - .../eval/hbpg/HbSimplifiedEvaluatorBase.java | 3 +- ...bstractIncrementalSimplifiedEvaluator.java | 89 ++++++++++++ .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 65 +++++++++ .../ai/eval/hbpg2/Hb2FastPhaseDetector.java | 29 ++++ .../ai/eval/hbpg2/Hb2IncrementalState.java | 76 +++++++++++ .../ai/eval/hbpg2/Hb2MyFirstEvaluator.java | 39 ++++++ .../chesslib/ai/eval/hbpg2/Hb2Phase.java | 41 ++++++ .../ai/eval/hbpg2/Hb2SimplifiedEvaluator.java | 27 ++++ .../hbpg2/Hb2SimplifiedEvaluatorBase.java | 127 ++++++++++++++++++ .../chesslib/ai/eval/hbpg2/package-info.java | 1 + .../jchess/chesslib/uci/ChessLibEngine.java | 8 +- .../jchess/chesslib/ai/HBThreeMovesTest.java | 2 - 14 files changed, 507 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluator.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/package-info.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java index 8caafc0..5c37359 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java @@ -1,7 +1,10 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg; -import static com.fathzer.chess.utils.Pieces.*; -import static com.fathzer.jchess.chesslib.ai.eval.hbpg.HbSimplifiedEvaluatorBase.*; +import static com.fathzer.chess.utils.Pieces.KING; +import static com.fathzer.chess.utils.Pieces.PAWN; +import static com.fathzer.chess.utils.Pieces.ROOK; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg.HbSimplifiedEvaluatorBase.getPositionValue; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg.HbSimplifiedEvaluatorBase.getRawValue; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java index 1d0046c..276d5cd 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java @@ -3,7 +3,6 @@ import com.fathzer.games.ai.evaluation.StaticEvaluator; import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; -import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; import com.github.bhlangonijr.chesslib.Board; import com.github.bhlangonijr.chesslib.move.Move; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java index 0ef0c26..102da40 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java @@ -1,9 +1,8 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg; +import com.fathzer.chess.utils.Pieces; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.BoardExplorerBuilder; - -import com.fathzer.chess.utils.Pieces; import com.fathzer.games.MoveGenerator; abstract class HbSimplifiedEvaluatorBase> implements BoardExplorerBuilder { diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java new file mode 100644 index 0000000..c609422 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java @@ -0,0 +1,89 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import java.util.function.Supplier; + +import com.fathzer.chess.utils.adapters.MoveData; +import com.fathzer.games.MoveGenerator; +import com.fathzer.games.ai.evaluation.Evaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.games.util.Stack; + +/** An incremental implementation of the simplified evaluator described at https://www.chessprogramming.org/Simplified_Evaluation_Function + *
This only works with 8*8 games and exactly one king per Color. + */ +public abstract class Hb2AbstractIncrementalSimplifiedEvaluator> extends Hb2SimplifiedEvaluatorBase implements ZeroSumEvaluator, Supplier> { + private final Stack states; + private Hb2IncrementalState toCommit; + private MoveData moveData; + + /** Default constructor + */ + protected Hb2AbstractIncrementalSimplifiedEvaluator() { + this.states = new Stack<>(Hb2IncrementalState::new); + this.moveData = get(); + } + + /** Constructor. + * @param state The state to initialize the evaluator + */ + protected Hb2AbstractIncrementalSimplifiedEvaluator(Hb2IncrementalState state) { + this(); + Hb2IncrementalState other = new Hb2IncrementalState(); + state.copyTo(other); + states.set(state); + } + + + @Override + public Evaluator fork() { + return fork(states.get()); + } + + /** Creates a new instance initialized with current state that will become the initial state of created instance. + * @param state The initial state. + * @return a new evaluator of the same class as this, this the same view point, and initialized with the state. + */ + protected abstract Hb2AbstractIncrementalSimplifiedEvaluator fork(Hb2IncrementalState state); + + @Override + public void init(B board) { + states.clear(); + states.set(new Hb2IncrementalState(getExplorer(board))); + } + + @Override + public void prepareMove(B board, M move) { + if (moveData.update(move, board)) { + buildToCommit(); + toCommit.update(moveData); + } + } + + private void buildToCommit() { + final Hb2IncrementalState current = states.get(); + states.next(); + toCommit = states.get(); + states.previous(); + current.copyTo(toCommit); + } + + @Override + public void commitMove() { + states.next(); + states.set(toCommit); + } + + @Override + public void unmakeMove() { + states.previous(); + } + + @Override + public int evaluateAsWhite(B board) { + return states.get().evaluateAsWhite(); + } + + Hb2IncrementalState getState() { + return states.get(); + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java new file mode 100644 index 0000000..4b623c1 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -0,0 +1,65 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import static com.fathzer.chess.utils.Pieces.KING; + +import com.fathzer.chess.utils.adapters.BoardExplorer; + +/** The state of the evaluator. + */ +class Hb2BasicState extends Hb2FastPhaseDetector { + int points; + int whiteKingIndex; + int blackKingIndex; + int computedPhase; + + + Hb2BasicState() { + super(); + } + + void copyTo(Hb2BasicState other) { + super.copyTo(other); + other.points = points; + other.blackKingIndex = blackKingIndex; + other.whiteKingIndex = whiteKingIndex; + other.computedPhase = computedPhase; + } + + Hb2BasicState(BoardExplorer explorer) { + + this.points = 0; + this.computedPhase = 0; + do { + final int p = explorer.getPiece(); + add(p); + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind!=KING) { + int inc = Hb2SimplifiedEvaluatorBase.getRawValue(kind); + inc += Hb2SimplifiedEvaluatorBase.getPositionValue(kind, isBlack, index); + if (isBlack) { + points -= inc; + } else { + points += inc; + } + } else if (isBlack) { + this.blackKingIndex = index; + } else { + this.whiteKingIndex = index; + } + + computedPhase += Hb2Phase.getPhaseValue(kind); + } while (explorer.next()); + } + + + int evaluateAsWhite() { + // for the time being (29/03/2024) points are the same in Mg and Eg except for the king preferred squares + // but it's gonna change very soon + int phase = getPhaseForTaperedEval(computedPhase); + int evalMg = points + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); + int evalEg = points + Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); + return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java new file mode 100644 index 0000000..4cf848e --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java @@ -0,0 +1,29 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +/** A class that tracks the current phase. + */ +class Hb2FastPhaseDetector { + +// private long state; + + + void add(int piece) { +// state += PIECE_KIND_TO_VALUES[piece + KING]; + } + + void remove(int piece) { +// state -= PIECE_KIND_TO_VALUES[piece + KING]; + } + + int getPhaseForTaperedEval(int computedPhaseValue) { + return (Math.min(computedPhaseValue, Hb2Phase.PHASE_UPPER_BOUND)); + } + + + + + + void copyTo(Hb2FastPhaseDetector other) { +// other.state = state; + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java new file mode 100644 index 0000000..a33ac4c --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -0,0 +1,76 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import static com.fathzer.chess.utils.Pieces.KING; +import static com.fathzer.chess.utils.Pieces.PAWN; +import static com.fathzer.chess.utils.Pieces.ROOK; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getPositionValue; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValue; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.chess.utils.adapters.MoveData; + +/** The current state of a {@link Hb2AbstractIncrementalSimplifiedEvaluator} + */ +public class Hb2IncrementalState extends Hb2BasicState { + Hb2IncrementalState() { + super(); + } + + Hb2IncrementalState(BoardExplorer exp) { + super(exp); + } + + void update(MoveData move) { + points += getIncrement(move); + } + + private int getIncrement(MoveData move) { + final boolean isBlack = move.getMovingPiece()<0; + int moving = Math.abs(move.getMovingPiece()); + final int movingIndex = move.getMovingIndex(); + int inc; + if (moving==KING) { + // The position value of kings is not evaluated incrementally + int rookIndex = move.getCastlingRookIndex(); + if (rookIndex>=0) { + // It's a castling move, update rook positions values + inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); + } else { + inc = doCapture(isBlack, move); + } + // Update king's position + if (isBlack) { + this.blackKingIndex = move.getMovingDestination(); + } else { + this.whiteKingIndex = move.getMovingDestination(); + } + } else { + // Remove the position value of the moving piece + inc = - getPositionValue(moving, isBlack, movingIndex); + final int promoType = move.getPromotionType(); + if (promoType!=0) { + // If promotion, add raw value points, update phase + inc += getRawValue(promoType)-getRawValue(PAWN); + moving = promoType; + add(isBlack ? -promoType : promoType); + } + inc += doCapture(isBlack, move); + // Adds the position value of the + inc += getPositionValue(moving, isBlack, move.getMovingDestination()); + } + return isBlack ? -inc : +inc; + } + + private int doCapture(boolean isBlack, MoveData move) { + int captured = move.getCapturedType(); + if (captured!=0) { + // A piece was captured + // Update the phase detector + remove(isBlack ? captured : -captured); + // Then add its raw value and its position value + return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); + } else { + return 0; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java new file mode 100644 index 0000000..70ccd41 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java @@ -0,0 +1,39 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import com.fathzer.games.ai.evaluation.StaticEvaluator; +import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.move.Move; + + +public class Hb2MyFirstEvaluator implements StaticEvaluator, ZeroSumEvaluator { + private final Hb2SimplifiedEvaluator ev = new Hb2SimplifiedEvaluator(); + + @Override + public int evaluateAsWhite(ChessLibMoveGenerator board) { + // Calculer l'évaluation de base + int baseEvaluation; +// synchronized (this) { // Alternative à la méthode fork + ev.init(board); + baseEvaluation = ev.evaluateAsWhite(board); +// } + // Tu peux ajouter ce qui concerne les chaines de pions, mauvais/bon fous, etc à l'évaluation de base ... + return baseEvaluation; + } + + @Override + public StaticEvaluator fork() { + // Attention : SimplifiedEvaluator n'est pas thread safe, ce qui est généralement le cas des évaluateurs statiques (d'où l'implémentation par défaut de fork qui renvoie this). + // Pour éviter les pb de threading, soit on crée un évaluateur par thread comme ici, soit l'usage du SimplifiedEvaluator doit être protégé par un synchronized (pas performant). + return new Hb2MyFirstEvaluator(); + } + + + public static void main(String[] args) { + // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer + ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(new Board()); + mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); + System.out.println(new Hb2MyFirstEvaluator().evaluate(mvg)); + } +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java new file mode 100644 index 0000000..125f670 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java @@ -0,0 +1,41 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +public class Hb2Phase { + + // Beware, what follows has nothing to do with com.fathzer.chess.utils.Pieces.VALUES, since the Queen is evaluated 9 instead of 10, in Pieces.VALUES + // Pieces.VALUE is useful only for comparing / ordering moves, by the way + protected static final int[] PHASE_VALUES = new int[] {0,1,3,3,5,10,0}; + + // The game phase will be an int value in the [0,64] interval + public static final int NB_INCR_PHASE = 64; // Pawns do not count. 3 for B and N, 5 for the R, 10 for the Q. White has therefore 32, and black likewise. Total = 64. + + // Very useful for the tapered evaluation + // Ethereal did not even think about it. But many others engines do. + // For example, If white or black or both have 2 queens for example, without an upper bound, the phase could exceed NB_INCR_PHASE, which would ruin the tapered evaluation + public static final int PHASE_UPPER_BOUND = NB_INCR_PHASE; + + + private int phase; + + public Hb2Phase(int computedPhaseValue) { + this.phase = computedPhaseValue; + } + + + public static int getPhaseValue(int indexPieceType) { + return(PHASE_VALUES[indexPieceType]); + } + + + public int getPhase() { + return phase; + } + + + public void setPhase(int phase) { + this.phase = phase; + } + + + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluator.java new file mode 100644 index 0000000..fdf1af9 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluator.java @@ -0,0 +1,27 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import com.fathzer.chess.utils.adapters.MoveData; +import com.fathzer.jchess.chesslib.ChessLibExplorerBuilder; +import com.fathzer.jchess.chesslib.ChessLibMoveData; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.move.Move; + +public class Hb2SimplifiedEvaluator extends Hb2AbstractIncrementalSimplifiedEvaluator implements ChessLibExplorerBuilder { + private Hb2SimplifiedEvaluator(Hb2IncrementalState state) { + super(state); + } + + public Hb2SimplifiedEvaluator() { + super(); + } + + @Override + public MoveData get() { + return new ChessLibMoveData(); + } + + @Override + protected Hb2AbstractIncrementalSimplifiedEvaluator fork(Hb2IncrementalState state) { + return new Hb2SimplifiedEvaluator(state); + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java new file mode 100644 index 0000000..3b3cd57 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java @@ -0,0 +1,127 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import com.fathzer.chess.utils.Pieces; +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.chess.utils.adapters.BoardExplorerBuilder; +import com.fathzer.games.MoveGenerator; + + +abstract class Hb2SimplifiedEvaluatorBase> implements BoardExplorerBuilder { + private static final int[] PIECE_VALUES = {0, 100, 320, 330, 500, 900, 20000}; + private static final int[] KING_MID_GAME_EVAL = new int[] { + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -30,-40,-40,-50,-50,-40,-40,-30, + -20,-30,-30,-40,-40,-30,-30,-20, + -10,-20,-20,-20,-20,-20,-20,-10, + 20, 20, 0, 0, 0, 0, 20, 20, + 20, 30, 10, 0, 0, 10, 30, 20}; + + private static final int[] KING_END_GAME_EVAL = new int[] { + -50,-40,-30,-20,-20,-30,-40,-50, + -30,-20,-10, 0, 0,-10,-20,-30, + -30,-10, 20, 30, 30, 20,-10,-30, + -30,-10, 30, 40, 40, 30,-10,-30, + -30,-10, 30, 40, 40, 30,-10,-30, + -30,-10, 20, 30, 30, 20,-10,-30, + -30,-30, 0, 0, 0, 0,-30,-30, + -50,-30,-30,-30,-30,-30,-30,-50}; + + private static final int [][] PIECE_POSITION_VALUES = new int[][] { + // Just to have index equals to piece type codes + new int[0], + // PAWN + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 50, 50, 50, 50, 50, 50, 50, 50, + 10, 10, 20, 30, 30, 20, 10, 10, + 5, 5, 10, 25, 25, 10, 5, 5, + 0, 0, 0, 20, 20, 0, 0, 0, + 5, -5,-10, 0, 0,-10, -5, 5, + 5, 10, 10,-20,-20, 10, 10, 5, + 0, 0, 0, 0, 0, 0, 0, 0}, + // KNIGHT + new int[] { + -50,-40,-30,-30,-30,-30,-40,-50, + -40,-20, 0, 0, 0, 0,-20,-40, + -30, 0, 10, 15, 15, 10, 0,-30, + -30, 5, 15, 20, 20, 15, 5,-30, + -30, 0, 15, 20, 20, 15, 0,-30, + -30, 5, 10, 15, 15, 10, 5,-30, + -40,-20, 0, 5, 5, 0,-20,-40, + -50,-40,-30,-30,-30,-30,-40,-50}, + // BISHOP + new int[] { + -20,-10,-10,-10,-10,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 10, 10, 5, 0,-10, + -10, 5, 5, 10, 10, 5, 5,-10, + -10, 0, 10, 10, 10, 10, 0,-10, + -10, 10, 10, 10, 10, 10, 10,-10, + -10, 5, 0, 0, 0, 0, 5,-10, + -20,-10,-10,-10,-10,-10,-10,-20}, + // ROOK + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 10, 10, 10, 10, 10, 10, 5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + 0, 0, 0, 5, 5, 0, 0, 0}, + // QUEEN + new int[] { + -20,-10,-10, -5, -5,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 5, 5, 5, 0,-10, + -5, 0, 5, 5, 5, 5, 0, -5, + 0, 0, 5, 5, 5, 5, 0, -5, + -10, 5, 5, 5, 5, 5, 0,-10, + -10, 0, 5, 0, 0, 0, 0,-10, + -20,-10,-10, -5, -5,-10,-10,-20 + }}; + + Hb2SimplifiedEvaluatorBase() { + super(); + } + + static int getPositionValue(int type, boolean black, int index) { + return getPositionValue(PIECE_POSITION_VALUES[type], index, black); + } + + static int getRawValue(int type) { + return PIECE_VALUES[type]; + } + + + + static int getKingPositionsValueMg(int whiteIndex, int blackIndex) { + + return getPositionValue(KING_MID_GAME_EVAL, whiteIndex, false) - getPositionValue(KING_MID_GAME_EVAL, blackIndex, true); + } + + static int getKingPositionsValueEg(int whiteIndex, int blackIndex) { + + return getPositionValue(KING_END_GAME_EVAL, whiteIndex, false) - getPositionValue(KING_END_GAME_EVAL, blackIndex, true); + } + + private static int getPositionValue(int[] positionMap, int index, boolean black) { + if (black) { + final int row = 7 - index/8; + final int col = index%8; + index = row*8 + col; + } + return positionMap[index]; + } + + /** Gets the position value associated with a type of piece and an index. + * @param type The piece type as define in {@link Pieces} + * @param index The index of the piece on the board as defined in {@link BoardExplorer} + * @return an integer + */ + static int getPositionValue(int type, int index) { + return PIECE_POSITION_VALUES[type][index]; + } +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/package-info.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/package-info.java new file mode 100644 index 0000000..08be1cb --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/package-info.java @@ -0,0 +1 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index da3dd8f..926049f 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -30,6 +30,7 @@ import com.fathzer.jchess.chesslib.ai.eval.MyTinyEvaluator; import com.fathzer.jchess.chesslib.ai.eval.NaiveEvaluator; import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2MyFirstEvaluator; import com.fathzer.jchess.chesslib.time.RemainingMoveOracle; import com.fathzer.jchess.uci.UCIMove; import com.fathzer.jchess.uci.extended.Displayable; @@ -42,7 +43,12 @@ public class ChessLibEngine extends AbstractEngine implements TestableMoveGeneratorBuilder, Displayable { private static final List> EVALUATORS = - Arrays.asList(new EvaluatorConfiguration<>("hb",MyTinyEvaluator::new),new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new),new EvaluatorConfiguration<>("naive",NaiveEvaluator::new)); + Arrays.asList( + new EvaluatorConfiguration<>("hbfirst2",Hb2MyFirstEvaluator::new), + new EvaluatorConfiguration<>("hbtiny",MyTinyEvaluator::new), + new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new), + new EvaluatorConfiguration<>("naive",NaiveEvaluator::new) + ); private final MoveLibrary ownBook; diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java index 7aaecf8..6db2757 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java @@ -1,7 +1,5 @@ package com.fathzer.jchess.chesslib.ai; -import static org.junit.jupiter.api.Assertions.*; - import java.util.List; import org.junit.jupiter.api.Test; From 9522cc2bd22c41a1928bbb3f1ab14234ca139ea2 Mon Sep 17 00:00:00 2001 From: herve Date: Sat, 30 Mar 2024 07:19:09 +0100 Subject: [PATCH 28/55] =?UTF-8?q?Valeurs=20diff=C3=A9rentes=20pour=20les?= =?UTF-8?q?=20positions=20des=20pions=20en=20Mg=20et=20Eg.=20L'incr=C3=A9m?= =?UTF-8?q?ental=20concerne=20d=C3=A9sormais=20seulement=20le=20mat=C3=A9r?= =?UTF-8?q?iel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chesslib/ChessLibMoveGenerator.java | 2 +- ...bstractIncrementalSimplifiedEvaluator.java | 4 +- .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 17 +- .../ai/eval/hbpg2/Hb2IncrementalState.java | 20 +- .../hbpg2/Hb2SimplifiedEvaluatorBase.java | 186 +++++++++++++++++- 5 files changed, 208 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveGenerator.java b/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveGenerator.java index 58b7eb8..5a029d5 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveGenerator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ChessLibMoveGenerator.java @@ -3,8 +3,8 @@ import java.util.List; import java.util.function.Function; -import com.fathzer.games.MoveGenerator; import com.fathzer.games.HashProvider; +import com.fathzer.games.MoveGenerator; import com.fathzer.games.Status; import com.fathzer.games.util.MoveList; import com.fathzer.games.util.SelectiveComparator; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java index c609422..3c1fdc3 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java @@ -7,6 +7,7 @@ import com.fathzer.games.ai.evaluation.Evaluator; import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; import com.fathzer.games.util.Stack; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; /** An incremental implementation of the simplified evaluator described at https://www.chessprogramming.org/Simplified_Evaluation_Function *
This only works with 8*8 games and exactly one king per Color. @@ -48,7 +49,8 @@ public Evaluator fork() { @Override public void init(B board) { states.clear(); - states.set(new Hb2IncrementalState(getExplorer(board))); + states.set(new Hb2IncrementalState(getExplorer(board), ((ChessLibMoveGenerator)board).getBoard())); + } @Override diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index 4b623c1..216b090 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -3,6 +3,7 @@ import static com.fathzer.chess.utils.Pieces.KING; import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.github.bhlangonijr.chesslib.Board; /** The state of the evaluator. */ @@ -11,6 +12,7 @@ class Hb2BasicState extends Hb2FastPhaseDetector { int whiteKingIndex; int blackKingIndex; int computedPhase; + Board board; Hb2BasicState() { @@ -23,10 +25,12 @@ void copyTo(Hb2BasicState other) { other.blackKingIndex = blackKingIndex; other.whiteKingIndex = whiteKingIndex; other.computedPhase = computedPhase; + other.board = board; + } - Hb2BasicState(BoardExplorer explorer) { - + Hb2BasicState(BoardExplorer explorer, Board board) { + this.board = board; this.points = 0; this.computedPhase = 0; do { @@ -37,7 +41,7 @@ void copyTo(Hb2BasicState other) { final boolean isBlack = p<0; if (kind!=KING) { int inc = Hb2SimplifiedEvaluatorBase.getRawValue(kind); - inc += Hb2SimplifiedEvaluatorBase.getPositionValue(kind, isBlack, index); +// inc += Hb2SimplifiedEvaluatorBase.getPositionValue(kind, isBlack, index); if (isBlack) { points -= inc; } else { @@ -57,9 +61,12 @@ void copyTo(Hb2BasicState other) { int evaluateAsWhite() { // for the time being (29/03/2024) points are the same in Mg and Eg except for the king preferred squares // but it's gonna change very soon + // points = material only, from now on. int phase = getPhaseForTaperedEval(computedPhase); - int evalMg = points + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); - int evalEg = points + Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); + int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); + int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); + int evalMg = points + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); + int evalEg = points + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); } } \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index a33ac4c..3e7d7ca 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -2,12 +2,12 @@ import static com.fathzer.chess.utils.Pieces.KING; import static com.fathzer.chess.utils.Pieces.PAWN; -import static com.fathzer.chess.utils.Pieces.ROOK; -import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getPositionValue; +//import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getPositionValue; import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValue; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; +import com.github.bhlangonijr.chesslib.Board; /** The current state of a {@link Hb2AbstractIncrementalSimplifiedEvaluator} */ @@ -16,8 +16,8 @@ public class Hb2IncrementalState extends Hb2BasicState { super(); } - Hb2IncrementalState(BoardExplorer exp) { - super(exp); + Hb2IncrementalState(BoardExplorer exp, Board board) { + super(exp, board); } void update(MoveData move) { @@ -28,13 +28,14 @@ private int getIncrement(MoveData move) { final boolean isBlack = move.getMovingPiece()<0; int moving = Math.abs(move.getMovingPiece()); final int movingIndex = move.getMovingIndex(); - int inc; +// int inc; + int inc = 0; if (moving==KING) { // The position value of kings is not evaluated incrementally int rookIndex = move.getCastlingRookIndex(); if (rookIndex>=0) { // It's a castling move, update rook positions values - inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); +// inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); } else { inc = doCapture(isBlack, move); } @@ -46,7 +47,7 @@ private int getIncrement(MoveData move) { } } else { // Remove the position value of the moving piece - inc = - getPositionValue(moving, isBlack, movingIndex); +// inc = - getPositionValue(moving, isBlack, movingIndex); final int promoType = move.getPromotionType(); if (promoType!=0) { // If promotion, add raw value points, update phase @@ -56,7 +57,7 @@ private int getIncrement(MoveData move) { } inc += doCapture(isBlack, move); // Adds the position value of the - inc += getPositionValue(moving, isBlack, move.getMovingDestination()); +// inc += getPositionValue(moving, isBlack, move.getMovingDestination()); } return isBlack ? -inc : +inc; } @@ -68,7 +69,8 @@ private int doCapture(boolean isBlack, MoveData move) { // Update the phase detector remove(isBlack ? captured : -captured); // Then add its raw value and its position value - return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); +// return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); + return getRawValue(captured); } else { return 0; } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java index 3b3cd57..162edd9 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java @@ -1,9 +1,13 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg2; +import static com.fathzer.chess.utils.Pieces.KING; + import com.fathzer.chess.utils.Pieces; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.BoardExplorerBuilder; import com.fathzer.games.MoveGenerator; +import com.fathzer.jchess.chesslib.ChessLibBoardExplorer; +import com.github.bhlangonijr.chesslib.Board; abstract class Hb2SimplifiedEvaluatorBase> implements BoardExplorerBuilder { @@ -28,7 +32,62 @@ abstract class Hb2SimplifiedEvaluatorBase> impleme -30,-30, 0, 0, 0, 0,-30,-30, -50,-30,-30,-30,-30,-30,-30,-50}; - private static final int [][] PIECE_POSITION_VALUES = new int[][] { +// private static final int [][] PIECE_POSITION_VALUES = new int[][] { +// // Just to have index equals to piece type codes +// new int[0], +// // PAWN +// new int[] { +// 0, 0, 0, 0, 0, 0, 0, 0, +// 50, 50, 50, 50, 50, 50, 50, 50, +// 10, 10, 20, 30, 30, 20, 10, 10, +// 5, 5, 10, 25, 25, 10, 5, 5, +// 0, 0, 0, 20, 20, 0, 0, 0, +// 5, -5,-10, 0, 0,-10, -5, 5, +// 5, 10, 10,-20,-20, 10, 10, 5, +// 0, 0, 0, 0, 0, 0, 0, 0}, +// // KNIGHT +// new int[] { +// -50,-40,-30,-30,-30,-30,-40,-50, +// -40,-20, 0, 0, 0, 0,-20,-40, +// -30, 0, 10, 15, 15, 10, 0,-30, +// -30, 5, 15, 20, 20, 15, 5,-30, +// -30, 0, 15, 20, 20, 15, 0,-30, +// -30, 5, 10, 15, 15, 10, 5,-30, +// -40,-20, 0, 5, 5, 0,-20,-40, +// -50,-40,-30,-30,-30,-30,-40,-50}, +// // BISHOP +// new int[] { +// -20,-10,-10,-10,-10,-10,-10,-20, +// -10, 0, 0, 0, 0, 0, 0,-10, +// -10, 0, 5, 10, 10, 5, 0,-10, +// -10, 5, 5, 10, 10, 5, 5,-10, +// -10, 0, 10, 10, 10, 10, 0,-10, +// -10, 10, 10, 10, 10, 10, 10,-10, +// -10, 5, 0, 0, 0, 0, 5,-10, +// -20,-10,-10,-10,-10,-10,-10,-20}, +// // ROOK +// new int[] { +// 0, 0, 0, 0, 0, 0, 0, 0, +// 5, 10, 10, 10, 10, 10, 10, 5, +// -5, 0, 0, 0, 0, 0, 0, -5, +// -5, 0, 0, 0, 0, 0, 0, -5, +// -5, 0, 0, 0, 0, 0, 0, -5, +// -5, 0, 0, 0, 0, 0, 0, -5, +// -5, 0, 0, 0, 0, 0, 0, -5, +// 0, 0, 0, 5, 5, 0, 0, 0}, +// // QUEEN +// new int[] { +// -20,-10,-10, -5, -5,-10,-10,-20, +// -10, 0, 0, 0, 0, 0, 0,-10, +// -10, 0, 5, 5, 5, 5, 0,-10, +// -5, 0, 5, 5, 5, 5, 0, -5, +// 0, 0, 5, 5, 5, 5, 0, -5, +// -10, 5, 5, 5, 5, 5, 0,-10, +// -10, 0, 5, 0, 0, 0, 0,-10, +// -20,-10,-10, -5, -5,-10,-10,-20 +// }}; + + private static final int [][] PIECE_POSITION_VALUES_MG = new int[][] { // Just to have index equals to piece type codes new int[0], // PAWN @@ -83,12 +142,75 @@ abstract class Hb2SimplifiedEvaluatorBase> impleme -20,-10,-10, -5, -5,-10,-10,-20 }}; + private static final int [][] PIECE_POSITION_VALUES_EG= new int[][] { + // Just to have index equals to piece type codes + new int[0], + // PAWN + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 90, 90, 90, 90, 90, 90, 90, 90, + 30, 30, 40, 60, 60, 40, 30, 30, + 10, 10, 20, 40, 40, 20, 10, 10, + 0, 0, 0, 20, 20, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 5, + 5, 10, 10,-20,-20, 10, 10, 5, + 0, 0, 0, 0, 0, 0, 0, 0}, + // KNIGHT + new int[] { + -50,-40,-30,-30,-30,-30,-40,-50, + -40,-20, 0, 0, 0, 0,-20,-40, + -30, 0, 10, 15, 15, 10, 0,-30, + -30, 5, 15, 20, 20, 15, 5,-30, + -30, 0, 15, 20, 20, 15, 0,-30, + -30, 5, 10, 15, 15, 10, 5,-30, + -40,-20, 0, 5, 5, 0,-20,-40, + -50,-40,-30,-30,-30,-30,-40,-50}, + // BISHOP + new int[] { + -20,-10,-10,-10,-10,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 10, 10, 5, 0,-10, + -10, 5, 5, 10, 10, 5, 5,-10, + -10, 0, 10, 10, 10, 10, 0,-10, + -10, 10, 10, 10, 10, 10, 10,-10, + -10, 5, 0, 0, 0, 0, 5,-10, + -20,-10,-10,-10,-10,-10,-10,-20}, + // ROOK + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 10, 10, 10, 10, 10, 10, 5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + 0, 0, 0, 5, 5, 0, 0, 0}, + // QUEEN + new int[] { + -20,-10,-10, -5, -5,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 5, 5, 5, 0,-10, + -5, 0, 5, 5, 5, 5, 0, -5, + 0, 0, 5, 5, 5, 5, 0, -5, + -10, 5, 5, 5, 5, 5, 0,-10, + -10, 0, 5, 0, 0, 0, 0,-10, + -20,-10,-10, -5, -5,-10,-10,-20 + }}; + Hb2SimplifiedEvaluatorBase() { super(); } - static int getPositionValue(int type, boolean black, int index) { - return getPositionValue(PIECE_POSITION_VALUES[type], index, black); +// static int getPositionValue(int type, boolean black, int index) { +// return getPositionValue(PIECE_POSITION_VALUES[type], index, black); +// } +// + static int getPositionValueMg(int type, boolean black, int index) { + return getPositionValue(PIECE_POSITION_VALUES_MG[type], index, black); + } + + static int getPositionValueEg(int type, boolean black, int index) { + return getPositionValue(PIECE_POSITION_VALUES_EG[type], index, black); } static int getRawValue(int type) { @@ -121,7 +243,61 @@ private static int getPositionValue(int[] positionMap, int index, boolean black) * @param index The index of the piece on the board as defined in {@link BoardExplorer} * @return an integer */ - static int getPositionValue(int type, int index) { - return PIECE_POSITION_VALUES[type][index]; +// static int getPositionValue(int type, int index) { +// return PIECE_POSITION_VALUES[type][index]; +// } + + static int getPositionValueMg(Board board) { +// BoardExplorer explorer = getExplorer(board); + int pointsPosMg = 0; + BoardExplorer explorer = new ChessLibBoardExplorer(board); + do { + final int p = explorer.getPiece(); + + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind!=KING) { + + int inc = getPositionValueMg(kind, isBlack, index); + if (isBlack) { + pointsPosMg -= inc; + } else { + pointsPosMg += inc; + } + } + + + } while (explorer.next()); + + return (pointsPosMg); + + } + + static int getPositionValueEg(Board board) { +// BoardExplorer explorer = getExplorer(board); + int pointsPosEg = 0; + BoardExplorer explorer = new ChessLibBoardExplorer(board); + do { + final int p = explorer.getPiece(); + + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind!=KING) { + + int inc = getPositionValueEg(kind, isBlack, index); + if (isBlack) { + pointsPosEg -= inc; + } else { + pointsPosEg += inc; + } + } + + + } while (explorer.next()); + + return (pointsPosEg); + } } From 0675d06426cbacbcfdb2f3d0e28eda5a94699f90 Mon Sep 17 00:00:00 2001 From: herve Date: Sat, 30 Mar 2024 07:24:35 +0100 Subject: [PATCH 29/55] oubli du push s'il y a quelques minutes --- .../chesslib/ChessLibBoardExplorer.java | 69 ++++++++++++++++++- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ChessLibBoardExplorer.java b/src/main/java/com/fathzer/jchess/chesslib/ChessLibBoardExplorer.java index 9c1ca61..15a2129 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ChessLibBoardExplorer.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ChessLibBoardExplorer.java @@ -1,6 +1,69 @@ package com.fathzer.jchess.chesslib; -import static com.github.bhlangonijr.chesslib.Square.*; +import static com.github.bhlangonijr.chesslib.Square.A1; +import static com.github.bhlangonijr.chesslib.Square.A2; +import static com.github.bhlangonijr.chesslib.Square.A3; +import static com.github.bhlangonijr.chesslib.Square.A4; +import static com.github.bhlangonijr.chesslib.Square.A5; +import static com.github.bhlangonijr.chesslib.Square.A6; +import static com.github.bhlangonijr.chesslib.Square.A7; +import static com.github.bhlangonijr.chesslib.Square.A8; +import static com.github.bhlangonijr.chesslib.Square.B1; +import static com.github.bhlangonijr.chesslib.Square.B2; +import static com.github.bhlangonijr.chesslib.Square.B3; +import static com.github.bhlangonijr.chesslib.Square.B4; +import static com.github.bhlangonijr.chesslib.Square.B5; +import static com.github.bhlangonijr.chesslib.Square.B6; +import static com.github.bhlangonijr.chesslib.Square.B7; +import static com.github.bhlangonijr.chesslib.Square.B8; +import static com.github.bhlangonijr.chesslib.Square.C1; +import static com.github.bhlangonijr.chesslib.Square.C2; +import static com.github.bhlangonijr.chesslib.Square.C3; +import static com.github.bhlangonijr.chesslib.Square.C4; +import static com.github.bhlangonijr.chesslib.Square.C5; +import static com.github.bhlangonijr.chesslib.Square.C6; +import static com.github.bhlangonijr.chesslib.Square.C7; +import static com.github.bhlangonijr.chesslib.Square.C8; +import static com.github.bhlangonijr.chesslib.Square.D1; +import static com.github.bhlangonijr.chesslib.Square.D2; +import static com.github.bhlangonijr.chesslib.Square.D3; +import static com.github.bhlangonijr.chesslib.Square.D4; +import static com.github.bhlangonijr.chesslib.Square.D5; +import static com.github.bhlangonijr.chesslib.Square.D6; +import static com.github.bhlangonijr.chesslib.Square.D7; +import static com.github.bhlangonijr.chesslib.Square.D8; +import static com.github.bhlangonijr.chesslib.Square.E1; +import static com.github.bhlangonijr.chesslib.Square.E2; +import static com.github.bhlangonijr.chesslib.Square.E3; +import static com.github.bhlangonijr.chesslib.Square.E4; +import static com.github.bhlangonijr.chesslib.Square.E5; +import static com.github.bhlangonijr.chesslib.Square.E6; +import static com.github.bhlangonijr.chesslib.Square.E7; +import static com.github.bhlangonijr.chesslib.Square.E8; +import static com.github.bhlangonijr.chesslib.Square.F1; +import static com.github.bhlangonijr.chesslib.Square.F2; +import static com.github.bhlangonijr.chesslib.Square.F3; +import static com.github.bhlangonijr.chesslib.Square.F4; +import static com.github.bhlangonijr.chesslib.Square.F5; +import static com.github.bhlangonijr.chesslib.Square.F6; +import static com.github.bhlangonijr.chesslib.Square.F7; +import static com.github.bhlangonijr.chesslib.Square.F8; +import static com.github.bhlangonijr.chesslib.Square.G1; +import static com.github.bhlangonijr.chesslib.Square.G2; +import static com.github.bhlangonijr.chesslib.Square.G3; +import static com.github.bhlangonijr.chesslib.Square.G4; +import static com.github.bhlangonijr.chesslib.Square.G5; +import static com.github.bhlangonijr.chesslib.Square.G6; +import static com.github.bhlangonijr.chesslib.Square.G7; +import static com.github.bhlangonijr.chesslib.Square.G8; +import static com.github.bhlangonijr.chesslib.Square.H1; +import static com.github.bhlangonijr.chesslib.Square.H2; +import static com.github.bhlangonijr.chesslib.Square.H3; +import static com.github.bhlangonijr.chesslib.Square.H4; +import static com.github.bhlangonijr.chesslib.Square.H5; +import static com.github.bhlangonijr.chesslib.Square.H6; +import static com.github.bhlangonijr.chesslib.Square.H7; +import static com.github.bhlangonijr.chesslib.Square.H8; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.github.bhlangonijr.chesslib.Board; @@ -9,7 +72,7 @@ import com.github.bhlangonijr.chesslib.Side; import com.github.bhlangonijr.chesslib.Square; -class ChessLibBoardExplorer implements BoardExplorer { +public class ChessLibBoardExplorer implements BoardExplorer { static final Square[] SQUARES; static { @@ -29,7 +92,7 @@ class ChessLibBoardExplorer implements BoardExplorer { private int index; private int piece; - ChessLibBoardExplorer(Board board) { + public ChessLibBoardExplorer(Board board) { this.board = board; this.index = -1; next(); From 8fcce8e2a003ba249319f90907f99465566ea551 Mon Sep 17 00:00:00 2001 From: herve Date: Mon, 20 May 2024 09:19:49 +0200 Subject: [PATCH 30/55] =?UTF-8?q?Valeurs=20diff=C3=A9rentes=20du=20mat?= =?UTF-8?q?=C3=A9riel=20en=20final=20rendues=20possibles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 26 ++++--- .../ai/eval/hbpg2/Hb2FastPhaseDetector.java | 14 ++-- .../ai/eval/hbpg2/Hb2IncrementalState.java | 74 +++++++++++++++--- .../chesslib/ai/eval/hbpg2/Hb2Phase.java | 2 +- .../hbpg2/Hb2SimplifiedEvaluatorBase.java | 75 ++++--------------- 5 files changed, 99 insertions(+), 92 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index 216b090..1aa7ef5 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -8,7 +8,8 @@ /** The state of the evaluator. */ class Hb2BasicState extends Hb2FastPhaseDetector { - int points; + int pointsMg; + int pointsEg; int whiteKingIndex; int blackKingIndex; int computedPhase; @@ -21,7 +22,7 @@ class Hb2BasicState extends Hb2FastPhaseDetector { void copyTo(Hb2BasicState other) { super.copyTo(other); - other.points = points; + other.pointsMg = pointsMg; other.blackKingIndex = blackKingIndex; other.whiteKingIndex = whiteKingIndex; other.computedPhase = computedPhase; @@ -31,21 +32,23 @@ void copyTo(Hb2BasicState other) { Hb2BasicState(BoardExplorer explorer, Board board) { this.board = board; - this.points = 0; + this.pointsMg = 0; this.computedPhase = 0; do { final int p = explorer.getPiece(); - add(p); +// add(p); final int kind = Math.abs(p); final int index = explorer.getIndex(); final boolean isBlack = p<0; if (kind!=KING) { - int inc = Hb2SimplifiedEvaluatorBase.getRawValue(kind); -// inc += Hb2SimplifiedEvaluatorBase.getPositionValue(kind, isBlack, index); + int incMg = Hb2SimplifiedEvaluatorBase.getRawValueMg(kind); + int incEg = Hb2SimplifiedEvaluatorBase.getRawValueMg(kind); if (isBlack) { - points -= inc; + pointsMg -= incMg; + pointsEg -= incEg; } else { - points += inc; + pointsMg += incMg; + pointsEg += incEg; } } else if (isBlack) { this.blackKingIndex = index; @@ -61,12 +64,13 @@ void copyTo(Hb2BasicState other) { int evaluateAsWhite() { // for the time being (29/03/2024) points are the same in Mg and Eg except for the king preferred squares // but it's gonna change very soon - // points = material only, from now on. + // pointsMg = material only! The white material minus the black material in the middlegame. + // pointsEg = material only! The white material minus the black material in the endgame. int phase = getPhaseForTaperedEval(computedPhase); int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); - int evalMg = points + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); - int evalEg = points + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); + int evalMg = pointsMg + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); + int evalEg = pointsEg + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); } } \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java index 4cf848e..6b6c880 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java @@ -7,13 +7,13 @@ class Hb2FastPhaseDetector { // private long state; - void add(int piece) { -// state += PIECE_KIND_TO_VALUES[piece + KING]; - } - - void remove(int piece) { -// state -= PIECE_KIND_TO_VALUES[piece + KING]; - } +// void add(int piece) { +//// state += PIECE_KIND_TO_VALUES[piece + KING]; +// } +// +// void remove(int piece) { +//// state -= PIECE_KIND_TO_VALUES[piece + KING]; +// } int getPhaseForTaperedEval(int computedPhaseValue) { return (Math.min(computedPhaseValue, Hb2Phase.PHASE_UPPER_BOUND)); diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index 3e7d7ca..fc67569 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -2,8 +2,8 @@ import static com.fathzer.chess.utils.Pieces.KING; import static com.fathzer.chess.utils.Pieces.PAWN; -//import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getPositionValue; -import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValue; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValueMg; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValueEg; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; @@ -21,10 +21,10 @@ public class Hb2IncrementalState extends Hb2BasicState { } void update(MoveData move) { - points += getIncrement(move); + pointsMg += getIncrementMg(move); } - private int getIncrement(MoveData move) { + private int getIncrementMg(MoveData move) { final boolean isBlack = move.getMovingPiece()<0; int moving = Math.abs(move.getMovingPiece()); final int movingIndex = move.getMovingIndex(); @@ -37,7 +37,7 @@ private int getIncrement(MoveData move) { // It's a castling move, update rook positions values // inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); } else { - inc = doCapture(isBlack, move); + inc = doCaptureMg(isBlack, move); } // Update king's position if (isBlack) { @@ -51,26 +51,78 @@ private int getIncrement(MoveData move) { final int promoType = move.getPromotionType(); if (promoType!=0) { // If promotion, add raw value points, update phase - inc += getRawValue(promoType)-getRawValue(PAWN); + inc += getRawValueMg(promoType)-getRawValueMg(PAWN); moving = promoType; - add(isBlack ? -promoType : promoType); +// add(isBlack ? -promoType : promoType); } - inc += doCapture(isBlack, move); + inc += doCaptureMg(isBlack, move); // Adds the position value of the // inc += getPositionValue(moving, isBlack, move.getMovingDestination()); } return isBlack ? -inc : +inc; } - private int doCapture(boolean isBlack, MoveData move) { + private int getIncrementEg(MoveData move) { + final boolean isBlack = move.getMovingPiece()<0; + int moving = Math.abs(move.getMovingPiece()); + final int movingIndex = move.getMovingIndex(); +// int inc; + int inc = 0; + if (moving==KING) { + // The position value of kings is not evaluated incrementally + int rookIndex = move.getCastlingRookIndex(); + if (rookIndex>=0) { + // It's a castling move, update rook positions values +// inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); + } else { + inc = doCaptureMg(isBlack, move); + } + // Update king's position + if (isBlack) { + this.blackKingIndex = move.getMovingDestination(); + } else { + this.whiteKingIndex = move.getMovingDestination(); + } + } else { + // Remove the position value of the moving piece +// inc = - getPositionValue(moving, isBlack, movingIndex); + final int promoType = move.getPromotionType(); + if (promoType!=0) { + // If promotion, add raw value points, update phase + inc += getRawValueEg(promoType)-getRawValueEg(PAWN); + moving = promoType; +// add(isBlack ? -promoType : promoType); + } + inc += doCaptureEg(isBlack, move); + // Adds the position value of the +// inc += getPositionValue(moving, isBlack, move.getMovingDestination()); + } + return isBlack ? -inc : +inc; + } + + private int doCaptureMg(boolean isBlack, MoveData move) { + int captured = move.getCapturedType(); + if (captured!=0) { + // A piece was captured + // Update the phase detector +// remove(isBlack ? captured : -captured); + // Then add its raw value and its position value +// return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); + return getRawValueMg(captured); + } else { + return 0; + } + } + + private int doCaptureEg(boolean isBlack, MoveData move) { int captured = move.getCapturedType(); if (captured!=0) { // A piece was captured // Update the phase detector - remove(isBlack ? captured : -captured); +// remove(isBlack ? captured : -captured); // Then add its raw value and its position value // return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); - return getRawValue(captured); + return getRawValueEg(captured); } else { return 0; } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java index 125f670..b23c4b8 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java @@ -10,7 +10,7 @@ public class Hb2Phase { public static final int NB_INCR_PHASE = 64; // Pawns do not count. 3 for B and N, 5 for the R, 10 for the Q. White has therefore 32, and black likewise. Total = 64. // Very useful for the tapered evaluation - // Ethereal did not even think about it. But many others engines do. + // Ethereal did not even think about it. But many other engines do. // For example, If white or black or both have 2 queens for example, without an upper bound, the phase could exceed NB_INCR_PHASE, which would ruin the tapered evaluation public static final int PHASE_UPPER_BOUND = NB_INCR_PHASE; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java index 162edd9..a76a400 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java @@ -11,7 +11,12 @@ abstract class Hb2SimplifiedEvaluatorBase> implements BoardExplorerBuilder { - private static final int[] PIECE_VALUES = {0, 100, 320, 330, 500, 900, 20000}; + + private static final int[] PIECE_VALUES_MG = {0, 100, 320, 330, 500, 900, 20000}; + + private static final int[] PIECE_VALUES_EG = {0, 100, 320, 330, 500, 900, 20000}; + + private static final int[] KING_MID_GAME_EVAL = new int[] { -30,-40,-40,-50,-50,-40,-40,-30, -30,-40,-40,-50,-50,-40,-40,-30, @@ -32,60 +37,7 @@ abstract class Hb2SimplifiedEvaluatorBase> impleme -30,-30, 0, 0, 0, 0,-30,-30, -50,-30,-30,-30,-30,-30,-30,-50}; -// private static final int [][] PIECE_POSITION_VALUES = new int[][] { -// // Just to have index equals to piece type codes -// new int[0], -// // PAWN -// new int[] { -// 0, 0, 0, 0, 0, 0, 0, 0, -// 50, 50, 50, 50, 50, 50, 50, 50, -// 10, 10, 20, 30, 30, 20, 10, 10, -// 5, 5, 10, 25, 25, 10, 5, 5, -// 0, 0, 0, 20, 20, 0, 0, 0, -// 5, -5,-10, 0, 0,-10, -5, 5, -// 5, 10, 10,-20,-20, 10, 10, 5, -// 0, 0, 0, 0, 0, 0, 0, 0}, -// // KNIGHT -// new int[] { -// -50,-40,-30,-30,-30,-30,-40,-50, -// -40,-20, 0, 0, 0, 0,-20,-40, -// -30, 0, 10, 15, 15, 10, 0,-30, -// -30, 5, 15, 20, 20, 15, 5,-30, -// -30, 0, 15, 20, 20, 15, 0,-30, -// -30, 5, 10, 15, 15, 10, 5,-30, -// -40,-20, 0, 5, 5, 0,-20,-40, -// -50,-40,-30,-30,-30,-30,-40,-50}, -// // BISHOP -// new int[] { -// -20,-10,-10,-10,-10,-10,-10,-20, -// -10, 0, 0, 0, 0, 0, 0,-10, -// -10, 0, 5, 10, 10, 5, 0,-10, -// -10, 5, 5, 10, 10, 5, 5,-10, -// -10, 0, 10, 10, 10, 10, 0,-10, -// -10, 10, 10, 10, 10, 10, 10,-10, -// -10, 5, 0, 0, 0, 0, 5,-10, -// -20,-10,-10,-10,-10,-10,-10,-20}, -// // ROOK -// new int[] { -// 0, 0, 0, 0, 0, 0, 0, 0, -// 5, 10, 10, 10, 10, 10, 10, 5, -// -5, 0, 0, 0, 0, 0, 0, -5, -// -5, 0, 0, 0, 0, 0, 0, -5, -// -5, 0, 0, 0, 0, 0, 0, -5, -// -5, 0, 0, 0, 0, 0, 0, -5, -// -5, 0, 0, 0, 0, 0, 0, -5, -// 0, 0, 0, 5, 5, 0, 0, 0}, -// // QUEEN -// new int[] { -// -20,-10,-10, -5, -5,-10,-10,-20, -// -10, 0, 0, 0, 0, 0, 0,-10, -// -10, 0, 5, 5, 5, 5, 0,-10, -// -5, 0, 5, 5, 5, 5, 0, -5, -// 0, 0, 5, 5, 5, 5, 0, -5, -// -10, 5, 5, 5, 5, 5, 0,-10, -// -10, 0, 5, 0, 0, 0, 0,-10, -// -20,-10,-10, -5, -5,-10,-10,-20 -// }}; + private static final int [][] PIECE_POSITION_VALUES_MG = new int[][] { // Just to have index equals to piece type codes @@ -201,10 +153,7 @@ abstract class Hb2SimplifiedEvaluatorBase> impleme super(); } -// static int getPositionValue(int type, boolean black, int index) { -// return getPositionValue(PIECE_POSITION_VALUES[type], index, black); -// } -// + static int getPositionValueMg(int type, boolean black, int index) { return getPositionValue(PIECE_POSITION_VALUES_MG[type], index, black); } @@ -213,11 +162,13 @@ static int getPositionValueEg(int type, boolean black, int index) { return getPositionValue(PIECE_POSITION_VALUES_EG[type], index, black); } - static int getRawValue(int type) { - return PIECE_VALUES[type]; + static int getRawValueMg(int type) { + return PIECE_VALUES_MG[type]; } - + static int getRawValueEg(int type) { + return PIECE_VALUES_EG[type]; + } static int getKingPositionsValueMg(int whiteIndex, int blackIndex) { From 3367e426a0a2c8d2728572377e4f4230d3db5e66 Mon Sep 17 00:00:00 2001 From: herve Date: Wed, 22 May 2024 07:22:41 +0200 Subject: [PATCH 31/55] =?UTF-8?q?Correction=20d'une=20erreur=20en=20=C3=A9?= =?UTF-8?q?valuation=20EndGame?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index 1aa7ef5..631e35b 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -42,7 +42,7 @@ void copyTo(Hb2BasicState other) { final boolean isBlack = p<0; if (kind!=KING) { int incMg = Hb2SimplifiedEvaluatorBase.getRawValueMg(kind); - int incEg = Hb2SimplifiedEvaluatorBase.getRawValueMg(kind); + int incEg = Hb2SimplifiedEvaluatorBase.getRawValueEg(kind); if (isBlack) { pointsMg -= incMg; pointsEg -= incEg; @@ -62,8 +62,7 @@ void copyTo(Hb2BasicState other) { int evaluateAsWhite() { - // for the time being (29/03/2024) points are the same in Mg and Eg except for the king preferred squares - // but it's gonna change very soon + // pointsMg = material only! The white material minus the black material in the middlegame. // pointsEg = material only! The white material minus the black material in the endgame. int phase = getPhaseForTaperedEval(computedPhase); From 60c345135542626e48844e53327c2e3a297c50ca Mon Sep 17 00:00:00 2001 From: herve Date: Thu, 3 Oct 2024 11:16:02 +0200 Subject: [PATCH 32/55] =?UTF-8?q?Hb2SimplifiedEvaluator:=20incr=C3=A9menta?= =?UTF-8?q?l=20achev=C3=A9=20et=20propre=20pour=20position=20des=20pi?= =?UTF-8?q?=C3=A8ces=20et=20mat=C3=A9riel.=20Avec=20tapered=20eval?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 27 +++- .../ai/eval/hbpg2/Hb2IncrementalState.java | 145 +++++++++++++++++- .../hbpg2/Hb2SimplifiedEvaluatorBase.java | 93 ++++++++++- .../jchess/chesslib/uci/ChessLibEngine.java | 2 + .../jchess/chesslib/ai/HBThreeMovesTest2.java | 33 ++++ 5 files changed, 289 insertions(+), 11 deletions(-) create mode 100644 src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index 631e35b..6054f94 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -10,6 +10,8 @@ class Hb2BasicState extends Hb2FastPhaseDetector { int pointsMg; int pointsEg; + int pointsPosMg; + int pointsPosEg; int whiteKingIndex; int blackKingIndex; int computedPhase; @@ -23,6 +25,9 @@ class Hb2BasicState extends Hb2FastPhaseDetector { void copyTo(Hb2BasicState other) { super.copyTo(other); other.pointsMg = pointsMg; + other.pointsEg= pointsEg; + other.pointsPosMg = pointsPosMg; + other.pointsPosEg= pointsPosEg; other.blackKingIndex = blackKingIndex; other.whiteKingIndex = whiteKingIndex; other.computedPhase = computedPhase; @@ -30,9 +35,14 @@ void copyTo(Hb2BasicState other) { } + + Hb2BasicState(BoardExplorer explorer, Board board) { this.board = board; this.pointsMg = 0; + this.pointsEg = 0; + this.pointsPosMg = 0; + this.pointsPosEg = 0; this.computedPhase = 0; do { final int p = explorer.getPiece(); @@ -56,6 +66,19 @@ void copyTo(Hb2BasicState other) { this.whiteKingIndex = index; } + + + if (kind!=KING) { + int incPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(kind, isBlack, index); + int incPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(kind, isBlack, index); + if (isBlack) { + pointsPosMg -= incPosMg; + pointsPosEg -= incPosEg; + } else { + pointsPosMg += incPosMg; + pointsPosEg += incPosEg; + } + } computedPhase += Hb2Phase.getPhaseValue(kind); } while (explorer.next()); } @@ -66,8 +89,8 @@ int evaluateAsWhite() { // pointsMg = material only! The white material minus the black material in the middlegame. // pointsEg = material only! The white material minus the black material in the endgame. int phase = getPhaseForTaperedEval(computedPhase); - int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); - int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); +// int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); +// int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); int evalMg = pointsMg + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); int evalEg = pointsEg + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index fc67569..5c5f6dc 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -5,6 +5,7 @@ import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValueMg; import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValueEg; +import com.fathzer.chess.utils.Pieces; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; import com.github.bhlangonijr.chesslib.Board; @@ -20,8 +21,32 @@ public class Hb2IncrementalState extends Hb2BasicState { super(exp, board); } + + void update(MoveData move) { pointsMg += getIncrementMg(move); + pointsEg += getIncrementEg(move); + pointsPosMg += getIncrementPosMg(move); + pointsPosEg += getIncrementPosEg(move); + updatePhase(move); + } + + private void updatePhase(MoveData move) { + final int promoType = move.getPromotionType(); + if (promoType!=0) { + // If promotion, add raw value points, update phase + computedPhase += Hb2Phase.getPhaseValue(promoType); + + } + int captured = move.getCapturedType(); + if (captured!=0) { + // A piece was captured + // Update the phase detector +// remove(isBlack ? captured : -captured); + // Then add its raw value and its position value +// return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); + computedPhase -= Hb2Phase.getPhaseValue(captured); + } } private int getIncrementMg(MoveData move) { @@ -37,7 +62,7 @@ private int getIncrementMg(MoveData move) { // It's a castling move, update rook positions values // inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); } else { - inc = doCaptureMg(isBlack, move); + inc += doCaptureMg(isBlack, move); } // Update king's position if (isBlack) { @@ -75,7 +100,7 @@ private int getIncrementEg(MoveData move) { // It's a castling move, update rook positions values // inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); } else { - inc = doCaptureMg(isBlack, move); + inc += doCaptureMg(isBlack, move); } // Update king's position if (isBlack) { @@ -127,4 +152,120 @@ private int doCaptureEg(boolean isBlack, MoveData move) { return 0; } } + + private int getIncrementPosMg(MoveData move) { + final boolean isBlack = move.getMovingPiece()<0; + int moving = Math.abs(move.getMovingPiece()); + final int movingIndex = move.getMovingIndex(); +// int inc; + int inc = 0; + if (moving==KING) { + // The position value of kings is not evaluated incrementally + int rookIndex = move.getCastlingRookIndex(); + if (rookIndex>=0) { + // It's a castling move, update rook positions values + inc += Hb2SimplifiedEvaluatorBase.getPositionValueMg(Pieces.ROOK, isBlack, move.getCastlingRookDestinationIndex()) - Hb2SimplifiedEvaluatorBase.getPositionValueMg(Pieces.ROOK, isBlack, rookIndex); +// inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); + } else { + inc = doCapturPosMg(isBlack, move); + } + // Update king's position + if (isBlack) { + this.blackKingIndex = move.getMovingDestination(); + } else { + this.whiteKingIndex = move.getMovingDestination(); + } + } else { + // Remove the position value of the moving piece +// inc = - getPositionValue(moving, isBlack, movingIndex); + inc -= Hb2SimplifiedEvaluatorBase.getPositionValueMg(moving, isBlack, movingIndex); + final int promoType = move.getPromotionType(); + if (promoType!=0) { + // If promotion, add raw value points, update phase +// inc += getRawValueMg(promoType)-getRawValueMg(PAWN); + moving = promoType; +// add(isBlack ? -promoType : promoType); + } + inc += doCapturPosMg(isBlack, move); + // Adds the position value of the moving piece at its destination square + inc += Hb2SimplifiedEvaluatorBase.getPositionValueMg(moving, isBlack, move.getMovingDestination()); +// inc += getPositionValue(moving, isBlack, move.getMovingDestination()); + } + return isBlack ? -inc : +inc; + } + + + private int doCapturPosMg(boolean isBlack, MoveData move) { + int captured = move.getCapturedType(); + if (captured!=0) { + // A piece was captured + // Update the phase detector +// remove(isBlack ? captured : -captured); + // Then add its raw value and its position value +// return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); + + return Hb2SimplifiedEvaluatorBase.getPositionValueMg(captured, !isBlack, move.getCapturedIndex()); + + } else { + return 0; + } + } + + private int getIncrementPosEg(MoveData move) { + final boolean isBlack = move.getMovingPiece()<0; + int moving = Math.abs(move.getMovingPiece()); + final int movingIndex = move.getMovingIndex(); +// int inc; + int inc = 0; + if (moving==KING) { + // The position value of kings is not evaluated incrementally + int rookIndex = move.getCastlingRookIndex(); + if (rookIndex>=0) { + // It's a castling move, update rook positions values + inc += Hb2SimplifiedEvaluatorBase.getPositionValueEg(Pieces.ROOK, isBlack, move.getCastlingRookDestinationIndex()) - Hb2SimplifiedEvaluatorBase.getPositionValueEg(Pieces.ROOK, isBlack, rookIndex); +// inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); + } else { + inc = doCapturPosEg(isBlack, move); + } + // Update king's position + if (isBlack) { + this.blackKingIndex = move.getMovingDestination(); + } else { + this.whiteKingIndex = move.getMovingDestination(); + } + } else { + // Remove the position value of the moving piece +// inc = - getPositionValue(moving, isBlack, movingIndex); + inc -= Hb2SimplifiedEvaluatorBase.getPositionValueEg(moving, isBlack, movingIndex); + final int promoType = move.getPromotionType(); + if (promoType!=0) { + // If promotion, add raw value points, update phase +// inc += getRawValueMg(promoType)-getRawValueMg(PAWN); + moving = promoType; +// add(isBlack ? -promoType : promoType); + } + inc += doCapturPosEg(isBlack, move); + // Adds the position value of the moving piece at its destination square + inc += Hb2SimplifiedEvaluatorBase.getPositionValueEg(moving, isBlack, move.getMovingDestination()); +// inc += getPositionValue(moving, isBlack, move.getMovingDestination()); + } + return isBlack ? -inc : +inc; + } + + + private int doCapturPosEg(boolean isBlack, MoveData move) { + int captured = move.getCapturedType(); + if (captured!=0) { + // A piece was captured + // Update the phase detector +// remove(isBlack ? captured : -captured); + // Then add its raw value and its position value +// return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); + + return Hb2SimplifiedEvaluatorBase.getPositionValueEg(captured, !isBlack, move.getCapturedIndex()); + + } else { + return 0; + } + } } \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java index a76a400..7dec136 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2SimplifiedEvaluatorBase.java @@ -12,11 +12,6 @@ abstract class Hb2SimplifiedEvaluatorBase> implements BoardExplorerBuilder { - private static final int[] PIECE_VALUES_MG = {0, 100, 320, 330, 500, 900, 20000}; - - private static final int[] PIECE_VALUES_EG = {0, 100, 320, 330, 500, 900, 20000}; - - private static final int[] KING_MID_GAME_EVAL = new int[] { -30,-40,-40,-50,-50,-40,-40,-30, -30,-40,-40,-50,-50,-40,-40,-30, @@ -37,6 +32,87 @@ abstract class Hb2SimplifiedEvaluatorBase> impleme -30,-30, 0, 0, 0, 0,-30,-30, -50,-30,-30,-30,-30,-30,-30,-50}; + private static final int [][] PIECE_POSITION_VALUES = new int[][] { + // Just to have index equals to piece type codes + new int[0], + // PAWN + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 50, 50, 50, 50, 50, 50, 50, 50, + 10, 10, 20, 30, 30, 20, 10, 10, + 5, 5, 10, 25, 25, 10, 5, 5, + 0, 0, 0, 20, 20, 0, 0, 0, + 5, -5,-10, 0, 0,-10, -5, 5, + 5, 10, 10,-20,-20, 10, 10, 5, + 0, 0, 0, 0, 0, 0, 0, 0}, + // KNIGHT + new int[] { + -50,-40,-30,-30,-30,-30,-40,-50, + -40,-20, 0, 0, 0, 0,-20,-40, + -30, 0, 10, 15, 15, 10, 0,-30, + -30, 5, 15, 20, 20, 15, 5,-30, + -30, 0, 15, 20, 20, 15, 0,-30, + -30, 5, 10, 15, 15, 10, 5,-30, + -40,-20, 0, 5, 5, 0,-20,-40, + -50,-40,-30,-30,-30,-30,-40,-50}, + // BISHOP + new int[] { + -20,-10,-10,-10,-10,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 10, 10, 5, 0,-10, + -10, 5, 5, 10, 10, 5, 5,-10, + -10, 0, 10, 10, 10, 10, 0,-10, + -10, 10, 10, 10, 10, 10, 10,-10, + -10, 5, 0, 0, 0, 0, 5,-10, + -20,-10,-10,-10,-10,-10,-10,-20}, + // ROOK + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 10, 10, 10, 10, 10, 10, 5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + -5, 0, 0, 0, 0, 0, 0, -5, + 0, 0, 0, 5, 5, 0, 0, 0}, + // QUEEN + new int[] { + -20,-10,-10, -5, -5,-10,-10,-20, + -10, 0, 0, 0, 0, 0, 0,-10, + -10, 0, 5, 5, 5, 5, 0,-10, + -5, 0, 5, 5, 5, 5, 0, -5, + 0, 0, 5, 5, 5, 5, 0, -5, + -10, 5, 5, 5, 5, 5, 0,-10, + -10, 0, 5, 0, 0, 0, 0,-10, + -20,-10,-10, -5, -5,-10,-10,-20 + }}; + + + private static final int[] PIECE_VALUES_MG = {0, 100, 320, 330, 500, 900, 20000}; + + private static final int[] PIECE_VALUES_EG = {0, 100, 320, 330, 500, 900, 20000}; + + +// private static final int[] KING_MID_GAME_EVAL = new int[] { +// -30,-40,-40,-50,-50,-40,-40,-30, +// -30,-40,-40,-50,-50,-40,-40,-30, +// -30,-40,-40,-50,-50,-40,-40,-30, +// -30,-40,-40,-50,-50,-40,-40,-30, +// -20,-30,-30,-40,-40,-30,-30,-20, +// -10,-20,-20,-20,-20,-20,-20,-10, +// 20, 20, 0, 0, 0, 0, 20, 20, +// 20, 30, 10, 0, 0, 10, 30, 20}; +// +// private static final int[] KING_END_GAME_EVAL = new int[] { +// -50,-40,-30,-20,-20,-30,-40,-50, +// -30,-20,-10, 0, 0,-10,-20,-30, +// -30,-10, 20, 30, 30, 20,-10,-30, +// -30,-10, 30, 40, 40, 30,-10,-30, +// -30,-10, 30, 40, 40, 30,-10,-30, +// -30,-10, 20, 30, 30, 20,-10,-30, +// -30,-30, 0, 0, 0, 0,-30,-30, +// -50,-30,-30,-30,-30,-30,-30,-50}; +// private static final int [][] PIECE_POSITION_VALUES_MG = new int[][] { @@ -155,15 +231,18 @@ abstract class Hb2SimplifiedEvaluatorBase> impleme static int getPositionValueMg(int type, boolean black, int index) { - return getPositionValue(PIECE_POSITION_VALUES_MG[type], index, black); +// return getPositionValue(PIECE_POSITION_VALUES_MG[type], index, black); + return getPositionValue(PIECE_POSITION_VALUES[type], index, black); } static int getPositionValueEg(int type, boolean black, int index) { - return getPositionValue(PIECE_POSITION_VALUES_EG[type], index, black); +// return getPositionValue(PIECE_POSITION_VALUES_EG[type], index, black); + return getPositionValue(PIECE_POSITION_VALUES[type], index, black); } static int getRawValueMg(int type) { return PIECE_VALUES_MG[type]; + } static int getRawValueEg(int type) { diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index 926049f..6d7ffa4 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -31,6 +31,7 @@ import com.fathzer.jchess.chesslib.ai.eval.NaiveEvaluator; import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2MyFirstEvaluator; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluator; import com.fathzer.jchess.chesslib.time.RemainingMoveOracle; import com.fathzer.jchess.uci.UCIMove; import com.fathzer.jchess.uci.extended.Displayable; @@ -46,6 +47,7 @@ public class ChessLibEngine extends AbstractEngine Arrays.asList( new EvaluatorConfiguration<>("hbfirst2",Hb2MyFirstEvaluator::new), new EvaluatorConfiguration<>("hbtiny",MyTinyEvaluator::new), + new EvaluatorConfiguration<>("hbSimplified",Hb2SimplifiedEvaluator::new), new EvaluatorConfiguration<>("simplified",SimplifiedEvaluator::new), new EvaluatorConfiguration<>("naive",NaiveEvaluator::new) ); diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2.java new file mode 100644 index 0000000..bc2df9f --- /dev/null +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2.java @@ -0,0 +1,33 @@ +package com.fathzer.jchess.chesslib.ai; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fathzer.games.ai.evaluation.EvaluatedMove; +import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.uci.ChessLibEngine; +import com.github.bhlangonijr.chesslib.move.Move; + +class HBThreeMovesTest2 { + + @Test + void test() { + final int depth = 6; + final int bestMoveCount = 3; + final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(Hb2SimplifiedEvaluator::new, depth); + engine.getDeepeningPolicy().setSize(bestMoveCount); + final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)).getBestMoves(); + System.out.println(moves); + for (int i=0;i<3;i++) { + EvaluatedMove move = moves.get(i); + List principalVariation = move.getPrincipalVariation(); + System.out.println(move+" -> "+principalVariation); + } + } + +} From 9ce97f38b22cd8f4a0a29e8e57a4a3be76950a0e Mon Sep 17 00:00:00 2001 From: herve Date: Sun, 6 Oct 2024 08:05:28 +0200 Subject: [PATCH 33/55] nettoyage --- ...bstractIncrementalSimplifiedEvaluator.java | 89 ------------- .../chesslib/ai/eval/hbpg/HbBasicState.java | 52 -------- .../ai/eval/hbpg/HbFastPhaseDetector.java | 64 ---------- .../ai/eval/hbpg/HbIncrementalState.java | 76 ----------- .../ai/eval/hbpg/HbMyFirstEvaluator.java | 39 ------ .../jchess/chesslib/ai/eval/hbpg/HbPhase.java | 13 -- .../ai/eval/hbpg/HbSimplifiedEvaluator.java | 27 ---- .../eval/hbpg/HbSimplifiedEvaluatorBase.java | 119 ------------------ .../chesslib/ai/eval/hbpg/package-info.java | 1 - 9 files changed, 480 deletions(-) delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java deleted file mode 100644 index bb291b9..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbAbstractIncrementalSimplifiedEvaluator.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.fathzer.jchess.chesslib.ai.eval.hbpg; - -import java.util.function.Supplier; - -import com.fathzer.chess.utils.adapters.MoveData; -import com.fathzer.games.MoveGenerator; -import com.fathzer.games.ai.evaluation.Evaluator; -import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; -import com.fathzer.games.util.Stack; - -/** An incremental implementation of the simplified evaluator described at https://www.chessprogramming.org/Simplified_Evaluation_Function - *
This only works with 8*8 games and exactly one king per Color. - */ -public abstract class HbAbstractIncrementalSimplifiedEvaluator> extends HbSimplifiedEvaluatorBase implements ZeroSumEvaluator, Supplier> { - private final Stack states; - private HbIncrementalState toCommit; - private MoveData moveData; - - /** Default constructor - */ - protected HbAbstractIncrementalSimplifiedEvaluator() { - this.states = new Stack<>(HbIncrementalState::new); - this.moveData = get(); - } - - /** Constructor. - * @param state The state to initialize the evaluator - */ - protected HbAbstractIncrementalSimplifiedEvaluator(HbIncrementalState state) { - this(); - HbIncrementalState other = new HbIncrementalState(); - state.copyTo(other); - states.set(state); - } - - - @Override - public Evaluator fork() { - return fork(states.get()); - } - - /** Creates a new instance initialized with current state that will become the initial state of created instance. - * @param state The initial state. - * @return a new evaluator of the same class as this, this the same view point, and initialized with the state. - */ - protected abstract HbAbstractIncrementalSimplifiedEvaluator fork(HbIncrementalState state); - - @Override - public void init(B board) { - states.clear(); - states.set(new HbIncrementalState(getExplorer(board))); - } - - @Override - public void prepareMove(B board, M move) { - if (moveData.update(move, board)) { - buildToCommit(); - toCommit.update(moveData); - } - } - - private void buildToCommit() { - final HbIncrementalState current = states.get(); - states.next(); - toCommit = states.get(); - states.previous(); - current.copyTo(toCommit); - } - - @Override - public void commitMove() { - states.next(); - states.set(toCommit); - } - - @Override - public void unmakeMove() { - states.previous(); - } - - @Override - public int evaluateAsWhite(B board) { - return states.get().evaluateAsWhite(); - } - - HbIncrementalState getState() { - return states.get(); - } -} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java deleted file mode 100644 index ecd3e71..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbBasicState.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.fathzer.jchess.chesslib.ai.eval.hbpg; - -import static com.fathzer.chess.utils.Pieces.KING; - -import com.fathzer.chess.utils.adapters.BoardExplorer; - -/** The state of the evaluator. - */ -class HbBasicState extends HbFastPhaseDetector { - int points; - int whiteKingIndex; - int blackKingIndex; - - HbBasicState() { - super(); - } - - void copyTo(HbBasicState other) { - super.copyTo(other); - other.points = points; - other.blackKingIndex = blackKingIndex; - other.whiteKingIndex = whiteKingIndex; - } - - HbBasicState(BoardExplorer explorer) { - this.points = 0; - do { - final int p = explorer.getPiece(); - add(p); - final int kind = Math.abs(p); - final int index = explorer.getIndex(); - final boolean isBlack = p<0; - if (kind!=KING) { - int inc = HbSimplifiedEvaluatorBase.getRawValue(kind); - inc += HbSimplifiedEvaluatorBase.getPositionValue(kind, isBlack, index); - if (isBlack) { - points -= inc; - } else { - points += inc; - } - } else if (isBlack) { - this.blackKingIndex = index; - } else { - this.whiteKingIndex = index; - } - } while (explorer.next()); - } - - int evaluateAsWhite() { - return points + HbSimplifiedEvaluatorBase.getKingPositionsValue(whiteKingIndex, blackKingIndex, getPhase()); - } -} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java deleted file mode 100644 index 14beee7..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbFastPhaseDetector.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.fathzer.jchess.chesslib.ai.eval.hbpg; - -import static com.fathzer.chess.utils.Pieces.KING; - -/** A class that tracks the current phase. - */ -class HbFastPhaseDetector { - private static final long BLACK_QUEEN_VALUE = 0x01L; - private static final long BLACK_QUEEN_MASK = 0xFFL; - private static final long WHITE_QUEEN_VALUE = 0x0100L; - private static final long WHITE_QUEEN_MASK = 0xFF00L; - private static final long BLACK_ROOK_VALUE = 0x010000L; - private static final long BLACK_ROOK_MASK = 0xFF0000L; - private static final long WHITE_ROOK_VALUE = 0x01000000L; - private static final long WHITE_ROOK_MASK = 0xFF000000L; - private static final long BLACK_MINOR_VALUE = 0x0100000000L; - private static final long BLACK_MINOR_MASK = 0xFF00000000L; - private static final long WHITE_MINOR_VALUE = 0x010000000000L; - private static final long WHITE_MINOR_MASK = 0xFF0000000000L; - - private static final long[] PIECE_KIND_TO_VALUES = new long[] {0L, BLACK_QUEEN_VALUE, BLACK_ROOK_VALUE, BLACK_MINOR_VALUE, BLACK_MINOR_VALUE, 0L, 0L, 0L, WHITE_MINOR_VALUE, WHITE_MINOR_VALUE, WHITE_ROOK_VALUE, WHITE_QUEEN_VALUE, 0L}; - - private long state; - - void add(int piece) { - state += PIECE_KIND_TO_VALUES[piece + KING]; - } - - void remove(int piece) { - state -= PIECE_KIND_TO_VALUES[piece + KING]; - } - - HbPhase getPhase() { - final boolean whiteQueen = (state & WHITE_QUEEN_MASK) != 0L; - final boolean blackQueen = (state & BLACK_QUEEN_MASK) != 0L; - if (!blackQueen && !whiteQueen) { - return HbPhase.END_GAME; - } - if ((blackQueen && (hasBlackRook() || hasManyBlackMinor())) || (whiteQueen && (hasWhiteRook() || hasManyWhiteMinor()))) { - return HbPhase.MIDDLE_GAME; - } - return HbPhase.END_GAME; - } - - boolean hasWhiteRook() { - return (state & WHITE_ROOK_MASK) != 0; - } - - boolean hasBlackRook() { - return (state & BLACK_ROOK_MASK) != 0; - } - - boolean hasManyBlackMinor() { - return (state & BLACK_MINOR_MASK) > BLACK_MINOR_VALUE; - } - - boolean hasManyWhiteMinor() { - return (state & WHITE_MINOR_MASK) > WHITE_MINOR_VALUE; - } - - void copyTo(HbFastPhaseDetector other) { - other.state = state; - } -} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java deleted file mode 100644 index 5c37359..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbIncrementalState.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.fathzer.jchess.chesslib.ai.eval.hbpg; - -import static com.fathzer.chess.utils.Pieces.KING; -import static com.fathzer.chess.utils.Pieces.PAWN; -import static com.fathzer.chess.utils.Pieces.ROOK; -import static com.fathzer.jchess.chesslib.ai.eval.hbpg.HbSimplifiedEvaluatorBase.getPositionValue; -import static com.fathzer.jchess.chesslib.ai.eval.hbpg.HbSimplifiedEvaluatorBase.getRawValue; - -import com.fathzer.chess.utils.adapters.BoardExplorer; -import com.fathzer.chess.utils.adapters.MoveData; - -/** The current state of a {@link HbAbstractIncrementalSimplifiedEvaluator} - */ -public class HbIncrementalState extends HbBasicState { - HbIncrementalState() { - super(); - } - - HbIncrementalState(BoardExplorer exp) { - super(exp); - } - - void update(MoveData move) { - points += getIncrement(move); - } - - private int getIncrement(MoveData move) { - final boolean isBlack = move.getMovingPiece()<0; - int moving = Math.abs(move.getMovingPiece()); - final int movingIndex = move.getMovingIndex(); - int inc; - if (moving==KING) { - // The position value of kings is not evaluated incrementally - int rookIndex = move.getCastlingRookIndex(); - if (rookIndex>=0) { - // It's a castling move, update rook positions values - inc = getPositionValue(ROOK, isBlack, move.getCastlingRookDestinationIndex()) - getPositionValue(ROOK, isBlack, rookIndex); - } else { - inc = doCapture(isBlack, move); - } - // Update king's position - if (isBlack) { - this.blackKingIndex = move.getMovingDestination(); - } else { - this.whiteKingIndex = move.getMovingDestination(); - } - } else { - // Remove the position value of the moving piece - inc = - getPositionValue(moving, isBlack, movingIndex); - final int promoType = move.getPromotionType(); - if (promoType!=0) { - // If promotion, add raw value points, update phase - inc += getRawValue(promoType)-getRawValue(PAWN); - moving = promoType; - add(isBlack ? -promoType : promoType); - } - inc += doCapture(isBlack, move); - // Adds the position value of the - inc += getPositionValue(moving, isBlack, move.getMovingDestination()); - } - return isBlack ? -inc : +inc; - } - - private int doCapture(boolean isBlack, MoveData move) { - int captured = move.getCapturedType(); - if (captured!=0) { - // A piece was captured - // Update the phase detector - remove(isBlack ? captured : -captured); - // Then add its raw value and its position value - return getRawValue(captured) + getPositionValue(captured, !isBlack, move.getCapturedIndex()); - } else { - return 0; - } - } -} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java deleted file mode 100644 index 276d5cd..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbMyFirstEvaluator.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fathzer.jchess.chesslib.ai.eval.hbpg; - -import com.fathzer.games.ai.evaluation.StaticEvaluator; -import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; -import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; -import com.github.bhlangonijr.chesslib.Board; -import com.github.bhlangonijr.chesslib.move.Move; - - -public class HbMyFirstEvaluator implements StaticEvaluator, ZeroSumEvaluator { - private final HbSimplifiedEvaluator ev = new HbSimplifiedEvaluator(); - - @Override - public int evaluateAsWhite(ChessLibMoveGenerator board) { - // Calculer l'évaluation de base - int baseEvaluation; -// synchronized (this) { // Alternative à la méthode fork - ev.init(board); - baseEvaluation = ev.evaluateAsWhite(board); -// } - // Tu peux ajouter ce qui concerne les chaines de pions, mauvais/bon fous, etc à l'évaluation de base ... - return baseEvaluation; - } - - @Override - public StaticEvaluator fork() { - // Attention : SimplifiedEvaluator n'est pas thread safe, ce qui est généralement le cas des évaluateurs statiques (d'où l'implémentation par défaut de fork qui renvoie this). - // Pour éviter les pb de threading, soit on crée un évaluateur par thread comme ici, soit l'usage du SimplifiedEvaluator doit être protégé par un synchronized (pas performant). - return new HbMyFirstEvaluator(); - } - - - public static void main(String[] args) { - // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer - ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(new Board()); - mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); - System.out.println(new HbMyFirstEvaluator().evaluate(mvg)); - } -} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java deleted file mode 100644 index d75ca9d..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbPhase.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fathzer.jchess.chesslib.ai.eval.hbpg; - -/** The phases of a game. - *
There's only two phases in the simplified evaluator, and not three as we could expect. - * The idea is, in the opening phase, the evaluation function should be replaced by an opening library, the middle game starts when the position - * is no more in the library. - */ -enum HbPhase { - /** Middle of the game.*/ - MIDDLE_GAME, - /** End of the game */ - END_GAME -} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java deleted file mode 100644 index 7dbb502..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluator.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.fathzer.jchess.chesslib.ai.eval.hbpg; - -import com.fathzer.chess.utils.adapters.MoveData; -import com.fathzer.jchess.chesslib.ChessLibExplorerBuilder; -import com.fathzer.jchess.chesslib.ChessLibMoveData; -import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; -import com.github.bhlangonijr.chesslib.move.Move; - -public class HbSimplifiedEvaluator extends HbAbstractIncrementalSimplifiedEvaluator implements ChessLibExplorerBuilder { - private HbSimplifiedEvaluator(HbIncrementalState state) { - super(state); - } - - public HbSimplifiedEvaluator() { - super(); - } - - @Override - public MoveData get() { - return new ChessLibMoveData(); - } - - @Override - protected HbAbstractIncrementalSimplifiedEvaluator fork(HbIncrementalState state) { - return new HbSimplifiedEvaluator(state); - } -} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java deleted file mode 100644 index 102da40..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/HbSimplifiedEvaluatorBase.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.fathzer.jchess.chesslib.ai.eval.hbpg; - -import com.fathzer.chess.utils.Pieces; -import com.fathzer.chess.utils.adapters.BoardExplorer; -import com.fathzer.chess.utils.adapters.BoardExplorerBuilder; -import com.fathzer.games.MoveGenerator; - -abstract class HbSimplifiedEvaluatorBase> implements BoardExplorerBuilder { - private static final int[] PIECE_VALUES = {0, 100, 320, 330, 500, 900, 20000}; - private static final int[] KING_MID_GAME_EVAL = new int[] { - -30,-40,-40,-50,-50,-40,-40,-30, - -30,-40,-40,-50,-50,-40,-40,-30, - -30,-40,-40,-50,-50,-40,-40,-30, - -30,-40,-40,-50,-50,-40,-40,-30, - -20,-30,-30,-40,-40,-30,-30,-20, - -10,-20,-20,-20,-20,-20,-20,-10, - 20, 20, 0, 0, 0, 0, 20, 20, - 20, 30, 10, 0, 0, 10, 30, 20}; - - private static final int[] KING_END_GAME_EVAL = new int[] { - -50,-40,-30,-20,-20,-30,-40,-50, - -30,-20,-10, 0, 0,-10,-20,-30, - -30,-10, 20, 30, 30, 20,-10,-30, - -30,-10, 30, 40, 40, 30,-10,-30, - -30,-10, 30, 40, 40, 30,-10,-30, - -30,-10, 20, 30, 30, 20,-10,-30, - -30,-30, 0, 0, 0, 0,-30,-30, - -50,-30,-30,-30,-30,-30,-30,-50}; - - private static final int [][] PIECE_POSITION_VALUES = new int[][] { - // Just to have index equals to piece type codes - new int[0], - // PAWN - new int[] { - 0, 0, 0, 0, 0, 0, 0, 0, - 50, 50, 50, 50, 50, 50, 50, 50, - 10, 10, 20, 30, 30, 20, 10, 10, - 5, 5, 10, 25, 25, 10, 5, 5, - 0, 0, 0, 20, 20, 0, 0, 0, - 5, -5,-10, 0, 0,-10, -5, 5, - 5, 10, 10,-20,-20, 10, 10, 5, - 0, 0, 0, 0, 0, 0, 0, 0}, - // KNIGHT - new int[] { - -50,-40,-30,-30,-30,-30,-40,-50, - -40,-20, 0, 0, 0, 0,-20,-40, - -30, 0, 10, 15, 15, 10, 0,-30, - -30, 5, 15, 20, 20, 15, 5,-30, - -30, 0, 15, 20, 20, 15, 0,-30, - -30, 5, 10, 15, 15, 10, 5,-30, - -40,-20, 0, 5, 5, 0,-20,-40, - -50,-40,-30,-30,-30,-30,-40,-50}, - // BISHOP - new int[] { - -20,-10,-10,-10,-10,-10,-10,-20, - -10, 0, 0, 0, 0, 0, 0,-10, - -10, 0, 5, 10, 10, 5, 0,-10, - -10, 5, 5, 10, 10, 5, 5,-10, - -10, 0, 10, 10, 10, 10, 0,-10, - -10, 10, 10, 10, 10, 10, 10,-10, - -10, 5, 0, 0, 0, 0, 5,-10, - -20,-10,-10,-10,-10,-10,-10,-20}, - // ROOK - new int[] { - 0, 0, 0, 0, 0, 0, 0, 0, - 5, 10, 10, 10, 10, 10, 10, 5, - -5, 0, 0, 0, 0, 0, 0, -5, - -5, 0, 0, 0, 0, 0, 0, -5, - -5, 0, 0, 0, 0, 0, 0, -5, - -5, 0, 0, 0, 0, 0, 0, -5, - -5, 0, 0, 0, 0, 0, 0, -5, - 0, 0, 0, 5, 5, 0, 0, 0}, - // QUEEN - new int[] { - -20,-10,-10, -5, -5,-10,-10,-20, - -10, 0, 0, 0, 0, 0, 0,-10, - -10, 0, 5, 5, 5, 5, 0,-10, - -5, 0, 5, 5, 5, 5, 0, -5, - 0, 0, 5, 5, 5, 5, 0, -5, - -10, 5, 5, 5, 5, 5, 0,-10, - -10, 0, 5, 0, 0, 0, 0,-10, - -20,-10,-10, -5, -5,-10,-10,-20 - }}; - - HbSimplifiedEvaluatorBase() { - super(); - } - - static int getPositionValue(int type, boolean black, int index) { - return getPositionValue(PIECE_POSITION_VALUES[type], index, black); - } - - static int getRawValue(int type) { - return PIECE_VALUES[type]; - } - - static int getKingPositionsValue(int whiteIndex, int blackIndex, HbPhase phase) { - final int[] kingMap = phase==HbPhase.MIDDLE_GAME ? KING_MID_GAME_EVAL : KING_END_GAME_EVAL; - return getPositionValue(kingMap, whiteIndex, false) - getPositionValue(kingMap, blackIndex, true); - } - - private static int getPositionValue(int[] positionMap, int index, boolean black) { - if (black) { - final int row = 7 - index/8; - final int col = index%8; - index = row*8 + col; - } - return positionMap[index]; - } - - /** Gets the position value associated with a type of piece and an index. - * @param type The piece type as define in {@link Pieces} - * @param index The index of the piece on the board as defined in {@link BoardExplorer} - * @return an integer - */ - static int getPositionValue(int type, int index) { - return PIECE_POSITION_VALUES[type][index]; - } -} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java deleted file mode 100644 index 327ea90..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package com.fathzer.jchess.chesslib.ai.eval.hbpg; \ No newline at end of file From f67222a23f8d7c779dedc9e2fab544c5adf215d1 Mon Sep 17 00:00:00 2001 From: herve Date: Mon, 7 Oct 2024 03:45:06 +0200 Subject: [PATCH 34/55] nettoyage, refactoring --- pom.xml | 2 +- .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 83 ++----------- .../eval/hbpg2/Hb2ElementaryBasicState.java | 110 ++++++++++++++++++ .../ai/eval/hbpg2/Hb2FastPhaseDetector.java | 29 ----- .../chesslib/ai/eval/hbpg2/Hb2Phase.java | 17 +-- 5 files changed, 127 insertions(+), 114 deletions(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java diff --git a/pom.xml b/pom.xml index 0b7a9b2..978f9c9 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. diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index 6054f94..a78f9ed 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -1,21 +1,13 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg2; -import static com.fathzer.chess.utils.Pieces.KING; + import com.fathzer.chess.utils.adapters.BoardExplorer; import com.github.bhlangonijr.chesslib.Board; /** The state of the evaluator. */ -class Hb2BasicState extends Hb2FastPhaseDetector { - int pointsMg; - int pointsEg; - int pointsPosMg; - int pointsPosEg; - int whiteKingIndex; - int blackKingIndex; - int computedPhase; - Board board; +class Hb2BasicState extends Hb2ElementaryBasicState { Hb2BasicState() { @@ -24,75 +16,24 @@ class Hb2BasicState extends Hb2FastPhaseDetector { void copyTo(Hb2BasicState other) { super.copyTo(other); - other.pointsMg = pointsMg; - other.pointsEg= pointsEg; - other.pointsPosMg = pointsPosMg; - other.pointsPosEg= pointsPosEg; - other.blackKingIndex = blackKingIndex; - other.whiteKingIndex = whiteKingIndex; - other.computedPhase = computedPhase; - other.board = board; +// other.pointsMg = pointsMg; +// other.pointsEg= pointsEg; +// other.pointsPosMg = pointsPosMg; +// other.pointsPosEg= pointsPosEg; +// other.blackKingIndex = blackKingIndex; +// other.whiteKingIndex = whiteKingIndex; +// other.computedPhase = computedPhase; +// other.board = board; } Hb2BasicState(BoardExplorer explorer, Board board) { - this.board = board; - this.pointsMg = 0; - this.pointsEg = 0; - this.pointsPosMg = 0; - this.pointsPosEg = 0; - this.computedPhase = 0; - do { - final int p = explorer.getPiece(); -// add(p); - final int kind = Math.abs(p); - final int index = explorer.getIndex(); - final boolean isBlack = p<0; - if (kind!=KING) { - int incMg = Hb2SimplifiedEvaluatorBase.getRawValueMg(kind); - int incEg = Hb2SimplifiedEvaluatorBase.getRawValueEg(kind); - if (isBlack) { - pointsMg -= incMg; - pointsEg -= incEg; - } else { - pointsMg += incMg; - pointsEg += incEg; - } - } else if (isBlack) { - this.blackKingIndex = index; - } else { - this.whiteKingIndex = index; - } - - - - if (kind!=KING) { - int incPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(kind, isBlack, index); - int incPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(kind, isBlack, index); - if (isBlack) { - pointsPosMg -= incPosMg; - pointsPosEg -= incPosEg; - } else { - pointsPosMg += incPosMg; - pointsPosEg += incPosEg; - } - } - computedPhase += Hb2Phase.getPhaseValue(kind); - } while (explorer.next()); + super(explorer, board); + } - int evaluateAsWhite() { - // pointsMg = material only! The white material minus the black material in the middlegame. - // pointsEg = material only! The white material minus the black material in the endgame. - int phase = getPhaseForTaperedEval(computedPhase); -// int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); -// int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); - int evalMg = pointsMg + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); - int evalEg = pointsEg + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); - return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); - } } \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java new file mode 100644 index 0000000..a1f244c --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java @@ -0,0 +1,110 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +import static com.fathzer.chess.utils.Pieces.KING; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.github.bhlangonijr.chesslib.Board; + +/** The elementary state of the evaluator. + */ + +class Hb2ElementaryBasicState { + + int pointsMg; + int pointsEg; + int pointsPosMg; + int pointsPosEg; + int whiteKingIndex; + int blackKingIndex; + int computedPhase; + Board board; + + + Hb2ElementaryBasicState() { + super(); + } + + void copyTo(Hb2BasicState other) { + + other.pointsMg = pointsMg; + other.pointsEg= pointsEg; + other.pointsPosMg = pointsPosMg; + other.pointsPosEg= pointsPosEg; + other.blackKingIndex = blackKingIndex; + other.whiteKingIndex = whiteKingIndex; + other.computedPhase = computedPhase; + other.board = board; + + } + + Hb2ElementaryBasicState(BoardExplorer explorer, Board board) { + this.board = board; + this.pointsMg = 0; + this.pointsEg = 0; + this.pointsPosMg = 0; + this.pointsPosEg = 0; + this.computedPhase = 0; + do { + final int p = explorer.getPiece(); + + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind!=KING) { + int incMg = Hb2SimplifiedEvaluatorBase.getRawValueMg(kind); + int incEg = Hb2SimplifiedEvaluatorBase.getRawValueEg(kind); + if (isBlack) { + pointsMg -= incMg; + pointsEg -= incEg; + } else { + pointsMg += incMg; + pointsEg += incEg; + } + } else if (isBlack) { + this.blackKingIndex = index; + } else { + this.whiteKingIndex = index; + } + + + + if (kind!=KING) { + int incPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(kind, isBlack, index); + int incPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(kind, isBlack, index); + if (isBlack) { + pointsPosMg -= incPosMg; + pointsPosEg -= incPosEg; + } else { + pointsPosMg += incPosMg; + pointsPosEg += incPosEg; + } + } + computedPhase += Hb2Phase.getPhaseValue(kind); + } while (explorer.next()); + } + + + + + int getPhaseForTaperedEval(int computedPhaseValue) { + return (Math.min(computedPhaseValue, Hb2Phase.PHASE_UPPER_BOUND)); + } + + + int evaluateAsWhite() { + + // pointsMg = material only! The white material minus the black material in the middlegame. + // pointsEg = material only! The white material minus the black material in the endgame. +// int phase = Hb2Phase.getPhaseForTaperedEval(computedPhase); + // gets the borned phase: necessary for the tapered evaluation + int phase= (computedPhase > Hb2Phase.PHASE_UPPER_BOUND?Hb2Phase.PHASE_UPPER_BOUND:computedPhase); +// int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); +// int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); + int evalMg = pointsMg + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); + int evalEg = pointsEg + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); + return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); + } + + + +} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java deleted file mode 100644 index 6b6c880..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2FastPhaseDetector.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.fathzer.jchess.chesslib.ai.eval.hbpg2; - -/** A class that tracks the current phase. - */ -class Hb2FastPhaseDetector { - -// private long state; - - -// void add(int piece) { -//// state += PIECE_KIND_TO_VALUES[piece + KING]; -// } -// -// void remove(int piece) { -//// state -= PIECE_KIND_TO_VALUES[piece + KING]; -// } - - int getPhaseForTaperedEval(int computedPhaseValue) { - return (Math.min(computedPhaseValue, Hb2Phase.PHASE_UPPER_BOUND)); - } - - - - - - void copyTo(Hb2FastPhaseDetector other) { -// other.state = state; - } -} \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java index b23c4b8..373a9aa 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2Phase.java @@ -1,6 +1,6 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg2; -public class Hb2Phase { +class Hb2Phase { // Beware, what follows has nothing to do with com.fathzer.chess.utils.Pieces.VALUES, since the Queen is evaluated 9 instead of 10, in Pieces.VALUES // Pieces.VALUE is useful only for comparing / ordering moves, by the way @@ -15,26 +15,17 @@ public class Hb2Phase { public static final int PHASE_UPPER_BOUND = NB_INCR_PHASE; - private int phase; - public Hb2Phase(int computedPhaseValue) { - this.phase = computedPhaseValue; + public static int getPhaseForTaperedEval(int computedPhaseValue) { + return (Math.min(computedPhaseValue, Hb2Phase.PHASE_UPPER_BOUND)); } - + public static int getPhaseValue(int indexPieceType) { return(PHASE_VALUES[indexPieceType]); } - public int getPhase() { - return phase; - } - - - public void setPhase(int phase) { - this.phase = phase; - } From b73e44ac0821706a4d23a45aadc915fe1331b927 Mon Sep 17 00:00:00 2001 From: herve Date: Mon, 7 Oct 2024 04:58:39 +0200 Subject: [PATCH 35/55] =?UTF-8?q?Evaluation=20de=20la=20structure=20de=20p?= =?UTF-8?q?ions:=20calcul=20du=20nombre=20de=20pions=20noirs=20par=20colon?= =?UTF-8?q?ne,=20du=20nombre=20de=20pions=20blancs=20par=20colonne.=20Ca?= =?UTF-8?q?=20servira=20pour=20les=20pions=20doubl=C3=A9s,=20les=20pions?= =?UTF-8?q?=20pass=C3=A9s,=20etc...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 17 +++++- .../ai/eval/hbpg2/Hb2ChessConstants.java | 7 +++ .../eval/hbpg2/Hb2ElementaryBasicState.java | 8 +-- .../additional/ChessEvalAdditionalElems.java | 34 ++++++++++++ .../eval/hbpg2/additional/PawnsStrucEval.java | 53 +++++++++++++++++++ .../eval/hbpg2/additional/package-info.java | 1 + 6 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/package-info.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index a78f9ed..cbf5da7 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -3,19 +3,22 @@ import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.additional.ChessEvalAdditionalElems; import com.github.bhlangonijr.chesslib.Board; /** The state of the evaluator. */ class Hb2BasicState extends Hb2ElementaryBasicState { - + private ChessEvalAdditionalElems chessEvalAdditionalElems; Hb2BasicState() { super(); } - void copyTo(Hb2BasicState other) { + public void copyTo(Hb2BasicState other) { super.copyTo(other); + chessEvalAdditionalElems.copyTo(other.chessEvalAdditionalElems); + // other.pointsMg = pointsMg; // other.pointsEg= pointsEg; // other.pointsPosMg = pointsPosMg; @@ -31,9 +34,19 @@ void copyTo(Hb2BasicState other) { Hb2BasicState(BoardExplorer explorer, Board board) { super(explorer, board); + chessEvalAdditionalElems = new ChessEvalAdditionalElems(explorer, board); + } + public ChessEvalAdditionalElems getChessEvalAdditionalElems() { + return chessEvalAdditionalElems; + } + + public void setChessEvalAdditionalElems(ChessEvalAdditionalElems chessEvalAdditionalElems) { + this.chessEvalAdditionalElems = chessEvalAdditionalElems; + } + } \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java new file mode 100644 index 0000000..2d3b29e --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java @@ -0,0 +1,7 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +public abstract class Hb2ChessConstants { + public static final int NB_RAWS = 8; + public static final int NB_COLS = 8; + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java index a1f244c..d34af93 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java @@ -24,7 +24,7 @@ class Hb2ElementaryBasicState { super(); } - void copyTo(Hb2BasicState other) { + public void copyTo(Hb2ElementaryBasicState other) { other.pointsMg = pointsMg; other.pointsEg= pointsEg; @@ -86,9 +86,9 @@ void copyTo(Hb2BasicState other) { - int getPhaseForTaperedEval(int computedPhaseValue) { - return (Math.min(computedPhaseValue, Hb2Phase.PHASE_UPPER_BOUND)); - } +// int getPhaseForTaperedEval(int computedPhaseValue) { +// return (Math.min(computedPhaseValue, Hb2Phase.PHASE_UPPER_BOUND)); +// } int evaluateAsWhite() { diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java new file mode 100644 index 0000000..96de4b5 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java @@ -0,0 +1,34 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2.additional; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.github.bhlangonijr.chesslib.Board; + + +/** This class contains all the chess evaluation stuff that is not in the elementary state of the evaluator. + */ + +public class ChessEvalAdditionalElems { + + private PawnsStrucEval pawnsStructEval; + + public ChessEvalAdditionalElems(BoardExplorer explorer, Board board) { + pawnsStructEval = new PawnsStrucEval(explorer, board); + } + + public void copyTo(ChessEvalAdditionalElems other) { + pawnsStructEval.copyTo(other.pawnsStructEval); + + } + + public PawnsStrucEval getPawnsStructEval() { + return pawnsStructEval; + } + + public void setPawnsStructEval(PawnsStrucEval pawnsStructEval) { + this.pawnsStructEval = pawnsStructEval; + } + + + + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java new file mode 100644 index 0000000..eca29ad --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -0,0 +1,53 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2.additional; + +import static com.fathzer.chess.utils.Pieces.PAWN; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; + +import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.Square; + +public class PawnsStrucEval { + private Board board; + + private int[] tabNbWhitePawnsByCol = new int[Hb2ChessConstants.NB_COLS]; + private int[] tabNbBlackPawnsByCol = new int[Hb2ChessConstants.NB_COLS]; + + public PawnsStrucEval(BoardExplorer explorer, Board board) { + super(); + this.board = board; + for (int i= 0; i < Hb2ChessConstants.NB_COLS; i++) { + tabNbWhitePawnsByCol[i] = 0; + tabNbBlackPawnsByCol[i] = 0; + } + + do { + final int p = explorer.getPiece(); + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind==PAWN) { + Square pawnSquare = Square.squareAt(index); + int columnPawn = pawnSquare.getFile().ordinal(); // 0 for a column, 1 for b column, etc... + if (isBlack) { + tabNbBlackPawnsByCol[columnPawn]++; + } else { + tabNbWhitePawnsByCol[columnPawn]++; + } + + + } + } while (explorer.next()); + + + } + + void copyTo(PawnsStrucEval other) { + other.board = board; + other.tabNbBlackPawnsByCol = tabNbBlackPawnsByCol.clone(); // not a shallow copy!!!! + other.tabNbWhitePawnsByCol = tabNbWhitePawnsByCol.clone(); // not a shallow copy!!!! + } + + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/package-info.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/package-info.java new file mode 100644 index 0000000..58f986f --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/package-info.java @@ -0,0 +1 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2.additional; \ No newline at end of file From aedc083e8fb99f2fe0cd4c5edc6c39473e89ee4b Mon Sep 17 00:00:00 2001 From: herve Date: Wed, 9 Oct 2024 08:32:43 +0200 Subject: [PATCH 36/55] Efficiency is paramount! --- .../ai/eval/hbpg2/additional/PawnsStrucEval.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index eca29ad..93f3ab3 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -6,7 +6,7 @@ import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; import com.github.bhlangonijr.chesslib.Board; -import com.github.bhlangonijr.chesslib.Square; + public class PawnsStrucEval { private Board board; @@ -26,11 +26,12 @@ public PawnsStrucEval(BoardExplorer explorer, Board board) { final int p = explorer.getPiece(); final int kind = Math.abs(p); final int index = explorer.getIndex(); - final boolean isBlack = p<0; + final boolean isPieceBlack = p<0; if (kind==PAWN) { - Square pawnSquare = Square.squareAt(index); - int columnPawn = pawnSquare.getFile().ordinal(); // 0 for a column, 1 for b column, etc... - if (isBlack) { + + final int columnPawn = index%Hb2ChessConstants.NB_COLS; + + if (isPieceBlack) { tabNbBlackPawnsByCol[columnPawn]++; } else { tabNbWhitePawnsByCol[columnPawn]++; From 5ae67a7c21eaf5522da1210d8f8bf1ec96e5ac56 Mon Sep 17 00:00:00 2001 From: herve Date: Thu, 24 Oct 2024 11:05:24 +0200 Subject: [PATCH 37/55] Doubled pawns are hit with a penalty --- .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 22 +++++- .../ai/eval/hbpg2/Hb2ChessConstants.java | 3 + .../eval/hbpg2/Hb2ElementaryBasicState.java | 26 +++---- .../ai/eval/hbpg2/Hb2IncrementalState.java | 2 +- .../additional/ChessEvalAdditionalElems.java | 18 +++++ .../eval/hbpg2/additional/PawnsStrucEval.java | 69 ++++++++++++++++++- .../jchess/chesslib/ai/HBThreeMovesTest2.java | 3 +- .../chesslib/ai/HBThreeMovesTest2Bis.java | 34 +++++++++ 8 files changed, 157 insertions(+), 20 deletions(-) create mode 100644 src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2Bis.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index cbf5da7..fe1329a 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -3,6 +3,7 @@ import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.jchess.chesslib.ChessLibBoardExplorer; import com.fathzer.jchess.chesslib.ai.eval.hbpg2.additional.ChessEvalAdditionalElems; import com.github.bhlangonijr.chesslib.Board; @@ -17,7 +18,8 @@ class Hb2BasicState extends Hb2ElementaryBasicState { public void copyTo(Hb2BasicState other) { super.copyTo(other); - chessEvalAdditionalElems.copyTo(other.chessEvalAdditionalElems); + other.chessEvalAdditionalElems = new ChessEvalAdditionalElems(this.chessEvalAdditionalElems); + // other.pointsMg = pointsMg; // other.pointsEg= pointsEg; @@ -34,7 +36,7 @@ public void copyTo(Hb2BasicState other) { Hb2BasicState(BoardExplorer explorer, Board board) { super(explorer, board); - chessEvalAdditionalElems = new ChessEvalAdditionalElems(explorer, board); + chessEvalAdditionalElems = new ChessEvalAdditionalElems(new ChessLibBoardExplorer(board), board); } @@ -47,6 +49,22 @@ public void setChessEvalAdditionalElems(ChessEvalAdditionalElems chessEvalAdditi this.chessEvalAdditionalElems = chessEvalAdditionalElems; } + + int evaluateAsWhite() { + + // pointsMg = material only! The white material minus the black material in the middlegame. + // pointsEg = material only! The white material minus the black material in the endgame. +// int phase = Hb2Phase.getPhaseForTaperedEval(computedPhase); + // gets the borned phase: necessary for the tapered evaluation + int phase= (computedPhase > Hb2Phase.PHASE_UPPER_BOUND?Hb2Phase.PHASE_UPPER_BOUND:computedPhase); +// int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); +// int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); + + int evalMg = pointsMg + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex) + chessEvalAdditionalElems.getContribMg(); + int evalEg = pointsEg + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex) + chessEvalAdditionalElems.getContribEg(); + + return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); + } } \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java index 2d3b29e..90cbe4b 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java @@ -3,5 +3,8 @@ public abstract class Hb2ChessConstants { public static final int NB_RAWS = 8; public static final int NB_COLS = 8; + + public static final int MALUS_DOUBLED_PAWN_MG = -20; + public static final int MALUS_DOUBLED_PAWN_EG = -40; } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java index d34af93..2ed7511 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java @@ -91,19 +91,19 @@ public void copyTo(Hb2ElementaryBasicState other) { // } - int evaluateAsWhite() { - - // pointsMg = material only! The white material minus the black material in the middlegame. - // pointsEg = material only! The white material minus the black material in the endgame. -// int phase = Hb2Phase.getPhaseForTaperedEval(computedPhase); - // gets the borned phase: necessary for the tapered evaluation - int phase= (computedPhase > Hb2Phase.PHASE_UPPER_BOUND?Hb2Phase.PHASE_UPPER_BOUND:computedPhase); -// int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); -// int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); - int evalMg = pointsMg + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); - int evalEg = pointsEg + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); - return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); - } +// int evaluateAsWhite() { +// +// // pointsMg = material only! The white material minus the black material in the middlegame. +// // pointsEg = material only! The white material minus the black material in the endgame. +//// int phase = Hb2Phase.getPhaseForTaperedEval(computedPhase); +// // gets the borned phase: necessary for the tapered evaluation +// int phase= (computedPhase > Hb2Phase.PHASE_UPPER_BOUND?Hb2Phase.PHASE_UPPER_BOUND:computedPhase); +//// int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); +//// int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); +// int evalMg = pointsMg + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); +// int evalEg = pointsEg + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); +// return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); +// } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index 5c5f6dc..61ab3c6 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -21,7 +21,7 @@ public class Hb2IncrementalState extends Hb2BasicState { super(exp, board); } - + // HBR TODO FONTOS 24102024. S'occuper de l'incrémental en structure de pions (pions doublés, pour l'instant) void update(MoveData move) { pointsMg += getIncrementMg(move); diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java index 96de4b5..929d6b4 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java @@ -11,6 +11,11 @@ public class ChessEvalAdditionalElems { private PawnsStrucEval pawnsStructEval; + public ChessEvalAdditionalElems(ChessEvalAdditionalElems ceae) { + pawnsStructEval = new PawnsStrucEval(ceae.pawnsStructEval); + } + + public ChessEvalAdditionalElems(BoardExplorer explorer, Board board) { pawnsStructEval = new PawnsStrucEval(explorer, board); } @@ -28,6 +33,19 @@ public void setPawnsStructEval(PawnsStrucEval pawnsStructEval) { this.pawnsStructEval = pawnsStructEval; } + public int getContribMg() { + int contrib = 0; + contrib+= pawnsStructEval.getContribMg(); + return(contrib); + + } + + public int getContribEg() { + int contrib = 0; + contrib+= pawnsStructEval.getContribEg(); + return(contrib); + + } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index 93f3ab3..cf1bdca 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -2,6 +2,8 @@ import static com.fathzer.chess.utils.Pieces.PAWN; +import java.util.Arrays; + import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; @@ -11,11 +13,27 @@ public class PawnsStrucEval { private Board board; - private int[] tabNbWhitePawnsByCol = new int[Hb2ChessConstants.NB_COLS]; - private int[] tabNbBlackPawnsByCol = new int[Hb2ChessConstants.NB_COLS]; + private int[] tabNbWhitePawnsByCol; + private int[] tabNbBlackPawnsByCol; + + + public PawnsStrucEval() { + tabNbWhitePawnsByCol = new int[Hb2ChessConstants.NB_COLS]; + tabNbBlackPawnsByCol = new int[Hb2ChessConstants.NB_COLS]; + } + + public PawnsStrucEval(PawnsStrucEval pse) { + // Since it's an array of integers, the copy is not a shallow copy + tabNbWhitePawnsByCol = Arrays.copyOf(pse.tabNbWhitePawnsByCol, Hb2ChessConstants.NB_COLS); + // Since it's an array of integers, the copy is not a shallow copy + tabNbBlackPawnsByCol = Arrays.copyOf(pse.tabNbBlackPawnsByCol, Hb2ChessConstants.NB_COLS); + + } public PawnsStrucEval(BoardExplorer explorer, Board board) { - super(); + this(); + + this.board = board; for (int i= 0; i < Hb2ChessConstants.NB_COLS; i++) { tabNbWhitePawnsByCol[i] = 0; @@ -50,5 +68,50 @@ void copyTo(PawnsStrucEval other) { other.tabNbWhitePawnsByCol = tabNbWhitePawnsByCol.clone(); // not a shallow copy!!!! } + public int getContribMg() { + + // white doubled pawns + int malusW = 0; + for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { + if (tabNbWhitePawnsByCol[i] > 1) { + malusW += tabNbWhitePawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWN_MG; + } + } + + // black doubled pawns + int malusB = 0; + for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { + if (tabNbBlackPawnsByCol[i] > 1) { + malusB += tabNbBlackPawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWN_MG; + } + } + return(malusW - malusB); + } + + + + + public int getContribEg() { + + // white doubled pawns + int malusW = 0; + for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { + if (tabNbWhitePawnsByCol[i] > 1) { + malusW += tabNbWhitePawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWN_EG; + } + } + + // black doubled pawns + int malusB = 0; + for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { + if (tabNbBlackPawnsByCol[i] > 1) { + malusB += tabNbBlackPawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWN_EG; + } + } + return(malusW - malusB); + + } + + } diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2.java index bc2df9f..55bfc77 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2.java @@ -18,7 +18,8 @@ class HBThreeMovesTest2 { void test() { final int depth = 6; final int bestMoveCount = 3; - final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; +// final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; // pions doublés dans le camp noir + final String fen = "r2k1r2/pp1b2p1/1b2Pnp1/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(Hb2SimplifiedEvaluator::new, depth); engine.getDeepeningPolicy().setSize(bestMoveCount); final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)).getBestMoves(); diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2Bis.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2Bis.java new file mode 100644 index 0000000..f1c5375 --- /dev/null +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2Bis.java @@ -0,0 +1,34 @@ +package com.fathzer.jchess.chesslib.ai; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fathzer.games.ai.evaluation.EvaluatedMove; +import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.uci.ChessLibEngine; +import com.github.bhlangonijr.chesslib.move.Move; + +class HBThreeMovesTest2Bis { + + @Test + void test() { + final int depth = 6; + final int bestMoveCount = 3; + final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; // pas de pions doublés +// final String fen = "r2k1r2/pp1b2p1/1b2Pnp1/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(Hb2SimplifiedEvaluator::new, depth); + engine.getDeepeningPolicy().setSize(bestMoveCount); + final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)).getBestMoves(); + System.out.println(moves); + for (int i=0;i<3;i++) { + EvaluatedMove move = moves.get(i); + List principalVariation = move.getPrincipalVariation(); + System.out.println(move+" -> "+principalVariation); + } + } + +} From 01449208b8278f845118efeb3a1816ec44db45e4 Mon Sep 17 00:00:00 2001 From: herve Date: Fri, 25 Oct 2024 07:01:13 +0200 Subject: [PATCH 38/55] =?UTF-8?q?Sp=C3=A9cifique=20=C3=A0=20OSX,=20apparem?= =?UTF-8?q?ment;=20mais=20sans=20effet=20n=C3=A9gatif=20sur=20d'autres=20p?= =?UTF-8?q?lateformes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- runConfigs/ChessLib-uci-engine (PerfTTest).launch | 1 + 1 file changed, 1 insertion(+) diff --git a/runConfigs/ChessLib-uci-engine (PerfTTest).launch b/runConfigs/ChessLib-uci-engine (PerfTTest).launch index 435ad64..8ae274b 100644 --- a/runConfigs/ChessLib-uci-engine (PerfTTest).launch +++ b/runConfigs/ChessLib-uci-engine (PerfTTest).launch @@ -15,6 +15,7 @@ + From 8f5557e1cfad89ba177611962c05691d74257659 Mon Sep 17 00:00:00 2001 From: herve Date: Fri, 25 Oct 2024 18:16:37 +0200 Subject: [PATCH 39/55] doubled pawns evaluation + 256MB HashTable + force all variations to max depth in deepening policy --- .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 2 +- .../ai/eval/hbpg2/Hb2IncrementalState.java | 7 +- .../ai/eval/hbpg2/Hb2MyFirstEvaluator.java | 7 +- .../additional/ChessEvalAdditionalElems.java | 5 ++ .../eval/hbpg2/additional/PawnsStrucEval.java | 65 ++++++++++++++++++- .../jchess/chesslib/uci/ChessLibEngine.java | 2 +- .../jchess/chesslib/ai/HBThreeMovesTest.java | 4 +- .../chesslib/ai/HBThreeMovesTest2Bis.java | 14 ++-- 8 files changed, 95 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index fe1329a..507a91c 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -10,7 +10,7 @@ /** The state of the evaluator. */ class Hb2BasicState extends Hb2ElementaryBasicState { - private ChessEvalAdditionalElems chessEvalAdditionalElems; + protected ChessEvalAdditionalElems chessEvalAdditionalElems; Hb2BasicState() { super(); diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index 61ab3c6..72be59f 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -21,16 +21,21 @@ public class Hb2IncrementalState extends Hb2BasicState { super(exp, board); } - // HBR TODO FONTOS 24102024. S'occuper de l'incrémental en structure de pions (pions doublés, pour l'instant) + void update(MoveData move) { pointsMg += getIncrementMg(move); pointsEg += getIncrementEg(move); pointsPosMg += getIncrementPosMg(move); pointsPosEg += getIncrementPosEg(move); + chessEvalAdditionalElems.upadateEvalAdditionalElems(move); updatePhase(move); } + + + + private void updatePhase(MoveData move) { final int promoType = move.getPromotionType(); if (promoType!=0) { diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java index b11e6af..6bdfe38 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java @@ -34,7 +34,12 @@ public StaticEvaluator fork() { public static void main(String[] args) { // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(new Board()); - mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); +// mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); + mvg.getBoard().loadFromFen("5k2/p1p2pp1/4b1p1/4p3/1P2P3/p2P1B2/1b2NP1P/6K1 w - - 0 1"); + System.out.println(new Hb2MyFirstEvaluator().evaluate(mvg)); + mvg.getBoard().loadFromFen("8/p1p1kppp/4b3/4p1P1/1P2P2P/p2P1B2/1b2NP2/6K1 w - - 0 1"); + + System.out.println(new Hb2MyFirstEvaluator().evaluate(mvg)); } } \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java index 929d6b4..da92ac3 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java @@ -1,6 +1,7 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg2.additional; import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.chess.utils.adapters.MoveData; import com.github.bhlangonijr.chesslib.Board; @@ -24,6 +25,10 @@ public void copyTo(ChessEvalAdditionalElems other) { pawnsStructEval.copyTo(other.pawnsStructEval); } + + public void upadateEvalAdditionalElems(MoveData move) { + pawnsStructEval.updatePawnsStructEval(move); + } public PawnsStrucEval getPawnsStructEval() { return pawnsStructEval; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index cf1bdca..df35839 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -5,6 +5,7 @@ import java.util.Arrays; import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.chess.utils.adapters.MoveData; import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; import com.github.bhlangonijr.chesslib.Board; @@ -64,10 +65,72 @@ public PawnsStrucEval(BoardExplorer explorer, Board board) { void copyTo(PawnsStrucEval other) { other.board = board; - other.tabNbBlackPawnsByCol = tabNbBlackPawnsByCol.clone(); // not a shallow copy!!!! + other.tabNbBlackPawnsByCol = tabNbBlackPawnsByCol.clone(); // not a shallow copy!!!! For integers are of primitive type... other.tabNbWhitePawnsByCol = tabNbWhitePawnsByCol.clone(); // not a shallow copy!!!! } + public void modifyNumberOfBlackPawnsofColumn(int column, int nbPawns ) { + tabNbBlackPawnsByCol[column] += nbPawns; + } + + public void modifyNumberOfWhitePawnsofColumn(int column, int nbPawns ) { + tabNbWhitePawnsByCol[column] += nbPawns; + } + public void updatePawnsStructEval(MoveData move) { + updateDoubledPawns(move); + } + + + private void updateDoubledPawns(MoveData move) { + int kind = Math.abs(move.getMovingPiece()); + if (kind != PAWN) { + return; + } + boolean isBlack = (move.getMovingPiece()<0?true:false); + int columnPawn = move.getMovingIndex()%Hb2ChessConstants.NB_COLS; + final int promoType = move.getPromotionType(); + if (promoType!=0) { + // If promotion, then the pawn disappears. + + + + // Get the pawn's column and decrement its number of pawns of its color + if (isBlack) { + modifyNumberOfBlackPawnsofColumn(columnPawn, (-1)); + } else { + modifyNumberOfWhitePawnsofColumn(columnPawn, (-1)); + } + return; // promotion. so we stop here: no chance of a pawn being captured... + + } + + int captured = move.getCapturedType(); + if (captured!=0) { + // Well the pawn with change columns...whatever it captures + int destinationColumnOfThePawn = move.getMovingDestination()%Hb2ChessConstants.NB_COLS; + if (isBlack) { + modifyNumberOfBlackPawnsofColumn(columnPawn, (-1)); + modifyNumberOfBlackPawnsofColumn(destinationColumnOfThePawn, 1); + } else { + modifyNumberOfWhitePawnsofColumn(columnPawn, (-1)); + modifyNumberOfWhitePawnsofColumn(destinationColumnOfThePawn, 1); + } + // If a piece was captured, we don't care; whereas if a pawn is captured, it'as another story... + if (Math.abs(captured)== PAWN) { + if (isBlack) { + // Black pawns are eating white pawns + modifyNumberOfWhitePawnsofColumn(destinationColumnOfThePawn, (-1)); + + } else { + // White pawns are eating black pawns + modifyNumberOfBlackPawnsofColumn(destinationColumnOfThePawn, (-1)); + + } + } + + } + } + public int getContribMg() { // white doubled pawns diff --git a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java index 6d7ffa4..bd4ccb2 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java +++ b/src/main/java/com/fathzer/jchess/chesslib/uci/ChessLibEngine.java @@ -132,7 +132,7 @@ public ChessLibMoveGenerator fromFEN(String fen) { } public static IterativeDeepeningEngine buildEngine(Supplier> evaluatorBuilder, int maxDepth) { - final IterativeDeepeningEngine engine = new IterativeDeepeningEngine<>(new ChessLibDeepeningPolicy(maxDepth), new TT(16, SizeUnit.MB), evaluatorBuilder) { + final IterativeDeepeningEngine engine = new IterativeDeepeningEngine<>(new ChessLibDeepeningPolicy(maxDepth), new TT(256, SizeUnit.MB), evaluatorBuilder) { @Override protected Negamax buildAi(ExecutionContext> context) { final Negamax negaMax = (Negamax) super.buildAi(context); diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java index 64096a3..c651f4a 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java @@ -17,7 +17,9 @@ class HBThreeMovesTest { void test() { final int depth = 6; final int bestMoveCount = 3; - final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final String fen = "5k2/p1p2ppp/4b3/1p2p1P1/1P2P3/3P1B2/Pb2NPKP/8 w - - 0 1"; +// final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(SimplifiedEvaluator::new, depth); engine.getDeepeningPolicy().setSize(bestMoveCount); final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)).getBestMoves(); diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2Bis.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2Bis.java index f1c5375..151a5a2 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2Bis.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest2Bis.java @@ -7,7 +7,6 @@ import com.fathzer.games.ai.evaluation.EvaluatedMove; import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; -import com.fathzer.jchess.chesslib.ai.eval.SimplifiedEvaluator; import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluator; import com.fathzer.jchess.chesslib.uci.ChessLibEngine; import com.github.bhlangonijr.chesslib.move.Move; @@ -16,16 +15,21 @@ class HBThreeMovesTest2Bis { @Test void test() { - final int depth = 6; + final int depth = 12; final int bestMoveCount = 3; - final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; // pas de pions doublés + final String fen = "5k2/p1p2ppp/4b3/1p2p1P1/1P2P3/3P1B2/Pb2NPKP/8 w - - 0 1"; +// final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; // pas de pions doublés +// final String fen = "5k2/p1p2ppp/4b3/4p1P1/1P2P3/p2P1B2/1b2NP1P/6K1 w - - 0 1"; + + // final String fen = "r2k1r2/pp1b2p1/1b2Pnp1/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(Hb2SimplifiedEvaluator::new, depth); engine.getDeepeningPolicy().setSize(bestMoveCount); + engine.getDeepeningPolicy().setDeepenOnForced(true); final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)).getBestMoves(); System.out.println(moves); - for (int i=0;i<3;i++) { - EvaluatedMove move = moves.get(i); + for (EvaluatedMove move : moves) { +// EvaluatedMove move = moves.get(i); List principalVariation = move.getPrincipalVariation(); System.out.println(move+" -> "+principalVariation); } From 7a85b3332e72182d28f70f7a2996745e038d6cbc Mon Sep 17 00:00:00 2001 From: herve Date: Sat, 26 Oct 2024 08:03:49 +0200 Subject: [PATCH 40/55] multiple pawns of the same color on a column taken into account for pawns structure's evaluation --- pom.xml | 2 +- .../jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java | 6 ++++-- .../chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java | 8 ++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 978f9c9..28ff8fb 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ 1.0.8 chesslib-uci-engine - 0.0.2 + 0.0.3 chesslib-uci-engine A basic uci engine plugin for jchess-uci. diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java index 90cbe4b..dc7e810 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java @@ -4,7 +4,9 @@ public abstract class Hb2ChessConstants { public static final int NB_RAWS = 8; public static final int NB_COLS = 8; - public static final int MALUS_DOUBLED_PAWN_MG = -20; - public static final int MALUS_DOUBLED_PAWN_EG = -40; + public static final int MALUS_DOUBLED_PAWNS_MG = -20; + public static final int MALUS_DOUBLED_PAWNS_EG = -40; + + public static final int NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS = 2; // Beyond, it could be counterproductive...according to many famous chess engines specs } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index df35839..767d2d6 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -137,7 +137,7 @@ public int getContribMg() { int malusW = 0; for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { if (tabNbWhitePawnsByCol[i] > 1) { - malusW += tabNbWhitePawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWN_MG; + malusW += tabNbWhitePawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_MG; } } @@ -145,7 +145,7 @@ public int getContribMg() { int malusB = 0; for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { if (tabNbBlackPawnsByCol[i] > 1) { - malusB += tabNbBlackPawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWN_MG; + malusB += tabNbBlackPawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_MG; } } return(malusW - malusB); @@ -160,7 +160,7 @@ public int getContribEg() { int malusW = 0; for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { if (tabNbWhitePawnsByCol[i] > 1) { - malusW += tabNbWhitePawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWN_EG; + malusW += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_EG; } } @@ -168,7 +168,7 @@ public int getContribEg() { int malusB = 0; for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { if (tabNbBlackPawnsByCol[i] > 1) { - malusB += tabNbBlackPawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWN_EG; + malusB += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_EG; } } return(malusW - malusB); From 10fae942de09b30cd7f3e6a18c59b9d95aa276d7 Mon Sep 17 00:00:00 2001 From: herve Date: Tue, 12 Nov 2024 10:25:19 +0100 Subject: [PATCH 41/55] First step in passed pawns' detection --- pom.xml | 6 +- .../ai/eval/hbpg2/Hb2ChessConstants.java | 5 +- .../eval/hbpg2/additional/PawnsStrucEval.java | 24 ++-- .../chesslib/hbpg2/test/TestPasserPawns.java | 114 ++++++++++++++++++ .../chesslib/hbpg2/test/package-info.java | 7 ++ 5 files changed, 139 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/TestPasserPawns.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/package-info.java diff --git a/pom.xml b/pom.xml index 28ff8fb..c1ee0d9 100644 --- a/pom.xml +++ b/pom.xml @@ -38,9 +38,9 @@ - com.github.bhlangonijr + com.github.bhlangonijr.chesslib chesslib - 1.3.3 + 1.3.4 com.fathzer @@ -93,7 +93,7 @@ 3.4.1 ${customized.jar.name} - true + false diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java index dc7e810..c91792d 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java @@ -1,8 +1,9 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg2; public abstract class Hb2ChessConstants { - public static final int NB_RAWS = 8; - public static final int NB_COLS = 8; + public static final int NB_RANKS = 8; + public static final int NB_FILES = 8; + public static final int INDEX_MAX_RANK = NB_RANKS-1; public static final int MALUS_DOUBLED_PAWNS_MG = -20; public static final int MALUS_DOUBLED_PAWNS_EG = -40; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index 767d2d6..b3c0db0 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -19,15 +19,15 @@ public class PawnsStrucEval { public PawnsStrucEval() { - tabNbWhitePawnsByCol = new int[Hb2ChessConstants.NB_COLS]; - tabNbBlackPawnsByCol = new int[Hb2ChessConstants.NB_COLS]; + tabNbWhitePawnsByCol = new int[Hb2ChessConstants.NB_FILES]; + tabNbBlackPawnsByCol = new int[Hb2ChessConstants.NB_FILES]; } public PawnsStrucEval(PawnsStrucEval pse) { // Since it's an array of integers, the copy is not a shallow copy - tabNbWhitePawnsByCol = Arrays.copyOf(pse.tabNbWhitePawnsByCol, Hb2ChessConstants.NB_COLS); + tabNbWhitePawnsByCol = Arrays.copyOf(pse.tabNbWhitePawnsByCol, Hb2ChessConstants.NB_FILES); // Since it's an array of integers, the copy is not a shallow copy - tabNbBlackPawnsByCol = Arrays.copyOf(pse.tabNbBlackPawnsByCol, Hb2ChessConstants.NB_COLS); + tabNbBlackPawnsByCol = Arrays.copyOf(pse.tabNbBlackPawnsByCol, Hb2ChessConstants.NB_FILES); } @@ -36,7 +36,7 @@ public PawnsStrucEval(BoardExplorer explorer, Board board) { this.board = board; - for (int i= 0; i < Hb2ChessConstants.NB_COLS; i++) { + for (int i= 0; i < Hb2ChessConstants.NB_FILES; i++) { tabNbWhitePawnsByCol[i] = 0; tabNbBlackPawnsByCol[i] = 0; } @@ -48,7 +48,7 @@ public PawnsStrucEval(BoardExplorer explorer, Board board) { final boolean isPieceBlack = p<0; if (kind==PAWN) { - final int columnPawn = index%Hb2ChessConstants.NB_COLS; + final int columnPawn = index%Hb2ChessConstants.NB_FILES; if (isPieceBlack) { tabNbBlackPawnsByCol[columnPawn]++; @@ -87,7 +87,7 @@ private void updateDoubledPawns(MoveData move) { return; } boolean isBlack = (move.getMovingPiece()<0?true:false); - int columnPawn = move.getMovingIndex()%Hb2ChessConstants.NB_COLS; + int columnPawn = move.getMovingIndex()%Hb2ChessConstants.NB_FILES; final int promoType = move.getPromotionType(); if (promoType!=0) { // If promotion, then the pawn disappears. @@ -107,7 +107,7 @@ private void updateDoubledPawns(MoveData move) { int captured = move.getCapturedType(); if (captured!=0) { // Well the pawn with change columns...whatever it captures - int destinationColumnOfThePawn = move.getMovingDestination()%Hb2ChessConstants.NB_COLS; + int destinationColumnOfThePawn = move.getMovingDestination()%Hb2ChessConstants.NB_FILES; if (isBlack) { modifyNumberOfBlackPawnsofColumn(columnPawn, (-1)); modifyNumberOfBlackPawnsofColumn(destinationColumnOfThePawn, 1); @@ -135,7 +135,7 @@ public int getContribMg() { // white doubled pawns int malusW = 0; - for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { + for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { if (tabNbWhitePawnsByCol[i] > 1) { malusW += tabNbWhitePawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_MG; } @@ -143,7 +143,7 @@ public int getContribMg() { // black doubled pawns int malusB = 0; - for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { + for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { if (tabNbBlackPawnsByCol[i] > 1) { malusB += tabNbBlackPawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_MG; } @@ -158,7 +158,7 @@ public int getContribEg() { // white doubled pawns int malusW = 0; - for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { + for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { if (tabNbWhitePawnsByCol[i] > 1) { malusW += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_EG; } @@ -166,7 +166,7 @@ public int getContribEg() { // black doubled pawns int malusB = 0; - for (int i = 0; i < Hb2ChessConstants.NB_COLS; i++) { + for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { if (tabNbBlackPawnsByCol[i] > 1) { malusB += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_EG; } diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/TestPasserPawns.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/TestPasserPawns.java new file mode 100644 index 0000000..be8da29 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/TestPasserPawns.java @@ -0,0 +1,114 @@ +package com.fathzer.jchess.chesslib.hbpg2.test; + +import static com.fathzer.chess.utils.Pieces.PAWN; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.jchess.chesslib.ChessLibBoardExplorer; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; +import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.Piece; +import com.github.bhlangonijr.chesslib.Rank; +import com.github.bhlangonijr.chesslib.Square; + +public class TestPasserPawns { + + public static int getIndex(Square square) { + return (7-square.getRank().ordinal())*8+square.getFile().ordinal(); + } + + static ChessLibMoveGenerator fromFEN(String fen) { + final Board board = new Board(); + board.loadFromFen(fen); + return new ChessLibMoveGenerator(board); + } + + static void printDetailsAboutPawn(Square pawnSq, boolean isBlack,Board board) { + + System.out.println(); + System.out.println(); + System.out.println("####################"); + if (isBlack) { + System.out.println("BLACK PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); + } else { + System.out.println("WHITE PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); + } + int indexCazz = getIndex(pawnSq); + System.out.println("Index JMA case "+ pawnSq.value()+":"+ indexCazz); + Square[] tabAdjSquares = pawnSq.getSideSquares(); + System.out.println("Cases adjacentes de la case "+ pawnSq.value()+":"); + for (int i = 0; i < tabAdjSquares.length; i++) { + System.out.println(tabAdjSquares[i].value()); + + } + + + int columnPawn = indexCazz%Hb2ChessConstants.NB_FILES; + int rankPawn =Hb2ChessConstants.INDEX_MAX_RANK-pawnSq.getRank().ordinal(); + System.out.println("rankPawn_JMA:"+ rankPawn); + System.out.println("columnPawn_JMA:"+ columnPawn); + + if (isBlack ) { + if ( pawnSq.getRank() == Rank.RANK_2) { + // A black pawn on the 2nd rank is a passer, by nature + System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); + } + + } else { + if ( pawnSq.getRank() == Rank.RANK_7) { + // A white pawn on the 7th rank is a passer, by nature + System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); + } + } + + + +// Piece enemyPawn = (isBlack?Piece.WHITE_PAWN:Piece.BLACK_PAWN); +// long bitboardEnemyPawns = board.getBitboard(enemyPawn); + + + System.out.println("####################"); + System.out.println(); + System.out.println(); + + } + + static void deallWithSquareOccupiedByPawn(Square pawnSq, boolean isBlack, Board board) { + + printDetailsAboutPawn(pawnSq, isBlack, board); + + } + + public static void main(String[] args) { + Board internal = new Board(); + internal.loadFromFen("6k1/8/1Pp5/8/8/3P4/1K6/8 w - - 0 1"); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen.gif + ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(internal); + + BoardExplorer explorer = new ChessLibBoardExplorer(mvg.getBoard()); + do { + final int p = explorer.getPiece(); + + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind == PAWN) { + int row = Hb2ChessConstants.INDEX_MAX_RANK - index/Hb2ChessConstants.NB_RANKS; + int col = index%Hb2ChessConstants.NB_FILES; + Square sqp = Square.squareAt((8*row)+col); + + deallWithSquareOccupiedByPawn(sqp, isBlack, mvg.getBoard()); +// +// int inc = getPositionValueEg(kind, isBlack, index); +// if (isBlack) { +// pointsPosEg -= inc; +// } else { +// pointsPosEg += inc; +// } + } + + + } while (explorer.next()); + + } + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/package-info.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/package-info.java new file mode 100644 index 0000000..6881f27 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/package-info.java @@ -0,0 +1,7 @@ +/** + * + */ +/** + * + */ +package com.fathzer.jchess.chesslib.hbpg2.test; \ No newline at end of file From 2321e50242388ffdeacbfcc42572e4ee678ea491 Mon Sep 17 00:00:00 2001 From: herve Date: Thu, 14 Nov 2024 08:05:03 +0100 Subject: [PATCH 42/55] Well, see VeryDirtyTestPasserPawns.java The detection method of the passed pawns works fine, eventually! --- .../chesslib/hbpg2/test/TestPasserPawns.java | 114 -------- .../hbpg2/test/VeryDirtyTestPasserPawns.java | 259 ++++++++++++++++++ 2 files changed, 259 insertions(+), 114 deletions(-) delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/TestPasserPawns.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/TestPasserPawns.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/TestPasserPawns.java deleted file mode 100644 index be8da29..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/TestPasserPawns.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.fathzer.jchess.chesslib.hbpg2.test; - -import static com.fathzer.chess.utils.Pieces.PAWN; - -import com.fathzer.chess.utils.adapters.BoardExplorer; -import com.fathzer.jchess.chesslib.ChessLibBoardExplorer; -import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; -import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; -import com.github.bhlangonijr.chesslib.Board; -import com.github.bhlangonijr.chesslib.Piece; -import com.github.bhlangonijr.chesslib.Rank; -import com.github.bhlangonijr.chesslib.Square; - -public class TestPasserPawns { - - public static int getIndex(Square square) { - return (7-square.getRank().ordinal())*8+square.getFile().ordinal(); - } - - static ChessLibMoveGenerator fromFEN(String fen) { - final Board board = new Board(); - board.loadFromFen(fen); - return new ChessLibMoveGenerator(board); - } - - static void printDetailsAboutPawn(Square pawnSq, boolean isBlack,Board board) { - - System.out.println(); - System.out.println(); - System.out.println("####################"); - if (isBlack) { - System.out.println("BLACK PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); - } else { - System.out.println("WHITE PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); - } - int indexCazz = getIndex(pawnSq); - System.out.println("Index JMA case "+ pawnSq.value()+":"+ indexCazz); - Square[] tabAdjSquares = pawnSq.getSideSquares(); - System.out.println("Cases adjacentes de la case "+ pawnSq.value()+":"); - for (int i = 0; i < tabAdjSquares.length; i++) { - System.out.println(tabAdjSquares[i].value()); - - } - - - int columnPawn = indexCazz%Hb2ChessConstants.NB_FILES; - int rankPawn =Hb2ChessConstants.INDEX_MAX_RANK-pawnSq.getRank().ordinal(); - System.out.println("rankPawn_JMA:"+ rankPawn); - System.out.println("columnPawn_JMA:"+ columnPawn); - - if (isBlack ) { - if ( pawnSq.getRank() == Rank.RANK_2) { - // A black pawn on the 2nd rank is a passer, by nature - System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); - } - - } else { - if ( pawnSq.getRank() == Rank.RANK_7) { - // A white pawn on the 7th rank is a passer, by nature - System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); - } - } - - - -// Piece enemyPawn = (isBlack?Piece.WHITE_PAWN:Piece.BLACK_PAWN); -// long bitboardEnemyPawns = board.getBitboard(enemyPawn); - - - System.out.println("####################"); - System.out.println(); - System.out.println(); - - } - - static void deallWithSquareOccupiedByPawn(Square pawnSq, boolean isBlack, Board board) { - - printDetailsAboutPawn(pawnSq, isBlack, board); - - } - - public static void main(String[] args) { - Board internal = new Board(); - internal.loadFromFen("6k1/8/1Pp5/8/8/3P4/1K6/8 w - - 0 1"); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen.gif - ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(internal); - - BoardExplorer explorer = new ChessLibBoardExplorer(mvg.getBoard()); - do { - final int p = explorer.getPiece(); - - final int kind = Math.abs(p); - final int index = explorer.getIndex(); - final boolean isBlack = p<0; - if (kind == PAWN) { - int row = Hb2ChessConstants.INDEX_MAX_RANK - index/Hb2ChessConstants.NB_RANKS; - int col = index%Hb2ChessConstants.NB_FILES; - Square sqp = Square.squareAt((8*row)+col); - - deallWithSquareOccupiedByPawn(sqp, isBlack, mvg.getBoard()); -// -// int inc = getPositionValueEg(kind, isBlack, index); -// if (isBlack) { -// pointsPosEg -= inc; -// } else { -// pointsPosEg += inc; -// } - } - - - } while (explorer.next()); - - } - -} diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java new file mode 100644 index 0000000..b1c96d5 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java @@ -0,0 +1,259 @@ +package com.fathzer.jchess.chesslib.hbpg2.test; + +import static com.fathzer.chess.utils.Pieces.PAWN; + +import java.util.List; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.jchess.chesslib.ChessLibBoardExplorer; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; +import com.github.bhlangonijr.chesslib.Bitboard; +import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.File; +import com.github.bhlangonijr.chesslib.Piece; +import com.github.bhlangonijr.chesslib.Rank; +import com.github.bhlangonijr.chesslib.Square; + +public class VeryDirtyTestPasserPawns { + + public static int getIndex(Square square) { + return (Hb2ChessConstants.INDEX_MAX_RANK-square.getRank().ordinal())*Hb2ChessConstants.NB_RANKS+square.getFile().ordinal(); + } + + static int getRgSquare (int rank, int file) { + return((Hb2ChessConstants.NB_RANKS*rank)+file); + } + + static ChessLibMoveGenerator fromFEN(String fen) { + final Board board = new Board(); + board.loadFromFen(fen); + return new ChessLibMoveGenerator(board); + } + + static void printDetailsAboutPawn(Square pawnSq, boolean isBlack,Board board) { + +// /// STALINE +// if (pawnSq.name().equalsIgnoreCase("E2") == false) { +// return; +// } + + System.out.println(); + System.out.println(); + System.out.println("####################"); + if (isBlack) { + System.out.println("BLACK PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); + } else { + System.out.println("WHITE PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); + } + int indexCazz = getIndex(pawnSq); + System.out.println("Index JMA case "+ pawnSq.value()+":"+ indexCazz); + Square[] tabAdjSquares = pawnSq.getSideSquares(); + System.out.println("Cases adjacentes de la case "+ pawnSq.value()+":"); + for (int i = 0; i < tabAdjSquares.length; i++) { + System.out.println(tabAdjSquares[i].value()); + + } + + + int columnPawn = indexCazz%Hb2ChessConstants.NB_FILES; + int rankPawn =Hb2ChessConstants.INDEX_MAX_RANK-pawnSq.getRank().ordinal(); + System.out.println("rankPawn_JMA:"+ rankPawn); + System.out.println("columnPawn_JMA:"+ columnPawn); + + if (isBlack ) { + if ( pawnSq.getRank() == Rank.RANK_2) { + // A black pawn on the 2nd rank is a passer, by nature + System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); + System.out.println("####################"); + System.out.println(); + System.out.println(); + return; + } + + } else { + if ( pawnSq.getRank() == Rank.RANK_7) { + // A white pawn on the 7th rank is a passer, by nature + System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); + System.out.println("####################"); + System.out.println(); + System.out.println(); + return; + } + } + + + + Piece enemyPawn = (isBlack?Piece.WHITE_PAWN:Piece.BLACK_PAWN); + long bitboardEnemyPawns = board.getBitboard(enemyPawn); + if (bitboardEnemyPawns == 0L) { + System.out.println("THE "+ (isBlack?"BLACK ":"WHITE ") + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); + } + + + if (!isBlack) { + + // Bon, on part de la rangée devant le pion blanc et on va jusqu'à la 7ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) + // On regarde s'il y a un pion noir ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions noirs, alors + // le pion blanc est passé + int rankDebut = pawnSq.getRank().ordinal()+1; + int rankFin = Rank.RANK_7.ordinal(); + int fileDebut = pawnSq.getFile().ordinal(); + int fileFin = pawnSq.getFile().ordinal(); + if (columnPawn == 0) { + fileFin = File.FILE_B.ordinal(); + } else if (columnPawn == 7) { + fileDebut = File.FILE_G.ordinal(); + } else { + fileDebut = pawnSq.getFile().ordinal() - 1; + fileFin = pawnSq.getFile().ordinal() +1; + } + //getRgSquare +// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); +// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); +// int rgDebutSq = (Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut; +// int rgFinSq = (Hb2ChessConstants.NB_RANKS*rankFin)+fileFin; + boolean areEnemyPawnInZone = false; + for (int rankk = rankDebut; rankk <= rankFin; rankk++) { + int rgSqDebutRank = getRgSquare(rankk, fileDebut); + int rgSqFintRank = getRgSquare(rankk, fileFin); + long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); + if (pionsAdversesDansZoneForRank != 0L) { + areEnemyPawnInZone = true; + break; + } + + } +// long ALL_BITS_EQUAL_ONE_BITBOARD = 0xFFFFFFFFFFFFFFFFL; +// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, sqDebut.ordinal(), sqFin.ordinal()); +// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, rgDebutSq, rgFinSq); +// List lstKazz = Bitboard.bbToSquareList(pionsAdversesDansZone); +// for (Square kaaaaz : lstKazz) { +// System.out.println(kaaaaz.value()); +// } + if (areEnemyPawnInZone == false) { + System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); + } + + + + + } else { + + // Bon, on part de la rangée devant le pion noir (du point de vue noir) et on va jusqu'à la 2ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) + // On regarde s'il y a un pion blanc ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions blancs, alors + // le pion noir est passé + int rankDebut = Rank.RANK_2.ordinal(); + int rankFin = pawnSq.getRank().ordinal()-1; + int fileDebut = pawnSq.getFile().ordinal(); + int fileFin = pawnSq.getFile().ordinal(); + if (columnPawn == 0) { + fileFin = File.FILE_B.ordinal(); + } else if (columnPawn == 7) { + fileDebut = File.FILE_G.ordinal(); + } else { + fileDebut = pawnSq.getFile().ordinal() - 1; + fileFin = pawnSq.getFile().ordinal() +1; + } + +// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); +// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); + + boolean areEnemyPawnInZone = false; + for (int rankk = rankDebut; rankk <= rankFin; rankk++) { + int rgSqDebutRank = getRgSquare(rankk, fileDebut); + int rgSqFintRank = getRgSquare(rankk, fileFin); + long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); + if (pionsAdversesDansZoneForRank != 0L) { + areEnemyPawnInZone = true; + break; + } + + } + + + if (areEnemyPawnInZone == false) { + System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); + } + + + } + + System.out.println("####################"); + System.out.println(); + System.out.println(); + + } + + static void deallWithSquareOccupiedByPawn(Square pawnSq, boolean isBlack, Board board) { + + printDetailsAboutPawn(pawnSq, isBlack, board); + + } + + + + static void testFen1() { + + + testFen("6k1/8/1Pp5/8/8/3P4/1K6/8 w - - 0 1"); + + + } + + + + static void testFen2() { + testFen("6k1/8/1Pp5/8/8/3P3p/1K2Pp2/8 w - - 0 1"); + + + } + static void testFen3() { + testFen("6k1/8/1Pp5/8/8/7p/1K1PPp2/8 w - - 0 1"); + + + } + + + static void testFen(String fen) { + + System.out.println(); + System.out.println("FEN en test pour les pions passés:" + fen); + Board internal = new Board(); + internal.loadFromFen(fen); + ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(internal); + + BoardExplorer explorer = new ChessLibBoardExplorer(mvg.getBoard()); + do { + final int p = explorer.getPiece(); + + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind == PAWN) { + int row = Hb2ChessConstants.INDEX_MAX_RANK - index/Hb2ChessConstants.NB_RANKS; + int col = index%Hb2ChessConstants.NB_FILES; + Square sqp = Square.squareAt((Hb2ChessConstants.NB_RANKS*row)+col); + + deallWithSquareOccupiedByPawn(sqp, isBlack, mvg.getBoard()); + + } + + } while (explorer.next()); + + System.out.println(); + System.out.println(); + System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + System.out.println(); + System.out.println(); + + } + + public static void main(String[] args) { +// testFen1(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen1.gif + testFen2(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen2.gif +// testFen3(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen3.gif + } + + +} From 119e545e2fa35355025faf4b185b51b9fd9ec843 Mon Sep 17 00:00:00 2001 From: herve Date: Thu, 14 Nov 2024 10:05:34 +0100 Subject: [PATCH 43/55] Dependencies correction in pom.xml --- pom.xml | 2 +- .../jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c1ee0d9..3987279 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ - com.github.bhlangonijr.chesslib + com.github.bhlangonijr chesslib 1.3.4 diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java index b1c96d5..91a9ca5 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java +++ b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java @@ -223,6 +223,8 @@ static void testFen(String fen) { internal.loadFromFen(fen); ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(internal); + System.out.println(internal.toStringFromWhiteViewPoint()); + BoardExplorer explorer = new ChessLibBoardExplorer(mvg.getBoard()); do { final int p = explorer.getPiece(); From f3f35a67fa673642b620596c3041a4f60fdb182c Mon Sep 17 00:00:00 2001 From: herve Date: Thu, 14 Nov 2024 12:25:25 +0100 Subject: [PATCH 44/55] passed pawns in evaluation pawns' structure: step one --- pom.xml | 2 +- .../ai/eval/hbpg2/Hb2ChessConstants.java | 3 +- .../eval/hbpg2/additional/PawnsStrucEval.java | 162 +++++++++++++++++- 3 files changed, 157 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index 3987279..c1ee0d9 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ - com.github.bhlangonijr + com.github.bhlangonijr.chesslib chesslib 1.3.4 diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java index c91792d..30c1e2b 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java @@ -5,8 +5,7 @@ public abstract class Hb2ChessConstants { public static final int NB_FILES = 8; public static final int INDEX_MAX_RANK = NB_RANKS-1; - public static final int MALUS_DOUBLED_PAWNS_MG = -20; - public static final int MALUS_DOUBLED_PAWNS_EG = -40; + public static final int NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS = 2; // Beyond, it could be counterproductive...according to many famous chess engines specs diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index b3c0db0..cb4d7ea 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -7,20 +7,57 @@ import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; - +import com.github.bhlangonijr.chesslib.Bitboard; import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.File; +import com.github.bhlangonijr.chesslib.Piece; +import com.github.bhlangonijr.chesslib.Rank; +import com.github.bhlangonijr.chesslib.Side; public class PawnsStrucEval { + + + private static final int MALUS_DOUBLED_PAWNS_MG = -20; + private static final int MALUS_DOUBLED_PAWNS_EG = -40; + + private static final int PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK = 13; + private static final int PASSED_PAWN_BONUS = 25; + private static final int PASSED_PAWN_BONUS_6_TH_RANK = 27; + private static final int PASSED_PAWN_BONUS_7_TH_RANK = 30; + + private static final int PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK_EG = 14; + private static final int PASSED_PAWN_BONUS_EG = 27; + private static final int PASSED_PAWN_BONUS_6_TH_RANK_EG = 30; + private static final int PASSED_PAWN_BONUS_7_TH_RANK_EG = 33; + + private static final int[] TAB_WHITE_PASSED_PAWN_BONUS_BY_RANK_MG = + {0,PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK, + PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK, + PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK, + PASSED_PAWN_BONUS,PASSED_PAWN_BONUS_6_TH_RANK,PASSED_PAWN_BONUS_7_TH_RANK, + 0}; + + private static final int[] TAB_WHITE_PASSED_PAWN_BONUS_BY_RANK_EG = + {0,PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK_EG, + PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK_EG, + PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK_EG, + PASSED_PAWN_BONUS,PASSED_PAWN_BONUS_6_TH_RANK_EG,PASSED_PAWN_BONUS_7_TH_RANK_EG, + 0}; + private Board board; private int[] tabNbWhitePawnsByCol; private int[] tabNbBlackPawnsByCol; - + private int bonusWhitePassedPawns; + private int bonusBlackPassedPawns; public PawnsStrucEval() { tabNbWhitePawnsByCol = new int[Hb2ChessConstants.NB_FILES]; tabNbBlackPawnsByCol = new int[Hb2ChessConstants.NB_FILES]; + bonusBlackPassedPawns = 0; + bonusWhitePassedPawns = 0; + } public PawnsStrucEval(PawnsStrucEval pse) { @@ -34,6 +71,8 @@ public PawnsStrucEval(PawnsStrucEval pse) { public PawnsStrucEval(BoardExplorer explorer, Board board) { this(); + long bitboardWhitePawns = board.getBitboard(Piece.WHITE_PAWN); + long bitboardBlackPawns = board.getBitboard(Piece.BLACK_PAWN); this.board = board; for (int i= 0; i < Hb2ChessConstants.NB_FILES; i++) { @@ -55,7 +94,11 @@ public PawnsStrucEval(BoardExplorer explorer, Board board) { } else { tabNbWhitePawnsByCol[columnPawn]++; } - + if (isPieceBlack) { + + } else { + + } } } while (explorer.next()); @@ -63,6 +106,111 @@ public PawnsStrucEval(BoardExplorer explorer, Board board) { } + static int getRgSquare (int rank, int file) { + return((Hb2ChessConstants.NB_RANKS*rank)+file); + } + + + boolean isPawnPassed(int indexPawnJma, boolean isBlack, long bitboardWhitePawns, long bitboardBlackPawns) { + + + long bitboardEnemyPawns = (isBlack?bitboardWhitePawns:bitboardBlackPawns); + if (bitboardEnemyPawns == 0L) { + return(true); + } + int row = Hb2ChessConstants.INDEX_MAX_RANK - indexPawnJma/Hb2ChessConstants.NB_RANKS; + int col = indexPawnJma%Hb2ChessConstants.NB_FILES; + if (!isBlack) { + + // Bon, on part de la rangée devant le pion blanc et on va jusqu'à la 7ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) + // On regarde s'il y a un pion noir ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions noirs, alors + // le pion blanc est passé + int rankDebut = row +1; + int rankFin = Rank.RANK_7.ordinal(); + int fileDebut = col; + int fileFin = col; + if (col == 0) { + fileFin = File.FILE_B.ordinal(); + } else if (col == 7) { + fileDebut = File.FILE_G.ordinal(); + } else { + fileDebut = col - 1; + fileFin = col +1; + } + //getRgSquare +// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); +// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); +// int rgDebutSq = (Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut; +// int rgFinSq = (Hb2ChessConstants.NB_RANKS*rankFin)+fileFin; + boolean areEnemyPawnInZone = false; + for (int rankk = rankDebut; rankk <= rankFin; rankk++) { + int rgSqDebutRank = getRgSquare(rankk, fileDebut); + int rgSqFintRank = getRgSquare(rankk, fileFin); + long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); + if (pionsAdversesDansZoneForRank != 0L) { + areEnemyPawnInZone = true; + return(false); + } + + } +// long ALL_BITS_EQUAL_ONE_BITBOARD = 0xFFFFFFFFFFFFFFFFL; +// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, sqDebut.ordinal(), sqFin.ordinal()); +// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, rgDebutSq, rgFinSq); +// List lstKazz = Bitboard.bbToSquareList(pionsAdversesDansZone); +// for (Square kaaaaz : lstKazz) { +// System.out.println(kaaaaz.value()); +// } + if (areEnemyPawnInZone == false) { + return(true); + } + + + + + } else { + + // Bon, on part de la rangée devant le pion noir (du point de vue noir) et on va jusqu'à la 2ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) + // On regarde s'il y a un pion blanc ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions blancs, alors + // le pion noir est passé + int rankDebut = Rank.RANK_2.ordinal(); + int rankFin = row-1; + int fileDebut =col; + int fileFin = col; + if (col == 0) { + fileFin = File.FILE_B.ordinal(); + } else if (col == 7) { + fileDebut = File.FILE_G.ordinal(); + } else { + fileDebut = col - 1; + fileFin = col +1; + } + +// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); +// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); + + boolean areEnemyPawnInZone = false; + for (int rankk = rankDebut; rankk <= rankFin; rankk++) { + int rgSqDebutRank = getRgSquare(rankk, fileDebut); + int rgSqFintRank = getRgSquare(rankk, fileFin); + long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); + if (pionsAdversesDansZoneForRank != 0L) { + areEnemyPawnInZone = true; + return(false); + } + + } + + + if (areEnemyPawnInZone == false) { + return(true); + } + + + } + + return(true); + } + void copyTo(PawnsStrucEval other) { other.board = board; other.tabNbBlackPawnsByCol = tabNbBlackPawnsByCol.clone(); // not a shallow copy!!!! For integers are of primitive type... @@ -137,7 +285,7 @@ public int getContribMg() { int malusW = 0; for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { if (tabNbWhitePawnsByCol[i] > 1) { - malusW += tabNbWhitePawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_MG; + malusW += tabNbWhitePawnsByCol[i] * MALUS_DOUBLED_PAWNS_MG; } } @@ -145,7 +293,7 @@ public int getContribMg() { int malusB = 0; for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { if (tabNbBlackPawnsByCol[i] > 1) { - malusB += tabNbBlackPawnsByCol[i] * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_MG; + malusB += tabNbBlackPawnsByCol[i] * MALUS_DOUBLED_PAWNS_MG; } } return(malusW - malusB); @@ -160,7 +308,7 @@ public int getContribEg() { int malusW = 0; for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { if (tabNbWhitePawnsByCol[i] > 1) { - malusW += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_EG; + malusW += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * MALUS_DOUBLED_PAWNS_EG; } } @@ -168,7 +316,7 @@ public int getContribEg() { int malusB = 0; for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { if (tabNbBlackPawnsByCol[i] > 1) { - malusB += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * Hb2ChessConstants.MALUS_DOUBLED_PAWNS_EG; + malusB += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * MALUS_DOUBLED_PAWNS_EG; } } return(malusW - malusB); From 93e663ad8b0e8665039f18e9a47995a5708cfc17 Mon Sep 17 00:00:00 2001 From: herve Date: Fri, 15 Nov 2024 08:07:01 +0100 Subject: [PATCH 45/55] Passed pawns evaluation completed (still todo is the incremental satte) --- pom.xml | 2 +- ...bstractIncrementalSimplifiedEvaluator.java | 3 +- .../ai/eval/hbpg2/Hb2ChessConstants.java | 1 + .../ai/eval/hbpg2/Hb2IncrementalState.java | 10 +- .../eval/hbpg2/additional/PawnsStrucEval.java | 314 +++++++++++------- 5 files changed, 215 insertions(+), 115 deletions(-) diff --git a/pom.xml b/pom.xml index c1ee0d9..3987279 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ - com.github.bhlangonijr.chesslib + com.github.bhlangonijr chesslib 1.3.4 diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java index 3c1fdc3..af83f9e 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java @@ -57,7 +57,8 @@ public void init(B board) { public void prepareMove(B board, M move) { if (moveData.update(move, board)) { buildToCommit(); - toCommit.update(moveData); + toCommit.update(moveData, ((ChessLibMoveGenerator)board).getBoard()); // STALINE +// toCommit.update(moveData); } } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java index 30c1e2b..c0b3bce 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ChessConstants.java @@ -4,6 +4,7 @@ public abstract class Hb2ChessConstants { public static final int NB_RANKS = 8; public static final int NB_FILES = 8; public static final int INDEX_MAX_RANK = NB_RANKS-1; + public static final int INDEX_MAX_FILE = NB_FILES-1; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index 72be59f..ae2201f 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -32,7 +32,15 @@ void update(MoveData move) { updatePhase(move); } - + //TODO STALINE à coder + void update(MoveData move, Board board) { + pointsMg += getIncrementMg(move); + pointsEg += getIncrementEg(move); + pointsPosMg += getIncrementPosMg(move); + pointsPosEg += getIncrementPosEg(move); + chessEvalAdditionalElems.upadateEvalAdditionalElems(move); + updatePhase(move); + } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index cb4d7ea..2aef723 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -31,14 +31,15 @@ public class PawnsStrucEval { private static final int PASSED_PAWN_BONUS_6_TH_RANK_EG = 30; private static final int PASSED_PAWN_BONUS_7_TH_RANK_EG = 33; - private static final int[] TAB_WHITE_PASSED_PAWN_BONUS_BY_RANK_MG = + // Here the ranks are relative to the side. For black, the seventh rank is the 2nd rank + private static final int[] TAB_PASSED_PAWN_BONUS_BY_RANK_MG = {0,PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK, PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK, PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK, PASSED_PAWN_BONUS,PASSED_PAWN_BONUS_6_TH_RANK,PASSED_PAWN_BONUS_7_TH_RANK, 0}; - private static final int[] TAB_WHITE_PASSED_PAWN_BONUS_BY_RANK_EG = + private static final int[] TAB_PASSED_PAWN_BONUS_BY_RANK_EG = {0,PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK_EG, PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK_EG, PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK_EG, @@ -49,14 +50,18 @@ public class PawnsStrucEval { private int[] tabNbWhitePawnsByCol; private int[] tabNbBlackPawnsByCol; - private int bonusWhitePassedPawns; - private int bonusBlackPassedPawns; + private int bonusWhitePassedPawnsMg; + private int bonusWhitePassedPawnsEg; + private int bonusBlackPassedPawnsMg; + private int bonusBlackPassedPawnsEg; public PawnsStrucEval() { tabNbWhitePawnsByCol = new int[Hb2ChessConstants.NB_FILES]; tabNbBlackPawnsByCol = new int[Hb2ChessConstants.NB_FILES]; - bonusBlackPassedPawns = 0; - bonusWhitePassedPawns = 0; + bonusWhitePassedPawnsEg = 0; + bonusBlackPassedPawnsMg = 0; + bonusBlackPassedPawnsMg = 0; + bonusBlackPassedPawnsEg = 0; } @@ -88,18 +93,29 @@ public PawnsStrucEval(BoardExplorer explorer, Board board) { if (kind==PAWN) { final int columnPawn = index%Hb2ChessConstants.NB_FILES; + int rawPawn = Hb2ChessConstants.INDEX_MAX_RANK - index/Hb2ChessConstants.NB_RANKS; + if (isPieceBlack) { tabNbBlackPawnsByCol[columnPawn]++; } else { tabNbWhitePawnsByCol[columnPawn]++; } - if (isPieceBlack) { - - } else { + + boolean isPassedPawn = isPawnPassed(rawPawn, columnPawn, isPieceBlack, bitboardWhitePawns, bitboardBlackPawns); + if (isPassedPawn) { + if (isPieceBlack) { + bonusBlackPassedPawnsMg += TAB_PASSED_PAWN_BONUS_BY_RANK_MG[Hb2ChessConstants.INDEX_MAX_RANK - rawPawn]; + bonusBlackPassedPawnsEg += TAB_PASSED_PAWN_BONUS_BY_RANK_EG[Hb2ChessConstants.INDEX_MAX_RANK - rawPawn]; + + } else { + bonusWhitePassedPawnsMg += TAB_PASSED_PAWN_BONUS_BY_RANK_MG[rawPawn]; + bonusWhitePassedPawnsEg += TAB_PASSED_PAWN_BONUS_BY_RANK_EG[rawPawn]; + } } + } } while (explorer.next()); @@ -110,105 +126,96 @@ static int getRgSquare (int rank, int file) { return((Hb2ChessConstants.NB_RANKS*rank)+file); } + static boolean areEnemyPawnInZone(int rankDebut,int rankFin, int fileDebut, int fileFin, long bitboardEnemyPawns) { + - boolean isPawnPassed(int indexPawnJma, boolean isBlack, long bitboardWhitePawns, long bitboardBlackPawns) { + for (int rankk = rankDebut; rankk <= rankFin; rankk++) { + int rgSqDebutRank = getRgSquare(rankk, fileDebut); + int rgSqFintRank = getRgSquare(rankk, fileFin); + long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); + if (pionsAdversesDansZoneForRank != 0L) { + + return(false); + } + + } + + return(true); + - long bitboardEnemyPawns = (isBlack?bitboardWhitePawns:bitboardBlackPawns); - if (bitboardEnemyPawns == 0L) { + } + + static boolean isWhitePawnPassed(int rawPawn, int colPawn, long bitboardBlackPawns) { + + if (bitboardBlackPawns == 0L) { return(true); } - int row = Hb2ChessConstants.INDEX_MAX_RANK - indexPawnJma/Hb2ChessConstants.NB_RANKS; - int col = indexPawnJma%Hb2ChessConstants.NB_FILES; - if (!isBlack) { - - // Bon, on part de la rangée devant le pion blanc et on va jusqu'à la 7ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) - // On regarde s'il y a un pion noir ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions noirs, alors - // le pion blanc est passé - int rankDebut = row +1; - int rankFin = Rank.RANK_7.ordinal(); - int fileDebut = col; - int fileFin = col; - if (col == 0) { - fileFin = File.FILE_B.ordinal(); - } else if (col == 7) { - fileDebut = File.FILE_G.ordinal(); - } else { - fileDebut = col - 1; - fileFin = col +1; - } - //getRgSquare -// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); -// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); -// int rgDebutSq = (Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut; -// int rgFinSq = (Hb2ChessConstants.NB_RANKS*rankFin)+fileFin; - boolean areEnemyPawnInZone = false; - for (int rankk = rankDebut; rankk <= rankFin; rankk++) { - int rgSqDebutRank = getRgSquare(rankk, fileDebut); - int rgSqFintRank = getRgSquare(rankk, fileFin); - long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); - if (pionsAdversesDansZoneForRank != 0L) { - areEnemyPawnInZone = true; - return(false); + // Bon, on part de la rangée devant le pion blanc et on va jusqu'à la 7ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) + // On regarde s'il y a un pion noir ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions noirs, alors + // le pion blanc est passé + int rankDebut = rawPawn +1; + int rankFin = Rank.RANK_7.ordinal(); + int fileDebut = colPawn; + int fileFin = colPawn; + if (colPawn == 0) { + fileFin = File.FILE_B.ordinal(); + } else if (colPawn == Hb2ChessConstants.INDEX_MAX_FILE) { + fileDebut = File.FILE_G.ordinal(); + } else { + fileDebut = colPawn - 1; + fileFin = colPawn +1; } - } -// long ALL_BITS_EQUAL_ONE_BITBOARD = 0xFFFFFFFFFFFFFFFFL; -// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, sqDebut.ordinal(), sqFin.ordinal()); -// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, rgDebutSq, rgFinSq); -// List lstKazz = Bitboard.bbToSquareList(pionsAdversesDansZone); -// for (Square kaaaaz : lstKazz) { -// System.out.println(kaaaaz.value()); -// } - if (areEnemyPawnInZone == false) { - return(true); - } - - + boolean areEnemyPawnInZoneToBeExplored = areEnemyPawnInZone( rankDebut, rankFin, fileDebut, fileFin,bitboardBlackPawns); + return ( areEnemyPawnInZoneToBeExplored); - - } else { - - // Bon, on part de la rangée devant le pion noir (du point de vue noir) et on va jusqu'à la 2ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) - // On regarde s'il y a un pion blanc ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions blancs, alors - // le pion noir est passé - int rankDebut = Rank.RANK_2.ordinal(); - int rankFin = row-1; - int fileDebut =col; - int fileFin = col; - if (col == 0) { - fileFin = File.FILE_B.ordinal(); - } else if (col == 7) { - fileDebut = File.FILE_G.ordinal(); - } else { - fileDebut = col - 1; - fileFin = col +1; - } - -// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); -// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); - - boolean areEnemyPawnInZone = false; - for (int rankk = rankDebut; rankk <= rankFin; rankk++) { - int rgSqDebutRank = getRgSquare(rankk, fileDebut); - int rgSqFintRank = getRgSquare(rankk, fileFin); - long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); - if (pionsAdversesDansZoneForRank != 0L) { - areEnemyPawnInZone = true; - return(false); - } - - } + + } - - if (areEnemyPawnInZone == false) { - return(true); - } - + + static boolean isBlackPawnPassed(int rawPawn, int colPawn, long bitboardWhitePawns) { + + if (bitboardWhitePawns == 0L) { + return(true); + } + // Bon, on part de la rangée devant le pion noir (du point de vue noir) et on va jusqu'à la 2ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) + // On regarde s'il y a un pion blanc ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions blancs, alors + // le pion noir est passé + int rankDebut = Rank.RANK_2.ordinal(); + int rankFin = rawPawn-1; + int fileDebut =colPawn; + int fileFin = colPawn; + if (colPawn == 0) { + fileFin = File.FILE_B.ordinal(); + } else if (colPawn == Hb2ChessConstants.INDEX_MAX_FILE) { + fileDebut = File.FILE_G.ordinal(); + } else { + fileDebut = colPawn - 1; + fileFin = colPawn +1; + } + + boolean areEnemyPawnInZoneToBeExplored = areEnemyPawnInZone( rankDebut, rankFin, fileDebut, fileFin,bitboardWhitePawns); + return ( areEnemyPawnInZoneToBeExplored); + + } + + static boolean isPawnPassed(int rawPawn, int colPawn , boolean isBlack, long bitboardWhitePawns, long bitboardBlackPawns) { + + + + + + + + if (!isBlack) { + + return(isWhitePawnPassed( rawPawn, colPawn, bitboardBlackPawns)); + } else { + return(isBlackPawnPassed( rawPawn, colPawn, bitboardWhitePawns)); } - return(true); } void copyTo(PawnsStrucEval other) { @@ -279,7 +286,58 @@ private void updateDoubledPawns(MoveData move) { } } - public int getContribMg() { + private void updatePasseddPawns(MoveData move) { + //TODO STALINE A CODER!! + int kind = Math.abs(move.getMovingPiece()); + if (kind != PAWN) { + return; + } + boolean isBlack = (move.getMovingPiece()<0?true:false); + int columnPawn = move.getMovingIndex()%Hb2ChessConstants.NB_FILES; + final int promoType = move.getPromotionType(); + if (promoType!=0) { + // If promotion, then the pawn disappears. + + + + // Get the pawn's column and decrement its number of pawns of its color + if (isBlack) { + modifyNumberOfBlackPawnsofColumn(columnPawn, (-1)); + } else { + modifyNumberOfWhitePawnsofColumn(columnPawn, (-1)); + } + return; // promotion. so we stop here: no chance of a pawn being captured... + + } + + int captured = move.getCapturedType(); + if (captured!=0) { + // Well the pawn with change columns...whatever it captures + int destinationColumnOfThePawn = move.getMovingDestination()%Hb2ChessConstants.NB_FILES; + if (isBlack) { + modifyNumberOfBlackPawnsofColumn(columnPawn, (-1)); + modifyNumberOfBlackPawnsofColumn(destinationColumnOfThePawn, 1); + } else { + modifyNumberOfWhitePawnsofColumn(columnPawn, (-1)); + modifyNumberOfWhitePawnsofColumn(destinationColumnOfThePawn, 1); + } + // If a piece was captured, we don't care; whereas if a pawn is captured, it'as another story... + if (Math.abs(captured)== PAWN) { + if (isBlack) { + // Black pawns are eating white pawns + modifyNumberOfWhitePawnsofColumn(destinationColumnOfThePawn, (-1)); + + } else { + // White pawns are eating black pawns + modifyNumberOfBlackPawnsofColumn(destinationColumnOfThePawn, (-1)); + + } + } + + } + } + + public int getContribDoubledPawnsMg() { // white doubled pawns int malusW = 0; @@ -297,29 +355,61 @@ public int getContribMg() { } } return(malusW - malusB); + } + public int getContribPassedPawnsMg() { + return(bonusWhitePassedPawnsMg - bonusBlackPassedPawnsMg); + + } - public int getContribEg() { + public int getContribMg() { + + int ctrbDoubledPawns = getContribDoubledPawnsMg(); + int ctrbPassedPawns = getContribPassedPawnsMg(); + + return(ctrbDoubledPawns+ctrbPassedPawns); + + + } + + + + public int getContribDoubledPawnsEg() { // white doubled pawns - int malusW = 0; - for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { - if (tabNbWhitePawnsByCol[i] > 1) { - malusW += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * MALUS_DOUBLED_PAWNS_EG; - } - } + int malusW = 0; + for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { + if (tabNbWhitePawnsByCol[i] > 1) { + malusW += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * MALUS_DOUBLED_PAWNS_EG; + } + } + + // black doubled pawns + int malusB = 0; + for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { + if (tabNbBlackPawnsByCol[i] > 1) { + malusB += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * MALUS_DOUBLED_PAWNS_EG; + } + } + return(malusW - malusB); - // black doubled pawns - int malusB = 0; - for (int i = 0; i < Hb2ChessConstants.NB_FILES; i++) { - if (tabNbBlackPawnsByCol[i] > 1) { - malusB += Hb2ChessConstants.NB_MAX_PAWNS_TAKEN_INTO_ACCOUNT_FOR_MALUS_DOUBLED_PAWNS * MALUS_DOUBLED_PAWNS_EG; - } - } - return(malusW - malusB); + } + + public int getContribPassedPawnsEg() { + return(bonusWhitePassedPawnsEg - bonusBlackPassedPawnsEg); + + + } + + public int getContribEg() { + + int ctrbDoubledPawns = getContribDoubledPawnsEg(); + int ctrbPassedPawns = getContribPassedPawnsEg(); + + return(ctrbDoubledPawns+ctrbPassedPawns); } From 1e497ad847287d724a27943222bd82097593e685 Mon Sep 17 00:00:00 2001 From: herve Date: Tue, 19 Nov 2024 09:24:07 +0100 Subject: [PATCH 46/55] =?UTF-8?q?Retour=20=C3=A0=20la=20v1.3.3=20de=20ches?= =?UTF-8?q?slib?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 3987279..f094a49 100644 --- a/pom.xml +++ b/pom.xml @@ -40,7 +40,7 @@ com.github.bhlangonijr chesslib - 1.3.4 + 1.3.3 com.fathzer diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java index 91a9ca5..66adf32 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java +++ b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java @@ -109,8 +109,7 @@ static void printDetailsAboutPawn(Square pawnSq, boolean isBlack,Board board) { fileFin = pawnSq.getFile().ordinal() +1; } //getRgSquare -// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); -// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); + // int rgDebutSq = (Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut; // int rgFinSq = (Hb2ChessConstants.NB_RANKS*rankFin)+fileFin; boolean areEnemyPawnInZone = false; @@ -124,9 +123,12 @@ static void printDetailsAboutPawn(Square pawnSq, boolean isBlack,Board board) { } } + +// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); +// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); // long ALL_BITS_EQUAL_ONE_BITBOARD = 0xFFFFFFFFFFFFFFFFL; // long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, sqDebut.ordinal(), sqFin.ordinal()); -// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, rgDebutSq, rgFinSq); +//// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, rgDebutSq, rgFinSq); // List lstKazz = Bitboard.bbToSquareList(pionsAdversesDansZone); // for (Square kaaaaz : lstKazz) { // System.out.println(kaaaaz.value()); From 50156299e5e3b63afb54b5c0b323962ba4169e1f Mon Sep 17 00:00:00 2001 From: herve Date: Wed, 20 Nov 2024 12:05:02 +0100 Subject: [PATCH 47/55] Passed pawns and connected pawns: first efficient and successful DIRTY test funded of powerful Bitboard masks and operations --- ...therVeryDirtyTestPassedConnectedPawns.java | 468 ++++++++++++++++++ .../chesslib/hbpg2/test/BitboardTries.java | 39 ++ 2 files changed, 507 insertions(+) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/AnotherVeryDirtyTestPassedConnectedPawns.java create mode 100644 src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/BitboardTries.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/AnotherVeryDirtyTestPassedConnectedPawns.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/AnotherVeryDirtyTestPassedConnectedPawns.java new file mode 100644 index 0000000..c5a2c44 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/AnotherVeryDirtyTestPassedConnectedPawns.java @@ -0,0 +1,468 @@ +package com.fathzer.jchess.chesslib.hbpg2.test; + +import static com.fathzer.chess.utils.Pieces.PAWN; + +import java.util.List; + +import com.fathzer.chess.utils.adapters.BoardExplorer; +import com.fathzer.jchess.chesslib.ChessLibBoardExplorer; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; +import com.github.bhlangonijr.chesslib.Bitboard; +import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.File; +import com.github.bhlangonijr.chesslib.Piece; +import com.github.bhlangonijr.chesslib.Rank; +import com.github.bhlangonijr.chesslib.Square; + + + +public class AnotherVeryDirtyTestPassedConnectedPawns { + + public static final long h_file = 0x8080808080808080L; + public static final long g_file = h_file >>> 1; + public static final long f_file = h_file >>> 2; + public static final long e_file = h_file >>> 3; + public static final long d_file = h_file >>> 4; + public static final long c_file = h_file >>> 5; + public static final long b_file = h_file >>> 6; + public static final long a_file = h_file >>> 7; + + public static final long rank_1 = 0x00000000000000FFL; + public static final long rank_2 = rank_1 << 8; + public static final long rank_3 = rank_1 << 16; + public static final long rank_4 = rank_1 << 24; + public static final long rank_5 = rank_1 << 32; + public static final long rank_6 = rank_1 << 40; + public static final long rank_7 = rank_1 << 48; + public static final long rank_8 = rank_1 << 56; + + + public static final long not_a_file = ~a_file; + public static final long not_h_file = ~h_file; + public static final long not_rank_1 = ~rank_1; + public static final long not_rank_8 = ~rank_8; + + public static final long[] whitePassedPawnMask = new long[] { + 0x0303030303030300L, 0x0707070707070700L, 0x0e0e0e0e0e0e0e00L, 0x1c1c1c1c1c1c1c00L, + 0x3838383838383800L, 0x7070707070707000L, 0xe0e0e0e0e0e0e000L, 0xc0c0c0c0c0c0c000L, + 0x0303030303030000L, 0x0707070707070000L, 0x0e0e0e0e0e0e0000L, 0x1c1c1c1c1c1c0000L, + 0x3838383838380000L, 0x7070707070700000L, 0xe0e0e0e0e0e00000L, 0xc0c0c0c0c0c00000L, + 0x0303030303000000L, 0x0707070707000000L, 0x0e0e0e0e0e000000L, 0x1c1c1c1c1c000000L, + 0x3838383838000000L, 0x7070707070000000L, 0xe0e0e0e0e0000000L, 0xc0c0c0c0c0000000L, + 0x0303030300000000L, 0x0707070700000000L, 0x0e0e0e0e00000000L, 0x1c1c1c1c00000000L, + 0x3838383800000000L, 0x7070707000000000L, 0xe0e0e0e000000000L, 0xc0c0c0c000000000L, + 0x0303030000000000L, 0x0707070000000000L, 0x0e0e0e0000000000L, 0x1c1c1c0000000000L, + 0x3838380000000000L, 0x7070700000000000L, 0xe0e0e00000000000L, 0xc0c0c00000000000L, + 0x0303000000000000L, 0x0707000000000000L, 0x0e0e000000000000L, 0x1c1c000000000000L, + 0x3838000000000000L, 0x7070000000000000L, 0xe0e0000000000000L, 0xc0c0000000000000L, + 0x0300000000000000L, 0x0700000000000000L, 0x0e00000000000000L, 0x1c00000000000000L, + 0x3800000000000000L, 0x7000000000000000L, 0xe000000000000000L, 0xc000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L + }; + + public static final long[] blackPassedPawnMask = new long[] { + + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000003L, 0x0000000000000007L, 0x000000000000000eL, 0x000000000000001cL, + 0x0000000000000038L, 0x0000000000000070L, 0x00000000000000e0L, 0x00000000000000c0L, + 0x0000000000000303L, 0x0000000000000707L, 0x0000000000000e0eL, 0x0000000000001c1cL, + 0x0000000000003838L, 0x0000000000007070L, 0x000000000000e0e0L, 0x000000000000c0c0L, + 0x0000000000030303L, 0x0000000000070707L, 0x00000000000e0e0eL, 0x00000000001c1c1cL, + 0x0000000000383838L, 0x0000000000707070L, 0x0000000000e0e0e0L, 0x0000000000c0c0c0L, + 0x0000000003030303L, 0x0000000007070707L, 0x000000000e0e0e0eL, 0x000000001c1c1c1cL, + 0x0000000038383838L, 0x0000000070707070L, 0x00000000e0e0e0e0L, 0x00000000c0c0c0c0L, + 0x0000000303030303L, 0x0000000707070707L, 0x0000000e0e0e0e0eL, 0x0000001c1c1c1c1cL, + 0x0000003838383838L, 0x0000007070707070L, 0x000000e0e0e0e0e0L, 0x000000c0c0c0c0c0L, + 0x0000030303030303L, 0x0000070707070707L, 0x00000e0e0e0e0e0eL, 0x00001c1c1c1c1c1cL, + 0x0000383838383838L, 0x0000707070707070L, 0x0000e0e0e0e0e0e0L, 0x0000c0c0c0c0c0c0L, + 0x0003030303030303L, 0x0007070707070707L, 0x000e0e0e0e0e0e0eL, 0x001c1c1c1c1c1c1cL, + 0x0038383838383838L, 0x0070707070707070L, 0x00e0e0e0e0e0e0e0L, 0x00c0c0c0c0c0c0c0L, + }; + + public static final long shiftWest(long b) { + return (b >>> 1) & not_h_file; + } + + public static final long shiftEast(long b) { + return (b << 1) & not_a_file; + } + + public static final long shiftSouth(long b) { + return b >>> 8; + } + + public static final long shiftNorth(long b) { + return b << 8; + } + + public static final long shiftNorthEast(long b) { + return (b << 9) & not_a_file; + } + + public static final long shiftSouthEast(long b) { + return (b >>> 7) & not_a_file; + } + + public static final long shiftSouthWest(long b) { + return (b >>> 9) & not_h_file; + } + + public static final long shiftNorthWest(long b) { + return (b << 7) & not_h_file; + } + + + public static int getIndex(Square square) { + return (Hb2ChessConstants.INDEX_MAX_RANK-square.getRank().ordinal())*Hb2ChessConstants.NB_RANKS+square.getFile().ordinal(); + } + + static int getRgSquare (int rank, int file) { + return((Hb2ChessConstants.NB_RANKS*rank)+file); + } + + static ChessLibMoveGenerator fromFEN(String fen) { + final Board board = new Board(); + board.loadFromFen(fen); + return new ChessLibMoveGenerator(board); + } + + + public static void printLstSquare(List lstSq) { + for (Square sq : lstSq) { + System.out.print(sq.value()); + System.out.print(" "); + } + System.out.println(); + } + + static void newPrintDetailsAboutPawn(Square pawnSq, boolean isBlack,Board board) { + +// /// STALINE +// if (pawnSq.name().equalsIgnoreCase("H3") == false) { +// return; +// } +// long toto = pawnSq.ordinal(); +// List lstSquaretoto = Bitboard.bbToSquareList(toto); +// printLstSquare(lstSquaretoto); +// toto = (1L << pawnSq.ordinal()); +// lstSquaretoto = Bitboard.bbToSquareList(toto); +// printLstSquare(lstSquaretoto); + + long bitBoardWhitePawns = board.getBitboard(Piece.WHITE_PAWN); + long connectedPawnsEastWhite = shiftNorthEast(bitBoardWhitePawns) & bitBoardWhitePawns; + long connectedPawnsWestWhite = shiftNorthWest(bitBoardWhitePawns) & bitBoardWhitePawns; + + List lstSquare = Bitboard.bbToSquareList(connectedPawnsEastWhite); + printLstSquare(lstSquare); + lstSquare = Bitboard.bbToSquareList(connectedPawnsWestWhite); + printLstSquare(lstSquare); + + long bitBoardBlackPawns = board.getBitboard(Piece.BLACK_PAWN); + long connectedPawnsEastBlack = shiftSouthEast(bitBoardBlackPawns) & bitBoardBlackPawns; + long connectedPawnsWestBlack = shiftSouthWest(bitBoardBlackPawns) & bitBoardBlackPawns; + List lstSquareBP = Bitboard.bbToSquareList(connectedPawnsEastBlack); + printLstSquare(lstSquareBP); + lstSquare = Bitboard.bbToSquareList(connectedPawnsWestBlack); + printLstSquare(lstSquare); + + + System.out.println(); + System.out.println(); + System.out.println("####################"); + if (isBlack) { + System.out.println("BLACK PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); + } else { + System.out.println("WHITE PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); + } + int indexCazz = getIndex(pawnSq); + System.out.println("Index JMA case "+ pawnSq.value()+":"+ indexCazz); + Square[] tabAdjSquares = pawnSq.getSideSquares(); + System.out.println("Cases adjacentes de la case "+ pawnSq.value()+":"); + for (int i = 0; i < tabAdjSquares.length; i++) { + System.out.println(tabAdjSquares[i].value()); + + } + + + int columnPawn = indexCazz%Hb2ChessConstants.NB_FILES; + int rankPawn =Hb2ChessConstants.INDEX_MAX_RANK-pawnSq.getRank().ordinal(); + System.out.println("rankPawn_JMA:"+ rankPawn); + System.out.println("columnPawn_JMA:"+ columnPawn); + +// if (isBlack ) { +// if ( pawnSq.getRank() == Rank.RANK_2) { +// // A black pawn on the 2nd rank is a passer, by nature +// System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); +// System.out.println("####################"); +// System.out.println(); +// System.out.println(); +// return; +// } +// +// } else { +// if ( pawnSq.getRank() == Rank.RANK_7) { +// // A white pawn on the 7th rank is a passer, by nature +// System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); +// System.out.println("####################"); +// System.out.println(); +// System.out.println(); +// return; +// } +// } +// + + + Piece enemyPawn = (isBlack?Piece.WHITE_PAWN:Piece.BLACK_PAWN); + long bitboardEnemyPawns = board.getBitboard(enemyPawn); +// if (bitboardEnemyPawns == 0L) { +// System.out.println("THE "+ (isBlack?"BLACK ":"WHITE ") + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); +// } + long testPassedPawn = 0L; + if (!isBlack) { + testPassedPawn = whitePassedPawnMask[pawnSq.ordinal()] & bitboardEnemyPawns; + } else { + testPassedPawn = blackPassedPawnMask[pawnSq.ordinal()] & bitboardEnemyPawns; + } + if (testPassedPawn == 0L) { + if (!isBlack) { + + System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); + + } else { + System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); + } + + } + + +// long bitBoardWhitePawns = board.getBitboard(Piece.WHITE_PAWN); +// long connectedPawnsEastWhite = shiftNorthEast(bitBoardWhitePawns) & bitBoardWhitePawns; +// long connectedPawnsWestWhite = shiftNorthWest(bitBoardWhitePawns) & bitBoardWhitePawns; +// +// long bitBoardBlackPawns = board.getBitboard(Piece.BLACK_PAWN); +// long connectedPawnsEastBlack = shiftSouthEast(bitBoardBlackPawns) & bitBoardBlackPawns; +// long connectedPawnsWestBlack = shiftSouthWest(bitBoardBlackPawns) & bitBoardBlackPawns; + if (!isBlack) { + + boolean connectedWhitePawn = ( (1L << pawnSq.ordinal()) & (connectedPawnsEastWhite | connectedPawnsWestWhite)) != 0; + if (connectedWhitePawn) { + System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A CONNECTED PAWN!"); + } + + } else { + boolean connectedBlackPawn = ((1L << pawnSq.ordinal()) & (connectedPawnsEastBlack | connectedPawnsWestBlack)) != 0; + if (connectedBlackPawn) { + System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A CONNECTED PAWN!"); + } + + } + + + +// if (!isBlack) { +// +// // Bon, on part de la rangée devant le pion blanc et on va jusqu'à la 7ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) +// // On regarde s'il y a un pion noir ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions noirs, alors +// // le pion blanc est passé +// int rankDebut = pawnSq.getRank().ordinal()+1; +// int rankFin = Rank.RANK_7.ordinal(); +// int fileDebut = pawnSq.getFile().ordinal(); +// int fileFin = pawnSq.getFile().ordinal(); +// if (columnPawn == 0) { +// fileFin = File.FILE_B.ordinal(); +// } else if (columnPawn == 7) { +// fileDebut = File.FILE_G.ordinal(); +// } else { +// fileDebut = pawnSq.getFile().ordinal() - 1; +// fileFin = pawnSq.getFile().ordinal() +1; +// } +// //getRgSquare +// +//// int rgDebutSq = (Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut; +//// int rgFinSq = (Hb2ChessConstants.NB_RANKS*rankFin)+fileFin; +// boolean areEnemyPawnInZone = false; +// for (int rankk = rankDebut; rankk <= rankFin; rankk++) { +// int rgSqDebutRank = getRgSquare(rankk, fileDebut); +// int rgSqFintRank = getRgSquare(rankk, fileFin); +// long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); +// if (pionsAdversesDansZoneForRank != 0L) { +// areEnemyPawnInZone = true; +// break; +// } +// +// } +// +//// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); +//// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); +//// long ALL_BITS_EQUAL_ONE_BITBOARD = 0xFFFFFFFFFFFFFFFFL; +//// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, sqDebut.ordinal(), sqFin.ordinal()); +////// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, rgDebutSq, rgFinSq); +//// List lstKazz = Bitboard.bbToSquareList(pionsAdversesDansZone); +//// for (Square kaaaaz : lstKazz) { +//// System.out.println(kaaaaz.value()); +//// } +// if (areEnemyPawnInZone == false) { +// System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); +// } +// +// +// +// +// } else { +// +// // Bon, on part de la rangée devant le pion noir (du point de vue noir) et on va jusqu'à la 2ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) +// // On regarde s'il y a un pion blanc ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions blancs, alors +// // le pion noir est passé +// int rankDebut = Rank.RANK_2.ordinal(); +// int rankFin = pawnSq.getRank().ordinal()-1; +// int fileDebut = pawnSq.getFile().ordinal(); +// int fileFin = pawnSq.getFile().ordinal(); +// if (columnPawn == 0) { +// fileFin = File.FILE_B.ordinal(); +// } else if (columnPawn == 7) { +// fileDebut = File.FILE_G.ordinal(); +// } else { +// fileDebut = pawnSq.getFile().ordinal() - 1; +// fileFin = pawnSq.getFile().ordinal() +1; +// } +// +//// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); +//// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); +// +// boolean areEnemyPawnInZone = false; +// for (int rankk = rankDebut; rankk <= rankFin; rankk++) { +// int rgSqDebutRank = getRgSquare(rankk, fileDebut); +// int rgSqFintRank = getRgSquare(rankk, fileFin); +// long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); +// if (pionsAdversesDansZoneForRank != 0L) { +// areEnemyPawnInZone = true; +// break; +// } +// +// } +// +// +// if (areEnemyPawnInZone == false) { +// System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); +// } +// +// +// } + + System.out.println("####################"); + System.out.println(); + System.out.println(); + + } + + static void newDeallWithSquareOccupiedByPawn(Square pawnSq, boolean isBlack, Board board) { + + newPrintDetailsAboutPawn(pawnSq, isBlack, board); + + } + + + + static void testFen1() { + + + testFen("6k1/8/1Pp5/8/8/3P4/1K6/8 w - - 0 1"); + + + } + + + + static void testFen2() { +// testFen("6k1/8/1Pp5/8/8/3P3p/1K2Pp2/8 w - - 0 1"); + testFen("6k1/8/1Pp5/8/6p1/3P3p/1K2Pp2/8 w - - 0 1"); + + + + } + static void testFen3() { + testFen("6k1/8/1Pp5/8/8/7p/1K1PPp2/8 w - - 0 1"); + + + } + + + static void testFen(String fen) { + +// long bbBlackPawnsOccupancy = 0L; +// long bbWhitePawnsOccupancy = 0L; + System.out.println(); + System.out.println("FEN en test pour les pions passés:" + fen); + Board internal = new Board(); + internal.loadFromFen(fen); + ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(internal); + + System.out.println(internal.toStringFromWhiteViewPoint()); + +// BoardExplorer explorer0 = new ChessLibBoardExplorer(mvg.getBoard()); +// do { +// final int p = explorer0.getPiece(); +// +// final int kind = Math.abs(p); +// final int index = explorer0.getIndex(); +// final boolean isBlack = p<0; +// if (kind == PAWN) { +// int row = Hb2ChessConstants.INDEX_MAX_RANK - index/Hb2ChessConstants.NB_RANKS; +// int col = index%Hb2ChessConstants.NB_FILES; +// Square sqp = Square.squareAt((Hb2ChessConstants.NB_RANKS*row)+col); +// long bbPawn = Bitboard.getBbtable(sqp); +// if (isBlack) { +// bbBlackPawnsOccupancy = bbBlackPawnsOccupancy | bbPawn; +// } else { +// bbWhitePawnsOccupancy = bbWhitePawnsOccupancy | bbPawn; +// } +// +// +// } +// +// } while (explorer0.next()); +// +// List lstSquareWhitePawns = Bitboard.bbToSquareList(bbWhitePawnsOccupancy); +// BitboardTries.printLstSquare(lstSquareWhitePawns); +// +// List lstSquareBlackPawns = Bitboard.bbToSquareList(bbBlackPawnsOccupancy); +// BitboardTries.printLstSquare(lstSquareBlackPawns); + + + BoardExplorer explorer = new ChessLibBoardExplorer(mvg.getBoard()); + do { + final int p = explorer.getPiece(); + + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isBlack = p<0; + if (kind == PAWN) { + int row = Hb2ChessConstants.INDEX_MAX_RANK - index/Hb2ChessConstants.NB_RANKS; + int col = index%Hb2ChessConstants.NB_FILES; + Square sqp = Square.squareAt((Hb2ChessConstants.NB_RANKS*row)+col); + + newDeallWithSquareOccupiedByPawn(sqp, isBlack, mvg.getBoard()); + + } + + } while (explorer.next()); + + System.out.println(); + System.out.println(); + System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + System.out.println(); + System.out.println(); + + } + + public static void main(String[] args) { +// testFen1(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen1.gif + testFen2(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen2.gif +// testFen3(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen3.gif + } + + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/BitboardTries.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/BitboardTries.java new file mode 100644 index 0000000..5999e12 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/BitboardTries.java @@ -0,0 +1,39 @@ +package com.fathzer.jchess.chesslib.hbpg2.test; + +import java.util.List; + +import com.github.bhlangonijr.chesslib.Bitboard; +import com.github.bhlangonijr.chesslib.Square; + +public class BitboardTries { + + public static void printLongAsBinary(long l) { + for(int i = 0; i < Long.numberOfLeadingZeros((long)l); i++) { + System.out.print('0'); + } + System.out.println(Long.toBinaryString((long)l)); + } + + public static void printLstSquare(List lstSq) { + for (Square sq : lstSq) { + System.out.print(sq.value()); + System.out.print(" "); + } + System.out.println(); + } + + + public static void main(String[] args) { + // TODO Auto-generated method stub + List lstSquare = Bitboard.bbToSquareList(256L); + printLstSquare(lstSquare); + List lstSquare2 = Bitboard.bbToSquareList(1L); + printLstSquare(lstSquare2); + List lstSquare3 = Bitboard.bbToSquareList(1099511627776L); + printLstSquare(lstSquare3); + List lstSquare4 = Bitboard.bbToSquareList(512L); + printLstSquare(lstSquare4); + + } + +} From b9bdd508a482d34048d1c1c61d0ff879f989c1b6 Mon Sep 17 00:00:00 2001 From: herve Date: Thu, 21 Nov 2024 12:08:14 +0100 Subject: [PATCH 48/55] Cleaning; and taking into account protected passed pawns; use of bitboard maks from https://github.com/Luecx/Chess.git (GNU PUBLIC LICENCE) --- .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 11 +- .../ai/eval/hbpg2/Hb2BitboardsUtils.java | 91 ++++ .../ai/eval/hbpg2/Hb2IncrementalState.java | 20 +- .../ai/eval/hbpg2/Hb2MyFirstEvaluator.java | 12 +- .../additional/ChessEvalAdditionalElems.java | 10 +- .../eval/hbpg2/additional/PawnsStrucEval.java | 223 ++++++--- ...therVeryDirtyTestPassedConnectedPawns.java | 468 ------------------ .../chesslib/hbpg2/test/BitboardTries.java | 39 -- .../hbpg2/test/VeryDirtyTestPasserPawns.java | 263 ---------- .../chesslib/hbpg2/test/package-info.java | 7 - .../jchess/chesslib/ai/HBThreeMovesTest.java | 9 +- .../ai/HBThreeMovesTestPassedPawns.java | 40 ++ 12 files changed, 329 insertions(+), 864 deletions(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BitboardsUtils.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/AnotherVeryDirtyTestPassedConnectedPawns.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/BitboardTries.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java delete mode 100644 src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/package-info.java create mode 100644 src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTestPassedPawns.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index 507a91c..123a9cf 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -21,14 +21,7 @@ public void copyTo(Hb2BasicState other) { other.chessEvalAdditionalElems = new ChessEvalAdditionalElems(this.chessEvalAdditionalElems); -// other.pointsMg = pointsMg; -// other.pointsEg= pointsEg; -// other.pointsPosMg = pointsPosMg; -// other.pointsPosEg= pointsPosEg; -// other.blackKingIndex = blackKingIndex; -// other.whiteKingIndex = whiteKingIndex; -// other.computedPhase = computedPhase; -// other.board = board; + } @@ -36,7 +29,7 @@ public void copyTo(Hb2BasicState other) { Hb2BasicState(BoardExplorer explorer, Board board) { super(explorer, board); - chessEvalAdditionalElems = new ChessEvalAdditionalElems(new ChessLibBoardExplorer(board), board); + chessEvalAdditionalElems = new ChessEvalAdditionalElems( board); } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BitboardsUtils.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BitboardsUtils.java new file mode 100644 index 0000000..5f17728 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BitboardsUtils.java @@ -0,0 +1,91 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2; + +public class Hb2BitboardsUtils { + + public static final long h_file = 0x8080808080808080L; + public static final long g_file = h_file >>> 1; + public static final long f_file = h_file >>> 2; + public static final long e_file = h_file >>> 3; + public static final long d_file = h_file >>> 4; + public static final long c_file = h_file >>> 5; + public static final long b_file = h_file >>> 6; + public static final long a_file = h_file >>> 7; + + public static final long rank_1 = 0x00000000000000FFL; + public static final long rank_2 = rank_1 << 8; + public static final long rank_3 = rank_1 << 16; + public static final long rank_4 = rank_1 << 24; + public static final long rank_5 = rank_1 << 32; + public static final long rank_6 = rank_1 << 40; + public static final long rank_7 = rank_1 << 48; + public static final long rank_8 = rank_1 << 56; + + public static final long not_a_file = ~a_file; + public static final long not_h_file = ~h_file; + public static final long not_rank_1 = ~rank_1; + public static final long not_rank_8 = ~rank_8; + + public static final long[] whitePassedPawnMask = new long[] { 0x0303030303030300L, 0x0707070707070700L, + 0x0e0e0e0e0e0e0e00L, 0x1c1c1c1c1c1c1c00L, 0x3838383838383800L, 0x7070707070707000L, 0xe0e0e0e0e0e0e000L, + 0xc0c0c0c0c0c0c000L, 0x0303030303030000L, 0x0707070707070000L, 0x0e0e0e0e0e0e0000L, 0x1c1c1c1c1c1c0000L, + 0x3838383838380000L, 0x7070707070700000L, 0xe0e0e0e0e0e00000L, 0xc0c0c0c0c0c00000L, 0x0303030303000000L, + 0x0707070707000000L, 0x0e0e0e0e0e000000L, 0x1c1c1c1c1c000000L, 0x3838383838000000L, 0x7070707070000000L, + 0xe0e0e0e0e0000000L, 0xc0c0c0c0c0000000L, 0x0303030300000000L, 0x0707070700000000L, 0x0e0e0e0e00000000L, + 0x1c1c1c1c00000000L, 0x3838383800000000L, 0x7070707000000000L, 0xe0e0e0e000000000L, 0xc0c0c0c000000000L, + 0x0303030000000000L, 0x0707070000000000L, 0x0e0e0e0000000000L, 0x1c1c1c0000000000L, 0x3838380000000000L, + 0x7070700000000000L, 0xe0e0e00000000000L, 0xc0c0c00000000000L, 0x0303000000000000L, 0x0707000000000000L, + 0x0e0e000000000000L, 0x1c1c000000000000L, 0x3838000000000000L, 0x7070000000000000L, 0xe0e0000000000000L, + 0xc0c0000000000000L, 0x0300000000000000L, 0x0700000000000000L, 0x0e00000000000000L, 0x1c00000000000000L, + 0x3800000000000000L, 0x7000000000000000L, 0xe000000000000000L, 0xc000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L }; + + public static final long[] blackPassedPawnMask = new long[] { + + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000003L, 0x0000000000000007L, + 0x000000000000000eL, 0x000000000000001cL, 0x0000000000000038L, 0x0000000000000070L, 0x00000000000000e0L, + 0x00000000000000c0L, 0x0000000000000303L, 0x0000000000000707L, 0x0000000000000e0eL, 0x0000000000001c1cL, + 0x0000000000003838L, 0x0000000000007070L, 0x000000000000e0e0L, 0x000000000000c0c0L, 0x0000000000030303L, + 0x0000000000070707L, 0x00000000000e0e0eL, 0x00000000001c1c1cL, 0x0000000000383838L, 0x0000000000707070L, + 0x0000000000e0e0e0L, 0x0000000000c0c0c0L, 0x0000000003030303L, 0x0000000007070707L, 0x000000000e0e0e0eL, + 0x000000001c1c1c1cL, 0x0000000038383838L, 0x0000000070707070L, 0x00000000e0e0e0e0L, 0x00000000c0c0c0c0L, + 0x0000000303030303L, 0x0000000707070707L, 0x0000000e0e0e0e0eL, 0x0000001c1c1c1c1cL, 0x0000003838383838L, + 0x0000007070707070L, 0x000000e0e0e0e0e0L, 0x000000c0c0c0c0c0L, 0x0000030303030303L, 0x0000070707070707L, + 0x00000e0e0e0e0e0eL, 0x00001c1c1c1c1c1cL, 0x0000383838383838L, 0x0000707070707070L, 0x0000e0e0e0e0e0e0L, + 0x0000c0c0c0c0c0c0L, 0x0003030303030303L, 0x0007070707070707L, 0x000e0e0e0e0e0e0eL, 0x001c1c1c1c1c1c1cL, + 0x0038383838383838L, 0x0070707070707070L, 0x00e0e0e0e0e0e0e0L, 0x00c0c0c0c0c0c0c0L, }; + + public static final long shiftWest(long b) { + return (b >>> 1) & not_h_file; + } + + public static final long shiftEast(long b) { + return (b << 1) & not_a_file; + } + + public static final long shiftSouth(long b) { + return b >>> 8; + } + + public static final long shiftNorth(long b) { + return b << 8; + } + + public static final long shiftNorthEast(long b) { + return (b << 9) & not_a_file; + } + + public static final long shiftSouthEast(long b) { + return (b >>> 7) & not_a_file; + } + + public static final long shiftSouthWest(long b) { + return (b >>> 9) & not_h_file; + } + + public static final long shiftNorthWest(long b) { + return (b << 7) & not_h_file; + } + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index ae2201f..a3d6718 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -23,22 +23,22 @@ public class Hb2IncrementalState extends Hb2BasicState { - void update(MoveData move) { - pointsMg += getIncrementMg(move); - pointsEg += getIncrementEg(move); - pointsPosMg += getIncrementPosMg(move); - pointsPosEg += getIncrementPosEg(move); - chessEvalAdditionalElems.upadateEvalAdditionalElems(move); - updatePhase(move); - } +// void update(MoveData move) { +// pointsMg += getIncrementMg(move); +// pointsEg += getIncrementEg(move); +// pointsPosMg += getIncrementPosMg(move); +// pointsPosEg += getIncrementPosEg(move); +// chessEvalAdditionalElems.updateEvalAdditionalElems(move); +// updatePhase(move); +// } - //TODO STALINE à coder + void update(MoveData move, Board board) { pointsMg += getIncrementMg(move); pointsEg += getIncrementEg(move); pointsPosMg += getIncrementPosMg(move); pointsPosEg += getIncrementPosEg(move); - chessEvalAdditionalElems.upadateEvalAdditionalElems(move); + chessEvalAdditionalElems.updateEvalAdditionalElems(move, board); updatePhase(move); } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java index 6bdfe38..e92c014 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java @@ -35,11 +35,17 @@ public static void main(String[] args) { // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(new Board()); // mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); - mvg.getBoard().loadFromFen("5k2/p1p2pp1/4b1p1/4p3/1P2P3/p2P1B2/1b2NP1P/6K1 w - - 0 1"); - System.out.println(new Hb2MyFirstEvaluator().evaluate(mvg)); - mvg.getBoard().loadFromFen("8/p1p1kppp/4b3/4p1P1/1P2P2P/p2P1B2/1b2NP2/6K1 w - - 0 1"); +// mvg.getBoard().loadFromFen("5k2/p1p2pp1/4b1p1/4p3/1P2P3/p2P1B2/1b2NP1P/6K1 w - - 0 1"); +// System.out.println(new Hb2MyFirstEvaluator().evaluate(mvg)); +// mvg.getBoard().loadFromFen("8/p1p1kppp/4b3/4p1P1/1P2P2P/p2P1B2/1b2NP2/6K1 w - - 0 1"); + + + + final String fen = "8/3k3p/2R5/3PP3/8/1p2K3/7r/8 w - - 0 1"; +// final String fen = "8/3k3p/2R1P3/3P4/8/1p2K3/7r/8 w - - 0 1"; + mvg.getBoard().loadFromFen(fen); System.out.println(new Hb2MyFirstEvaluator().evaluate(mvg)); } } \ No newline at end of file diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java index da92ac3..394051c 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java @@ -1,6 +1,6 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg2.additional; -import com.fathzer.chess.utils.adapters.BoardExplorer; + import com.fathzer.chess.utils.adapters.MoveData; import com.github.bhlangonijr.chesslib.Board; @@ -17,8 +17,8 @@ public ChessEvalAdditionalElems(ChessEvalAdditionalElems ceae) { } - public ChessEvalAdditionalElems(BoardExplorer explorer, Board board) { - pawnsStructEval = new PawnsStrucEval(explorer, board); + public ChessEvalAdditionalElems(Board board) { + pawnsStructEval = new PawnsStrucEval( board); } public void copyTo(ChessEvalAdditionalElems other) { @@ -26,8 +26,8 @@ public void copyTo(ChessEvalAdditionalElems other) { } - public void upadateEvalAdditionalElems(MoveData move) { - pawnsStructEval.updatePawnsStructEval(move); + public void updateEvalAdditionalElems(MoveData move, Board board) { + pawnsStructEval.updatePawnsStructEval(move, board); } public PawnsStrucEval getPawnsStructEval() { diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index 2aef723..d63f1ec 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -3,16 +3,19 @@ import static com.fathzer.chess.utils.Pieces.PAWN; import java.util.Arrays; +import java.util.List; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; +import com.fathzer.jchess.chesslib.ChessLibBoardExplorer; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2BitboardsUtils; import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; import com.github.bhlangonijr.chesslib.Bitboard; import com.github.bhlangonijr.chesslib.Board; import com.github.bhlangonijr.chesslib.File; import com.github.bhlangonijr.chesslib.Piece; import com.github.bhlangonijr.chesslib.Rank; -import com.github.bhlangonijr.chesslib.Side; +import com.github.bhlangonijr.chesslib.Square; public class PawnsStrucEval { @@ -31,6 +34,9 @@ public class PawnsStrucEval { private static final int PASSED_PAWN_BONUS_6_TH_RANK_EG = 30; private static final int PASSED_PAWN_BONUS_7_TH_RANK_EG = 33; + private static final int PROTECTED_PASSED_PAWN_BONUS_MG = 20; + private static final int PROTECTED_PASSED_PAWN_BONUS_EG = 50; + // Here the ranks are relative to the side. For black, the seventh rank is the 2nd rank private static final int[] TAB_PASSED_PAWN_BONUS_BY_RANK_MG = {0,PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK, @@ -43,7 +49,7 @@ public class PawnsStrucEval { {0,PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK_EG, PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK_EG, PASSED_PAWN_BONUS_LESS_THAN_5TH_RANK_EG, - PASSED_PAWN_BONUS,PASSED_PAWN_BONUS_6_TH_RANK_EG,PASSED_PAWN_BONUS_7_TH_RANK_EG, + PASSED_PAWN_BONUS_EG,PASSED_PAWN_BONUS_6_TH_RANK_EG,PASSED_PAWN_BONUS_7_TH_RANK_EG, 0}; private Board board; @@ -66,20 +72,27 @@ public PawnsStrucEval() { } public PawnsStrucEval(PawnsStrucEval pse) { + + this.board = pse.board; // Since it's an array of integers, the copy is not a shallow copy tabNbWhitePawnsByCol = Arrays.copyOf(pse.tabNbWhitePawnsByCol, Hb2ChessConstants.NB_FILES); // Since it's an array of integers, the copy is not a shallow copy tabNbBlackPawnsByCol = Arrays.copyOf(pse.tabNbBlackPawnsByCol, Hb2ChessConstants.NB_FILES); + + bonusWhitePassedPawnsMg = pse.bonusWhitePassedPawnsMg; + bonusWhitePassedPawnsEg = pse.bonusWhitePassedPawnsEg; + bonusBlackPassedPawnsMg = pse.bonusBlackPassedPawnsMg; + bonusBlackPassedPawnsEg = pse.bonusBlackPassedPawnsEg; } - public PawnsStrucEval(BoardExplorer explorer, Board board) { - this(); + + + private void computeDoubledPawns() { + + BoardExplorer explorer = new ChessLibBoardExplorer(this.board); - long bitboardWhitePawns = board.getBitboard(Piece.WHITE_PAWN); - long bitboardBlackPawns = board.getBitboard(Piece.BLACK_PAWN); - this.board = board; for (int i= 0; i < Hb2ChessConstants.NB_FILES; i++) { tabNbWhitePawnsByCol[i] = 0; tabNbBlackPawnsByCol[i] = 0; @@ -93,7 +106,7 @@ public PawnsStrucEval(BoardExplorer explorer, Board board) { if (kind==PAWN) { final int columnPawn = index%Hb2ChessConstants.NB_FILES; - int rawPawn = Hb2ChessConstants.INDEX_MAX_RANK - index/Hb2ChessConstants.NB_RANKS; + if (isPieceBlack) { @@ -102,16 +115,73 @@ public PawnsStrucEval(BoardExplorer explorer, Board board) { tabNbWhitePawnsByCol[columnPawn]++; } - boolean isPassedPawn = isPawnPassed(rawPawn, columnPawn, isPieceBlack, bitboardWhitePawns, bitboardBlackPawns); + + + } + } while (explorer.next()); + + } + + private void computePassedAndProtectedPassedPawns() { + + BoardExplorer explorer = new ChessLibBoardExplorer(this.board); + + bonusWhitePassedPawnsEg = 0; + bonusBlackPassedPawnsMg = 0; + bonusBlackPassedPawnsMg = 0; + bonusBlackPassedPawnsEg = 0; + + long bitboardWhitePawns = board.getBitboard(Piece.WHITE_PAWN); + long bitboardBlackPawns = board.getBitboard(Piece.BLACK_PAWN); + + + long connectedPawnsEastWhite = Hb2BitboardsUtils.shiftNorthEast(bitboardWhitePawns) & bitboardWhitePawns; + long connectedPawnsWestWhite = Hb2BitboardsUtils.shiftNorthWest(bitboardWhitePawns) & bitboardWhitePawns; + + + long connectedPawnsEastBlack = Hb2BitboardsUtils.shiftSouthEast(bitboardBlackPawns) & bitboardBlackPawns; + long connectedPawnsWestBlack = Hb2BitboardsUtils.shiftSouthWest(bitboardBlackPawns) & bitboardBlackPawns; + + do { + final int p = explorer.getPiece(); + final int kind = Math.abs(p); + final int index = explorer.getIndex(); + final boolean isPieceBlack = p<0; + if (kind==PAWN) { + + final int columnPawn = index%Hb2ChessConstants.NB_FILES; + int rowPawn = Hb2ChessConstants.INDEX_MAX_RANK - index/Hb2ChessConstants.NB_RANKS; + + + + + boolean isPassedPawn = isPawnPassedModernWay(rowPawn, columnPawn, isPieceBlack, bitboardWhitePawns, bitboardBlackPawns); if (isPassedPawn) { if (isPieceBlack) { - bonusBlackPassedPawnsMg += TAB_PASSED_PAWN_BONUS_BY_RANK_MG[Hb2ChessConstants.INDEX_MAX_RANK - rawPawn]; - bonusBlackPassedPawnsEg += TAB_PASSED_PAWN_BONUS_BY_RANK_EG[Hb2ChessConstants.INDEX_MAX_RANK - rawPawn]; + bonusBlackPassedPawnsMg += TAB_PASSED_PAWN_BONUS_BY_RANK_MG[Hb2ChessConstants.INDEX_MAX_RANK - rowPawn]; + bonusBlackPassedPawnsEg += TAB_PASSED_PAWN_BONUS_BY_RANK_EG[Hb2ChessConstants.INDEX_MAX_RANK - rowPawn]; + + } else { + bonusWhitePassedPawnsMg += TAB_PASSED_PAWN_BONUS_BY_RANK_MG[rowPawn]; + bonusWhitePassedPawnsEg += TAB_PASSED_PAWN_BONUS_BY_RANK_EG[rowPawn]; + } + } + + boolean isProtectedPawn = isPawnProtectedModernWay( rowPawn, columnPawn , isPieceBlack, + connectedPawnsEastWhite, connectedPawnsWestWhite, + connectedPawnsEastBlack, connectedPawnsWestBlack); + + + if (isProtectedPawn) { + + if (isPieceBlack) { + bonusBlackPassedPawnsMg += PROTECTED_PASSED_PAWN_BONUS_MG; + bonusBlackPassedPawnsEg += PROTECTED_PASSED_PAWN_BONUS_EG; } else { - bonusWhitePassedPawnsMg += TAB_PASSED_PAWN_BONUS_BY_RANK_MG[rawPawn]; - bonusWhitePassedPawnsEg += TAB_PASSED_PAWN_BONUS_BY_RANK_EG[rawPawn]; + bonusWhitePassedPawnsMg += PROTECTED_PASSED_PAWN_BONUS_MG; + bonusWhitePassedPawnsEg += PROTECTED_PASSED_PAWN_BONUS_EG; } } @@ -119,6 +189,15 @@ public PawnsStrucEval(BoardExplorer explorer, Board board) { } } while (explorer.next()); + } + + public PawnsStrucEval( Board board) { + this(); + this.board = board; + computeDoubledPawns( ); + computePassedAndProtectedPassedPawns( ); + + } @@ -201,7 +280,7 @@ static boolean isBlackPawnPassed(int rawPawn, int colPawn, long bitboardWhitePaw } - static boolean isPawnPassed(int rawPawn, int colPawn , boolean isBlack, long bitboardWhitePawns, long bitboardBlackPawns) { + static boolean isPawnPassed(int rowPawn, int colPawn , boolean isBlack, long bitboardWhitePawns, long bitboardBlackPawns) { @@ -211,13 +290,61 @@ static boolean isPawnPassed(int rawPawn, int colPawn , boolean isBlack, long bit if (!isBlack) { - return(isWhitePawnPassed( rawPawn, colPawn, bitboardBlackPawns)); + return(isWhitePawnPassed( rowPawn, colPawn, bitboardBlackPawns)); } else { - return(isBlackPawnPassed( rawPawn, colPawn, bitboardWhitePawns)); + return(isBlackPawnPassed( rowPawn, colPawn, bitboardWhitePawns)); + } + + } + + public static boolean isPawnPassedModernWay(int rowPawn, int colPawn , boolean isBlack, long bitboardWhitePawns, long bitboardBlackPawns) { + + + int ordinalSquarePawn = (Hb2ChessConstants.NB_RANKS*rowPawn)+colPawn; + + long testPassedPawn = 0L; + if (!isBlack) { + testPassedPawn = Hb2BitboardsUtils.whitePassedPawnMask[ordinalSquarePawn] & bitboardBlackPawns; + } else { + testPassedPawn = Hb2BitboardsUtils.blackPassedPawnMask[ordinalSquarePawn] & bitboardWhitePawns; + } + + if (testPassedPawn == 0L) { + return(true); + } + return(false); + + + + + } + + public static boolean isPawnProtectedModernWay(int rowPawn, int colPawn , boolean isBlack, + long connectedPawnsEastWhite, long connectedPawnsWestWhite, + long connectedPawnsEastBlack, long connectedPawnsWestBlack) { + int ordinalSquarePawn = (Hb2ChessConstants.NB_RANKS*rowPawn)+colPawn; + boolean isPawnProtected = false; + if (!isBlack) { + + isPawnProtected = ( (1L << ordinalSquarePawn) & (connectedPawnsEastWhite | connectedPawnsWestWhite)) != 0; + + + } else { + isPawnProtected = ((1L << ordinalSquarePawn) & (connectedPawnsEastBlack | connectedPawnsWestBlack)) != 0; + + + }; + return (isPawnProtected); + + } + + + + void copyTo(PawnsStrucEval other) { other.board = board; other.tabNbBlackPawnsByCol = tabNbBlackPawnsByCol.clone(); // not a shallow copy!!!! For integers are of primitive type... @@ -231,8 +358,9 @@ public void modifyNumberOfBlackPawnsofColumn(int column, int nbPawns ) { public void modifyNumberOfWhitePawnsofColumn(int column, int nbPawns ) { tabNbWhitePawnsByCol[column] += nbPawns; } - public void updatePawnsStructEval(MoveData move) { + public void updatePawnsStructEval(MoveData move, Board board) { updateDoubledPawns(move); + updatePassedAndProtectePassedPawns(move); } @@ -286,55 +414,38 @@ private void updateDoubledPawns(MoveData move) { } } - private void updatePasseddPawns(MoveData move) { - //TODO STALINE A CODER!! - int kind = Math.abs(move.getMovingPiece()); - if (kind != PAWN) { - return; - } + + private void updatePassedAndProtectePassedPawns(MoveData move) { boolean isBlack = (move.getMovingPiece()<0?true:false); - int columnPawn = move.getMovingIndex()%Hb2ChessConstants.NB_FILES; - final int promoType = move.getPromotionType(); - if (promoType!=0) { - // If promotion, then the pawn disappears. - - + int kind = Math.abs(move.getMovingPiece()); + if (kind == PAWN) { - // Get the pawn's column and decrement its number of pawns of its color - if (isBlack) { - modifyNumberOfBlackPawnsofColumn(columnPawn, (-1)); - } else { - modifyNumberOfWhitePawnsofColumn(columnPawn, (-1)); + final int promoType = move.getPromotionType(); + if (promoType!=0) { + + return; // There is a promotion (i.e. the pawn departed from the seventh rank if white, fomr the 2nd rank if black) so we stop here: a promotion does not change pawn structure on the chessboard } - return; // promotion. so we stop here: no chance of a pawn being captured... - + // We have to recompute all that is relevant to passed and protected passed pawns: that is the simplest solution + computePassedAndProtectedPassedPawns(); + return; } + + + + int captured = move.getCapturedType(); if (captured!=0) { - // Well the pawn with change columns...whatever it captures - int destinationColumnOfThePawn = move.getMovingDestination()%Hb2ChessConstants.NB_FILES; - if (isBlack) { - modifyNumberOfBlackPawnsofColumn(columnPawn, (-1)); - modifyNumberOfBlackPawnsofColumn(destinationColumnOfThePawn, 1); - } else { - modifyNumberOfWhitePawnsofColumn(columnPawn, (-1)); - modifyNumberOfWhitePawnsofColumn(destinationColumnOfThePawn, 1); - } - // If a piece was captured, we don't care; whereas if a pawn is captured, it'as another story... - if (Math.abs(captured)== PAWN) { - if (isBlack) { - // Black pawns are eating white pawns - modifyNumberOfWhitePawnsofColumn(destinationColumnOfThePawn, (-1)); - - } else { - // White pawns are eating black pawns - modifyNumberOfBlackPawnsofColumn(destinationColumnOfThePawn, (-1)); - - } + if (Math.abs(captured) == PAWN) { + // We have to recompute all that is relevant to passed and protected passed pawns: that is the simplest solution + computePassedAndProtectedPassedPawns(); } + } + + // We reached a point where it's for sure that the pawn structures on the chessboard are not changed by the move played + // Doing nothing is the way to go... } public int getContribDoubledPawnsMg() { diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/AnotherVeryDirtyTestPassedConnectedPawns.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/AnotherVeryDirtyTestPassedConnectedPawns.java deleted file mode 100644 index c5a2c44..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/AnotherVeryDirtyTestPassedConnectedPawns.java +++ /dev/null @@ -1,468 +0,0 @@ -package com.fathzer.jchess.chesslib.hbpg2.test; - -import static com.fathzer.chess.utils.Pieces.PAWN; - -import java.util.List; - -import com.fathzer.chess.utils.adapters.BoardExplorer; -import com.fathzer.jchess.chesslib.ChessLibBoardExplorer; -import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; -import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; -import com.github.bhlangonijr.chesslib.Bitboard; -import com.github.bhlangonijr.chesslib.Board; -import com.github.bhlangonijr.chesslib.File; -import com.github.bhlangonijr.chesslib.Piece; -import com.github.bhlangonijr.chesslib.Rank; -import com.github.bhlangonijr.chesslib.Square; - - - -public class AnotherVeryDirtyTestPassedConnectedPawns { - - public static final long h_file = 0x8080808080808080L; - public static final long g_file = h_file >>> 1; - public static final long f_file = h_file >>> 2; - public static final long e_file = h_file >>> 3; - public static final long d_file = h_file >>> 4; - public static final long c_file = h_file >>> 5; - public static final long b_file = h_file >>> 6; - public static final long a_file = h_file >>> 7; - - public static final long rank_1 = 0x00000000000000FFL; - public static final long rank_2 = rank_1 << 8; - public static final long rank_3 = rank_1 << 16; - public static final long rank_4 = rank_1 << 24; - public static final long rank_5 = rank_1 << 32; - public static final long rank_6 = rank_1 << 40; - public static final long rank_7 = rank_1 << 48; - public static final long rank_8 = rank_1 << 56; - - - public static final long not_a_file = ~a_file; - public static final long not_h_file = ~h_file; - public static final long not_rank_1 = ~rank_1; - public static final long not_rank_8 = ~rank_8; - - public static final long[] whitePassedPawnMask = new long[] { - 0x0303030303030300L, 0x0707070707070700L, 0x0e0e0e0e0e0e0e00L, 0x1c1c1c1c1c1c1c00L, - 0x3838383838383800L, 0x7070707070707000L, 0xe0e0e0e0e0e0e000L, 0xc0c0c0c0c0c0c000L, - 0x0303030303030000L, 0x0707070707070000L, 0x0e0e0e0e0e0e0000L, 0x1c1c1c1c1c1c0000L, - 0x3838383838380000L, 0x7070707070700000L, 0xe0e0e0e0e0e00000L, 0xc0c0c0c0c0c00000L, - 0x0303030303000000L, 0x0707070707000000L, 0x0e0e0e0e0e000000L, 0x1c1c1c1c1c000000L, - 0x3838383838000000L, 0x7070707070000000L, 0xe0e0e0e0e0000000L, 0xc0c0c0c0c0000000L, - 0x0303030300000000L, 0x0707070700000000L, 0x0e0e0e0e00000000L, 0x1c1c1c1c00000000L, - 0x3838383800000000L, 0x7070707000000000L, 0xe0e0e0e000000000L, 0xc0c0c0c000000000L, - 0x0303030000000000L, 0x0707070000000000L, 0x0e0e0e0000000000L, 0x1c1c1c0000000000L, - 0x3838380000000000L, 0x7070700000000000L, 0xe0e0e00000000000L, 0xc0c0c00000000000L, - 0x0303000000000000L, 0x0707000000000000L, 0x0e0e000000000000L, 0x1c1c000000000000L, - 0x3838000000000000L, 0x7070000000000000L, 0xe0e0000000000000L, 0xc0c0000000000000L, - 0x0300000000000000L, 0x0700000000000000L, 0x0e00000000000000L, 0x1c00000000000000L, - 0x3800000000000000L, 0x7000000000000000L, 0xe000000000000000L, 0xc000000000000000L, - 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, - 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L - }; - - public static final long[] blackPassedPawnMask = new long[] { - - 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, - 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, - 0x0000000000000003L, 0x0000000000000007L, 0x000000000000000eL, 0x000000000000001cL, - 0x0000000000000038L, 0x0000000000000070L, 0x00000000000000e0L, 0x00000000000000c0L, - 0x0000000000000303L, 0x0000000000000707L, 0x0000000000000e0eL, 0x0000000000001c1cL, - 0x0000000000003838L, 0x0000000000007070L, 0x000000000000e0e0L, 0x000000000000c0c0L, - 0x0000000000030303L, 0x0000000000070707L, 0x00000000000e0e0eL, 0x00000000001c1c1cL, - 0x0000000000383838L, 0x0000000000707070L, 0x0000000000e0e0e0L, 0x0000000000c0c0c0L, - 0x0000000003030303L, 0x0000000007070707L, 0x000000000e0e0e0eL, 0x000000001c1c1c1cL, - 0x0000000038383838L, 0x0000000070707070L, 0x00000000e0e0e0e0L, 0x00000000c0c0c0c0L, - 0x0000000303030303L, 0x0000000707070707L, 0x0000000e0e0e0e0eL, 0x0000001c1c1c1c1cL, - 0x0000003838383838L, 0x0000007070707070L, 0x000000e0e0e0e0e0L, 0x000000c0c0c0c0c0L, - 0x0000030303030303L, 0x0000070707070707L, 0x00000e0e0e0e0e0eL, 0x00001c1c1c1c1c1cL, - 0x0000383838383838L, 0x0000707070707070L, 0x0000e0e0e0e0e0e0L, 0x0000c0c0c0c0c0c0L, - 0x0003030303030303L, 0x0007070707070707L, 0x000e0e0e0e0e0e0eL, 0x001c1c1c1c1c1c1cL, - 0x0038383838383838L, 0x0070707070707070L, 0x00e0e0e0e0e0e0e0L, 0x00c0c0c0c0c0c0c0L, - }; - - public static final long shiftWest(long b) { - return (b >>> 1) & not_h_file; - } - - public static final long shiftEast(long b) { - return (b << 1) & not_a_file; - } - - public static final long shiftSouth(long b) { - return b >>> 8; - } - - public static final long shiftNorth(long b) { - return b << 8; - } - - public static final long shiftNorthEast(long b) { - return (b << 9) & not_a_file; - } - - public static final long shiftSouthEast(long b) { - return (b >>> 7) & not_a_file; - } - - public static final long shiftSouthWest(long b) { - return (b >>> 9) & not_h_file; - } - - public static final long shiftNorthWest(long b) { - return (b << 7) & not_h_file; - } - - - public static int getIndex(Square square) { - return (Hb2ChessConstants.INDEX_MAX_RANK-square.getRank().ordinal())*Hb2ChessConstants.NB_RANKS+square.getFile().ordinal(); - } - - static int getRgSquare (int rank, int file) { - return((Hb2ChessConstants.NB_RANKS*rank)+file); - } - - static ChessLibMoveGenerator fromFEN(String fen) { - final Board board = new Board(); - board.loadFromFen(fen); - return new ChessLibMoveGenerator(board); - } - - - public static void printLstSquare(List lstSq) { - for (Square sq : lstSq) { - System.out.print(sq.value()); - System.out.print(" "); - } - System.out.println(); - } - - static void newPrintDetailsAboutPawn(Square pawnSq, boolean isBlack,Board board) { - -// /// STALINE -// if (pawnSq.name().equalsIgnoreCase("H3") == false) { -// return; -// } -// long toto = pawnSq.ordinal(); -// List lstSquaretoto = Bitboard.bbToSquareList(toto); -// printLstSquare(lstSquaretoto); -// toto = (1L << pawnSq.ordinal()); -// lstSquaretoto = Bitboard.bbToSquareList(toto); -// printLstSquare(lstSquaretoto); - - long bitBoardWhitePawns = board.getBitboard(Piece.WHITE_PAWN); - long connectedPawnsEastWhite = shiftNorthEast(bitBoardWhitePawns) & bitBoardWhitePawns; - long connectedPawnsWestWhite = shiftNorthWest(bitBoardWhitePawns) & bitBoardWhitePawns; - - List lstSquare = Bitboard.bbToSquareList(connectedPawnsEastWhite); - printLstSquare(lstSquare); - lstSquare = Bitboard.bbToSquareList(connectedPawnsWestWhite); - printLstSquare(lstSquare); - - long bitBoardBlackPawns = board.getBitboard(Piece.BLACK_PAWN); - long connectedPawnsEastBlack = shiftSouthEast(bitBoardBlackPawns) & bitBoardBlackPawns; - long connectedPawnsWestBlack = shiftSouthWest(bitBoardBlackPawns) & bitBoardBlackPawns; - List lstSquareBP = Bitboard.bbToSquareList(connectedPawnsEastBlack); - printLstSquare(lstSquareBP); - lstSquare = Bitboard.bbToSquareList(connectedPawnsWestBlack); - printLstSquare(lstSquare); - - - System.out.println(); - System.out.println(); - System.out.println("####################"); - if (isBlack) { - System.out.println("BLACK PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); - } else { - System.out.println("WHITE PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); - } - int indexCazz = getIndex(pawnSq); - System.out.println("Index JMA case "+ pawnSq.value()+":"+ indexCazz); - Square[] tabAdjSquares = pawnSq.getSideSquares(); - System.out.println("Cases adjacentes de la case "+ pawnSq.value()+":"); - for (int i = 0; i < tabAdjSquares.length; i++) { - System.out.println(tabAdjSquares[i].value()); - - } - - - int columnPawn = indexCazz%Hb2ChessConstants.NB_FILES; - int rankPawn =Hb2ChessConstants.INDEX_MAX_RANK-pawnSq.getRank().ordinal(); - System.out.println("rankPawn_JMA:"+ rankPawn); - System.out.println("columnPawn_JMA:"+ columnPawn); - -// if (isBlack ) { -// if ( pawnSq.getRank() == Rank.RANK_2) { -// // A black pawn on the 2nd rank is a passer, by nature -// System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); -// System.out.println("####################"); -// System.out.println(); -// System.out.println(); -// return; -// } -// -// } else { -// if ( pawnSq.getRank() == Rank.RANK_7) { -// // A white pawn on the 7th rank is a passer, by nature -// System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); -// System.out.println("####################"); -// System.out.println(); -// System.out.println(); -// return; -// } -// } -// - - - Piece enemyPawn = (isBlack?Piece.WHITE_PAWN:Piece.BLACK_PAWN); - long bitboardEnemyPawns = board.getBitboard(enemyPawn); -// if (bitboardEnemyPawns == 0L) { -// System.out.println("THE "+ (isBlack?"BLACK ":"WHITE ") + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); -// } - long testPassedPawn = 0L; - if (!isBlack) { - testPassedPawn = whitePassedPawnMask[pawnSq.ordinal()] & bitboardEnemyPawns; - } else { - testPassedPawn = blackPassedPawnMask[pawnSq.ordinal()] & bitboardEnemyPawns; - } - if (testPassedPawn == 0L) { - if (!isBlack) { - - System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); - - } else { - System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); - } - - } - - -// long bitBoardWhitePawns = board.getBitboard(Piece.WHITE_PAWN); -// long connectedPawnsEastWhite = shiftNorthEast(bitBoardWhitePawns) & bitBoardWhitePawns; -// long connectedPawnsWestWhite = shiftNorthWest(bitBoardWhitePawns) & bitBoardWhitePawns; -// -// long bitBoardBlackPawns = board.getBitboard(Piece.BLACK_PAWN); -// long connectedPawnsEastBlack = shiftSouthEast(bitBoardBlackPawns) & bitBoardBlackPawns; -// long connectedPawnsWestBlack = shiftSouthWest(bitBoardBlackPawns) & bitBoardBlackPawns; - if (!isBlack) { - - boolean connectedWhitePawn = ( (1L << pawnSq.ordinal()) & (connectedPawnsEastWhite | connectedPawnsWestWhite)) != 0; - if (connectedWhitePawn) { - System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A CONNECTED PAWN!"); - } - - } else { - boolean connectedBlackPawn = ((1L << pawnSq.ordinal()) & (connectedPawnsEastBlack | connectedPawnsWestBlack)) != 0; - if (connectedBlackPawn) { - System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A CONNECTED PAWN!"); - } - - } - - - -// if (!isBlack) { -// -// // Bon, on part de la rangée devant le pion blanc et on va jusqu'à la 7ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) -// // On regarde s'il y a un pion noir ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions noirs, alors -// // le pion blanc est passé -// int rankDebut = pawnSq.getRank().ordinal()+1; -// int rankFin = Rank.RANK_7.ordinal(); -// int fileDebut = pawnSq.getFile().ordinal(); -// int fileFin = pawnSq.getFile().ordinal(); -// if (columnPawn == 0) { -// fileFin = File.FILE_B.ordinal(); -// } else if (columnPawn == 7) { -// fileDebut = File.FILE_G.ordinal(); -// } else { -// fileDebut = pawnSq.getFile().ordinal() - 1; -// fileFin = pawnSq.getFile().ordinal() +1; -// } -// //getRgSquare -// -//// int rgDebutSq = (Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut; -//// int rgFinSq = (Hb2ChessConstants.NB_RANKS*rankFin)+fileFin; -// boolean areEnemyPawnInZone = false; -// for (int rankk = rankDebut; rankk <= rankFin; rankk++) { -// int rgSqDebutRank = getRgSquare(rankk, fileDebut); -// int rgSqFintRank = getRgSquare(rankk, fileFin); -// long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); -// if (pionsAdversesDansZoneForRank != 0L) { -// areEnemyPawnInZone = true; -// break; -// } -// -// } -// -//// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); -//// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); -//// long ALL_BITS_EQUAL_ONE_BITBOARD = 0xFFFFFFFFFFFFFFFFL; -//// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, sqDebut.ordinal(), sqFin.ordinal()); -////// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, rgDebutSq, rgFinSq); -//// List lstKazz = Bitboard.bbToSquareList(pionsAdversesDansZone); -//// for (Square kaaaaz : lstKazz) { -//// System.out.println(kaaaaz.value()); -//// } -// if (areEnemyPawnInZone == false) { -// System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); -// } -// -// -// -// -// } else { -// -// // Bon, on part de la rangée devant le pion noir (du point de vue noir) et on va jusqu'à la 2ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) -// // On regarde s'il y a un pion blanc ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions blancs, alors -// // le pion noir est passé -// int rankDebut = Rank.RANK_2.ordinal(); -// int rankFin = pawnSq.getRank().ordinal()-1; -// int fileDebut = pawnSq.getFile().ordinal(); -// int fileFin = pawnSq.getFile().ordinal(); -// if (columnPawn == 0) { -// fileFin = File.FILE_B.ordinal(); -// } else if (columnPawn == 7) { -// fileDebut = File.FILE_G.ordinal(); -// } else { -// fileDebut = pawnSq.getFile().ordinal() - 1; -// fileFin = pawnSq.getFile().ordinal() +1; -// } -// -//// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); -//// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); -// -// boolean areEnemyPawnInZone = false; -// for (int rankk = rankDebut; rankk <= rankFin; rankk++) { -// int rgSqDebutRank = getRgSquare(rankk, fileDebut); -// int rgSqFintRank = getRgSquare(rankk, fileFin); -// long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); -// if (pionsAdversesDansZoneForRank != 0L) { -// areEnemyPawnInZone = true; -// break; -// } -// -// } -// -// -// if (areEnemyPawnInZone == false) { -// System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); -// } -// -// -// } - - System.out.println("####################"); - System.out.println(); - System.out.println(); - - } - - static void newDeallWithSquareOccupiedByPawn(Square pawnSq, boolean isBlack, Board board) { - - newPrintDetailsAboutPawn(pawnSq, isBlack, board); - - } - - - - static void testFen1() { - - - testFen("6k1/8/1Pp5/8/8/3P4/1K6/8 w - - 0 1"); - - - } - - - - static void testFen2() { -// testFen("6k1/8/1Pp5/8/8/3P3p/1K2Pp2/8 w - - 0 1"); - testFen("6k1/8/1Pp5/8/6p1/3P3p/1K2Pp2/8 w - - 0 1"); - - - - } - static void testFen3() { - testFen("6k1/8/1Pp5/8/8/7p/1K1PPp2/8 w - - 0 1"); - - - } - - - static void testFen(String fen) { - -// long bbBlackPawnsOccupancy = 0L; -// long bbWhitePawnsOccupancy = 0L; - System.out.println(); - System.out.println("FEN en test pour les pions passés:" + fen); - Board internal = new Board(); - internal.loadFromFen(fen); - ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(internal); - - System.out.println(internal.toStringFromWhiteViewPoint()); - -// BoardExplorer explorer0 = new ChessLibBoardExplorer(mvg.getBoard()); -// do { -// final int p = explorer0.getPiece(); -// -// final int kind = Math.abs(p); -// final int index = explorer0.getIndex(); -// final boolean isBlack = p<0; -// if (kind == PAWN) { -// int row = Hb2ChessConstants.INDEX_MAX_RANK - index/Hb2ChessConstants.NB_RANKS; -// int col = index%Hb2ChessConstants.NB_FILES; -// Square sqp = Square.squareAt((Hb2ChessConstants.NB_RANKS*row)+col); -// long bbPawn = Bitboard.getBbtable(sqp); -// if (isBlack) { -// bbBlackPawnsOccupancy = bbBlackPawnsOccupancy | bbPawn; -// } else { -// bbWhitePawnsOccupancy = bbWhitePawnsOccupancy | bbPawn; -// } -// -// -// } -// -// } while (explorer0.next()); -// -// List lstSquareWhitePawns = Bitboard.bbToSquareList(bbWhitePawnsOccupancy); -// BitboardTries.printLstSquare(lstSquareWhitePawns); -// -// List lstSquareBlackPawns = Bitboard.bbToSquareList(bbBlackPawnsOccupancy); -// BitboardTries.printLstSquare(lstSquareBlackPawns); - - - BoardExplorer explorer = new ChessLibBoardExplorer(mvg.getBoard()); - do { - final int p = explorer.getPiece(); - - final int kind = Math.abs(p); - final int index = explorer.getIndex(); - final boolean isBlack = p<0; - if (kind == PAWN) { - int row = Hb2ChessConstants.INDEX_MAX_RANK - index/Hb2ChessConstants.NB_RANKS; - int col = index%Hb2ChessConstants.NB_FILES; - Square sqp = Square.squareAt((Hb2ChessConstants.NB_RANKS*row)+col); - - newDeallWithSquareOccupiedByPawn(sqp, isBlack, mvg.getBoard()); - - } - - } while (explorer.next()); - - System.out.println(); - System.out.println(); - System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - System.out.println(); - System.out.println(); - - } - - public static void main(String[] args) { -// testFen1(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen1.gif - testFen2(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen2.gif -// testFen3(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen3.gif - } - - -} diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/BitboardTries.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/BitboardTries.java deleted file mode 100644 index 5999e12..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/BitboardTries.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fathzer.jchess.chesslib.hbpg2.test; - -import java.util.List; - -import com.github.bhlangonijr.chesslib.Bitboard; -import com.github.bhlangonijr.chesslib.Square; - -public class BitboardTries { - - public static void printLongAsBinary(long l) { - for(int i = 0; i < Long.numberOfLeadingZeros((long)l); i++) { - System.out.print('0'); - } - System.out.println(Long.toBinaryString((long)l)); - } - - public static void printLstSquare(List lstSq) { - for (Square sq : lstSq) { - System.out.print(sq.value()); - System.out.print(" "); - } - System.out.println(); - } - - - public static void main(String[] args) { - // TODO Auto-generated method stub - List lstSquare = Bitboard.bbToSquareList(256L); - printLstSquare(lstSquare); - List lstSquare2 = Bitboard.bbToSquareList(1L); - printLstSquare(lstSquare2); - List lstSquare3 = Bitboard.bbToSquareList(1099511627776L); - printLstSquare(lstSquare3); - List lstSquare4 = Bitboard.bbToSquareList(512L); - printLstSquare(lstSquare4); - - } - -} diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java deleted file mode 100644 index 66adf32..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/VeryDirtyTestPasserPawns.java +++ /dev/null @@ -1,263 +0,0 @@ -package com.fathzer.jchess.chesslib.hbpg2.test; - -import static com.fathzer.chess.utils.Pieces.PAWN; - -import java.util.List; - -import com.fathzer.chess.utils.adapters.BoardExplorer; -import com.fathzer.jchess.chesslib.ChessLibBoardExplorer; -import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; -import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2ChessConstants; -import com.github.bhlangonijr.chesslib.Bitboard; -import com.github.bhlangonijr.chesslib.Board; -import com.github.bhlangonijr.chesslib.File; -import com.github.bhlangonijr.chesslib.Piece; -import com.github.bhlangonijr.chesslib.Rank; -import com.github.bhlangonijr.chesslib.Square; - -public class VeryDirtyTestPasserPawns { - - public static int getIndex(Square square) { - return (Hb2ChessConstants.INDEX_MAX_RANK-square.getRank().ordinal())*Hb2ChessConstants.NB_RANKS+square.getFile().ordinal(); - } - - static int getRgSquare (int rank, int file) { - return((Hb2ChessConstants.NB_RANKS*rank)+file); - } - - static ChessLibMoveGenerator fromFEN(String fen) { - final Board board = new Board(); - board.loadFromFen(fen); - return new ChessLibMoveGenerator(board); - } - - static void printDetailsAboutPawn(Square pawnSq, boolean isBlack,Board board) { - -// /// STALINE -// if (pawnSq.name().equalsIgnoreCase("E2") == false) { -// return; -// } - - System.out.println(); - System.out.println(); - System.out.println("####################"); - if (isBlack) { - System.out.println("BLACK PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); - } else { - System.out.println("WHITE PAWN DETECTED ON THE "+ pawnSq.name()+" SQUARE"); - } - int indexCazz = getIndex(pawnSq); - System.out.println("Index JMA case "+ pawnSq.value()+":"+ indexCazz); - Square[] tabAdjSquares = pawnSq.getSideSquares(); - System.out.println("Cases adjacentes de la case "+ pawnSq.value()+":"); - for (int i = 0; i < tabAdjSquares.length; i++) { - System.out.println(tabAdjSquares[i].value()); - - } - - - int columnPawn = indexCazz%Hb2ChessConstants.NB_FILES; - int rankPawn =Hb2ChessConstants.INDEX_MAX_RANK-pawnSq.getRank().ordinal(); - System.out.println("rankPawn_JMA:"+ rankPawn); - System.out.println("columnPawn_JMA:"+ columnPawn); - - if (isBlack ) { - if ( pawnSq.getRank() == Rank.RANK_2) { - // A black pawn on the 2nd rank is a passer, by nature - System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); - System.out.println("####################"); - System.out.println(); - System.out.println(); - return; - } - - } else { - if ( pawnSq.getRank() == Rank.RANK_7) { - // A white pawn on the 7th rank is a passer, by nature - System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); - System.out.println("####################"); - System.out.println(); - System.out.println(); - return; - } - } - - - - Piece enemyPawn = (isBlack?Piece.WHITE_PAWN:Piece.BLACK_PAWN); - long bitboardEnemyPawns = board.getBitboard(enemyPawn); - if (bitboardEnemyPawns == 0L) { - System.out.println("THE "+ (isBlack?"BLACK ":"WHITE ") + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); - } - - - if (!isBlack) { - - // Bon, on part de la rangée devant le pion blanc et on va jusqu'à la 7ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) - // On regarde s'il y a un pion noir ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions noirs, alors - // le pion blanc est passé - int rankDebut = pawnSq.getRank().ordinal()+1; - int rankFin = Rank.RANK_7.ordinal(); - int fileDebut = pawnSq.getFile().ordinal(); - int fileFin = pawnSq.getFile().ordinal(); - if (columnPawn == 0) { - fileFin = File.FILE_B.ordinal(); - } else if (columnPawn == 7) { - fileDebut = File.FILE_G.ordinal(); - } else { - fileDebut = pawnSq.getFile().ordinal() - 1; - fileFin = pawnSq.getFile().ordinal() +1; - } - //getRgSquare - -// int rgDebutSq = (Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut; -// int rgFinSq = (Hb2ChessConstants.NB_RANKS*rankFin)+fileFin; - boolean areEnemyPawnInZone = false; - for (int rankk = rankDebut; rankk <= rankFin; rankk++) { - int rgSqDebutRank = getRgSquare(rankk, fileDebut); - int rgSqFintRank = getRgSquare(rankk, fileFin); - long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); - if (pionsAdversesDansZoneForRank != 0L) { - areEnemyPawnInZone = true; - break; - } - - } - -// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); -// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); -// long ALL_BITS_EQUAL_ONE_BITBOARD = 0xFFFFFFFFFFFFFFFFL; -// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, sqDebut.ordinal(), sqFin.ordinal()); -//// long pionsAdversesDansZone = Bitboard.bitsBetween(ALL_BITS_EQUAL_ONE_BITBOARD, rgDebutSq, rgFinSq); -// List lstKazz = Bitboard.bbToSquareList(pionsAdversesDansZone); -// for (Square kaaaaz : lstKazz) { -// System.out.println(kaaaaz.value()); -// } - if (areEnemyPawnInZone == false) { - System.out.println("THE WHITE " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); - } - - - - - } else { - - // Bon, on part de la rangée devant le pion noir (du point de vue noir) et on va jusqu'à la 2ème rangée, pour la colonne du pion et ses colonnes adjacentes (au max 2) - // On regarde s'il y a un pion blanc ennemi dans cette zone. Si c'est le cas, alors le pion n'est pas passé. Si cette zone est vide de pions blancs, alors - // le pion noir est passé - int rankDebut = Rank.RANK_2.ordinal(); - int rankFin = pawnSq.getRank().ordinal()-1; - int fileDebut = pawnSq.getFile().ordinal(); - int fileFin = pawnSq.getFile().ordinal(); - if (columnPawn == 0) { - fileFin = File.FILE_B.ordinal(); - } else if (columnPawn == 7) { - fileDebut = File.FILE_G.ordinal(); - } else { - fileDebut = pawnSq.getFile().ordinal() - 1; - fileFin = pawnSq.getFile().ordinal() +1; - } - -// Square sqDebut = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankDebut)+fileDebut); -// Square sqFin = Square.squareAt((Hb2ChessConstants.NB_RANKS*rankFin)+fileFin); - - boolean areEnemyPawnInZone = false; - for (int rankk = rankDebut; rankk <= rankFin; rankk++) { - int rgSqDebutRank = getRgSquare(rankk, fileDebut); - int rgSqFintRank = getRgSquare(rankk, fileFin); - long pionsAdversesDansZoneForRank = Bitboard.bitsBetween(bitboardEnemyPawns, rgSqDebutRank, rgSqFintRank); - if (pionsAdversesDansZoneForRank != 0L) { - areEnemyPawnInZone = true; - break; - } - - } - - - if (areEnemyPawnInZone == false) { - System.out.println("THE BLACK " + pawnSq.name()+ " PAWN IS A PASSED PAWN!"); - } - - - } - - System.out.println("####################"); - System.out.println(); - System.out.println(); - - } - - static void deallWithSquareOccupiedByPawn(Square pawnSq, boolean isBlack, Board board) { - - printDetailsAboutPawn(pawnSq, isBlack, board); - - } - - - - static void testFen1() { - - - testFen("6k1/8/1Pp5/8/8/3P4/1K6/8 w - - 0 1"); - - - } - - - - static void testFen2() { - testFen("6k1/8/1Pp5/8/8/3P3p/1K2Pp2/8 w - - 0 1"); - - - } - static void testFen3() { - testFen("6k1/8/1Pp5/8/8/7p/1K1PPp2/8 w - - 0 1"); - - - } - - - static void testFen(String fen) { - - System.out.println(); - System.out.println("FEN en test pour les pions passés:" + fen); - Board internal = new Board(); - internal.loadFromFen(fen); - ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(internal); - - System.out.println(internal.toStringFromWhiteViewPoint()); - - BoardExplorer explorer = new ChessLibBoardExplorer(mvg.getBoard()); - do { - final int p = explorer.getPiece(); - - final int kind = Math.abs(p); - final int index = explorer.getIndex(); - final boolean isBlack = p<0; - if (kind == PAWN) { - int row = Hb2ChessConstants.INDEX_MAX_RANK - index/Hb2ChessConstants.NB_RANKS; - int col = index%Hb2ChessConstants.NB_FILES; - Square sqp = Square.squareAt((Hb2ChessConstants.NB_RANKS*row)+col); - - deallWithSquareOccupiedByPawn(sqp, isBlack, mvg.getBoard()); - - } - - } while (explorer.next()); - - System.out.println(); - System.out.println(); - System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - System.out.println(); - System.out.println(); - - } - - public static void main(String[] args) { -// testFen1(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen1.gif - testFen2(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen2.gif -// testFen3(); // cf /Volumes/PORSCHE/ECHECS_DVT/PROG_JMA/PIONS_PASSES/fen3.gif - } - - -} diff --git a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/package-info.java b/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/package-info.java deleted file mode 100644 index 6881f27..0000000 --- a/src/main/java/com/fathzer/jchess/chesslib/hbpg2/test/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * - */ -/** - * - */ -package com.fathzer.jchess.chesslib.hbpg2.test; \ No newline at end of file diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java index c651f4a..3fd6081 100644 --- a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTest.java @@ -15,16 +15,17 @@ class HBThreeMovesTest { @Test void test() { - final int depth = 6; - final int bestMoveCount = 3; - final String fen = "5k2/p1p2ppp/4b3/1p2p1P1/1P2P3/3P1B2/Pb2NPKP/8 w - - 0 1"; + final int depth = 1; + final int bestMoveCount = 10; +// final String fen = "5k2/p1p2ppp/4b3/1p2p1P1/1P2P3/3P1B2/Pb2NPKP/8 w - - 0 1"; // final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final String fen = "8/3k3p/2R5/3PP3/8/1p2K3/7r/8 w - - 0 1"; final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(SimplifiedEvaluator::new, depth); engine.getDeepeningPolicy().setSize(bestMoveCount); final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)).getBestMoves(); System.out.println(moves); - for (int i=0;i<3;i++) { + for (int i=0;i<10;i++) { EvaluatedMove move = moves.get(i); List principalVariation = move.getPrincipalVariation(); System.out.println(move+" -> "+principalVariation); diff --git a/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTestPassedPawns.java b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTestPassedPawns.java new file mode 100644 index 0000000..094ee57 --- /dev/null +++ b/src/test/java/com/fathzer/jchess/chesslib/ai/HBThreeMovesTestPassedPawns.java @@ -0,0 +1,40 @@ +package com.fathzer.jchess.chesslib.ai; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fathzer.games.ai.evaluation.EvaluatedMove; +import com.fathzer.games.ai.iterativedeepening.IterativeDeepeningEngine; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluator; +import com.fathzer.jchess.chesslib.uci.ChessLibEngine; +import com.github.bhlangonijr.chesslib.move.Move; + +class HBThreeMovesTestPassedPawns { + + @Test + void test() { + final int depth = 1; + final int bestMoveCount = 10; +// final String fen = "8/3k3p/2R5/3P4/1p2P3/4K3/7r/8 w - - 0 1"; + final String fen = "8/3k3p/2R5/3PP3/8/1p2K3/7r/8 w - - 0 1"; + +// final String fen = "r2k1r2/pp1b2pp/1b2Pn2/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; // pas de pions doublés +// final String fen = "5k2/p1p2ppp/4b3/4p1P1/1P2P3/p2P1B2/1b2NP1P/6K1 w - - 0 1"; + + +// final String fen = "r2k1r2/pp1b2p1/1b2Pnp1/2p5/Q1B2Bq1/2P5/P5PP/3R1RK1 w - - 0 1"; + final IterativeDeepeningEngine engine = ChessLibEngine.buildEngine(Hb2SimplifiedEvaluator::new, depth); + engine.getDeepeningPolicy().setSize(bestMoveCount); + engine.getDeepeningPolicy().setDeepenOnForced(true); + final List> moves = engine.getBestMoves(MinimaxEngineTest.fromFEN(fen, BasicMoveComparator::new)).getBestMoves(); + System.out.println(moves); + for (EvaluatedMove move : moves) { +// EvaluatedMove move = moves.get(i); + List principalVariation = move.getPrincipalVariation(); + System.out.println(move+" -> "+principalVariation); + } + } + +} From 701bde478a489925c84d5f9f39c7e7219ed61d44 Mon Sep 17 00:00:00 2001 From: herve Date: Thu, 21 Nov 2024 12:08:40 +0100 Subject: [PATCH 49/55] git_ignore updated --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5d665db..262aa49 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target/ /.settings/ /dependency-reduced-pom.xml +/.DS_Store From 32d72bec1c39725fe8b236c8a82da23a710bbe51 Mon Sep 17 00:00:00 2001 From: herve Date: Fri, 22 Nov 2024 09:17:12 +0100 Subject: [PATCH 50/55] cleaning, among others --- .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 7 ++++--- .../ai/eval/hbpg2/Hb2MyFirstEvaluator.java | 19 +++++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index 123a9cf..0ffd23e 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -52,9 +52,10 @@ int evaluateAsWhite() { int phase= (computedPhase > Hb2Phase.PHASE_UPPER_BOUND?Hb2Phase.PHASE_UPPER_BOUND:computedPhase); // int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); // int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); - - int evalMg = pointsMg + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex) + chessEvalAdditionalElems.getContribMg(); - int evalEg = pointsEg + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex) + chessEvalAdditionalElems.getContribEg(); + int posKingMg = Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); + int posKingEg = Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); + int evalMg = pointsMg + pointsPosMg + posKingMg + chessEvalAdditionalElems.getContribMg(); + int evalEg = pointsEg + pointsPosEg+ posKingEg + chessEvalAdditionalElems.getContribEg(); return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java index e92c014..d052a04 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2MyFirstEvaluator.java @@ -3,14 +3,13 @@ import com.fathzer.games.ai.evaluation.StaticEvaluator; import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; -import com.fathzer.jchess.chesslib.ai.eval.NaiveEvaluator; import com.github.bhlangonijr.chesslib.Board; import com.github.bhlangonijr.chesslib.move.Move; public class Hb2MyFirstEvaluator implements StaticEvaluator, ZeroSumEvaluator { private final Hb2SimplifiedEvaluator ev = new Hb2SimplifiedEvaluator(); - private final NaiveEvaluator enNaive = new NaiveEvaluator(); +// private final NaiveEvaluator enNaive = new NaiveEvaluator(); @Override public int evaluateAsWhite(ChessLibMoveGenerator board) { // Calculer l'évaluation de base @@ -30,6 +29,22 @@ public StaticEvaluator fork() { return new Hb2MyFirstEvaluator(); } + public static void evaluatePositionAsWhite(String fen) { + // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer + ChessLibMoveGenerator mvg = new ChessLibMoveGenerator(new Board()); +// mvg.getBoard().loadFromFen("8/3b3p/p3P1p1/3K4/5P1P/2k5/8/8 b - - 0 56"); +// mvg.getBoard().loadFromFen("5k2/p1p2pp1/4b1p1/4p3/1P2P3/p2P1B2/1b2NP1P/6K1 w - - 0 1"); +// System.out.println(new Hb2MyFirstEvaluator().evaluate(mvg)); +// mvg.getBoard().loadFromFen("8/p1p1kppp/4b3/4p1P1/1P2P2P/p2P1B2/1b2NP2/6K1 w - - 0 1"); + + + + + + + mvg.getBoard().loadFromFen(fen); + System.out.println(new Hb2MyFirstEvaluator().evaluate(mvg)); + } public static void main(String[] args) { // Exemple pour créer un ChessLibMoveGenerator à partir d'un FEN et l'évaluer From f71970cc8a5fd673d241cb6e437878be283011e4 Mon Sep 17 00:00:00 2001 From: herve Date: Mon, 25 Nov 2024 07:13:51 +0100 Subject: [PATCH 51/55] Dynamic Evaluator bug fixed (it was visible in the Passed Pawns's evaluation) --- ...bstractIncrementalSimplifiedEvaluator.java | 18 ++++++++++- .../ai/eval/hbpg2/Hb2IncrementalState.java | 17 ++++++---- .../eval/hbpg2/additional/PawnsStrucEval.java | 32 +++++++++---------- 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java index af83f9e..883775b 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java @@ -4,10 +4,14 @@ import com.fathzer.chess.utils.adapters.MoveData; import com.fathzer.games.MoveGenerator; +import com.fathzer.games.MoveGenerator.MoveConfidence; import com.fathzer.games.ai.evaluation.Evaluator; import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; import com.fathzer.games.util.Stack; import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; +import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.Square; +import com.github.bhlangonijr.chesslib.move.Move; /** An incremental implementation of the simplified evaluator described at https://www.chessprogramming.org/Simplified_Evaluation_Function *
This only works with 8*8 games and exactly one king per Color. @@ -57,7 +61,19 @@ public void init(B board) { public void prepareMove(B board, M move) { if (moveData.update(move, board)) { buildToCommit(); - toCommit.update(moveData, ((ChessLibMoveGenerator)board).getBoard()); // STALINE + ChessLibMoveGenerator lChessLibMoveGenerator = (ChessLibMoveGenerator)board; + Board boardBeforeMove = lChessLibMoveGenerator.getBoard(); + Board bordAfterMove = boardBeforeMove.clone(); + Move lMove = (Move)move; + bordAfterMove.doMove(lMove, true); + + if (moveData.getMovingIndex() == 28) { + toCommit.update(moveData, bordAfterMove); // STALINE +// toCommit.update(moveData, ((ChessLibMoveGenerator)board).getBoard()); // STALINE + return; + } + toCommit.update(moveData, bordAfterMove); // STALINE +// toCommit.update(moveData, ((ChessLibMoveGenerator)board).getBoard()); // STALINE // toCommit.update(moveData); } } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index a3d6718..7cdea57 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -8,7 +8,9 @@ import com.fathzer.chess.utils.Pieces; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; +import com.fathzer.games.MoveGenerator.MoveConfidence; import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.move.Move; /** The current state of a {@link Hb2AbstractIncrementalSimplifiedEvaluator} */ @@ -33,13 +35,14 @@ public class Hb2IncrementalState extends Hb2BasicState { // } - void update(MoveData move, Board board) { - pointsMg += getIncrementMg(move); - pointsEg += getIncrementEg(move); - pointsPosMg += getIncrementPosMg(move); - pointsPosEg += getIncrementPosEg(move); - chessEvalAdditionalElems.updateEvalAdditionalElems(move, board); - updatePhase(move); + void update(MoveData moveData, Board board) { + + pointsMg += getIncrementMg(moveData); + pointsEg += getIncrementEg(moveData); + pointsPosMg += getIncrementPosMg(moveData); + pointsPosEg += getIncrementPosEg(moveData); + chessEvalAdditionalElems.updateEvalAdditionalElems(moveData, board); + updatePhase(moveData); } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index d63f1ec..b6f7544 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -52,7 +52,7 @@ public class PawnsStrucEval { PASSED_PAWN_BONUS_EG,PASSED_PAWN_BONUS_6_TH_RANK_EG,PASSED_PAWN_BONUS_7_TH_RANK_EG, 0}; - private Board board; + private int[] tabNbWhitePawnsByCol; private int[] tabNbBlackPawnsByCol; @@ -64,16 +64,16 @@ public class PawnsStrucEval { public PawnsStrucEval() { tabNbWhitePawnsByCol = new int[Hb2ChessConstants.NB_FILES]; tabNbBlackPawnsByCol = new int[Hb2ChessConstants.NB_FILES]; + bonusWhitePassedPawnsMg = 0; bonusWhitePassedPawnsEg = 0; bonusBlackPassedPawnsMg = 0; - bonusBlackPassedPawnsMg = 0; bonusBlackPassedPawnsEg = 0; } public PawnsStrucEval(PawnsStrucEval pse) { - this.board = pse.board; + // Since it's an array of integers, the copy is not a shallow copy tabNbWhitePawnsByCol = Arrays.copyOf(pse.tabNbWhitePawnsByCol, Hb2ChessConstants.NB_FILES); // Since it's an array of integers, the copy is not a shallow copy @@ -88,9 +88,9 @@ public PawnsStrucEval(PawnsStrucEval pse) { - private void computeDoubledPawns() { + private void computeDoubledPawns(Board board) { - BoardExplorer explorer = new ChessLibBoardExplorer(this.board); + BoardExplorer explorer = new ChessLibBoardExplorer(board); for (int i= 0; i < Hb2ChessConstants.NB_FILES; i++) { @@ -122,13 +122,13 @@ private void computeDoubledPawns() { } - private void computePassedAndProtectedPassedPawns() { + private void computePassedAndProtectedPassedPawns(Board board) { - BoardExplorer explorer = new ChessLibBoardExplorer(this.board); + BoardExplorer explorer = new ChessLibBoardExplorer(board); + bonusWhitePassedPawnsMg = 0; bonusWhitePassedPawnsEg = 0; bonusBlackPassedPawnsMg = 0; - bonusBlackPassedPawnsMg = 0; bonusBlackPassedPawnsEg = 0; long bitboardWhitePawns = board.getBitboard(Piece.WHITE_PAWN); @@ -193,9 +193,9 @@ private void computePassedAndProtectedPassedPawns() { public PawnsStrucEval( Board board) { this(); - this.board = board; - computeDoubledPawns( ); - computePassedAndProtectedPassedPawns( ); + + computeDoubledPawns( board); + computePassedAndProtectedPassedPawns( board); @@ -346,7 +346,7 @@ public static boolean isPawnProtectedModernWay(int rowPawn, int colPawn , boolea void copyTo(PawnsStrucEval other) { - other.board = board; + other.tabNbBlackPawnsByCol = tabNbBlackPawnsByCol.clone(); // not a shallow copy!!!! For integers are of primitive type... other.tabNbWhitePawnsByCol = tabNbWhitePawnsByCol.clone(); // not a shallow copy!!!! } @@ -360,7 +360,7 @@ public void modifyNumberOfWhitePawnsofColumn(int column, int nbPawns ) { } public void updatePawnsStructEval(MoveData move, Board board) { updateDoubledPawns(move); - updatePassedAndProtectePassedPawns(move); + updatePassedAndProtectePassedPawns(move, board); } @@ -415,7 +415,7 @@ private void updateDoubledPawns(MoveData move) { } - private void updatePassedAndProtectePassedPawns(MoveData move) { + private void updatePassedAndProtectePassedPawns(MoveData move, Board board) { boolean isBlack = (move.getMovingPiece()<0?true:false); int kind = Math.abs(move.getMovingPiece()); if (kind == PAWN) { @@ -426,7 +426,7 @@ private void updatePassedAndProtectePassedPawns(MoveData move) { return; // There is a promotion (i.e. the pawn departed from the seventh rank if white, fomr the 2nd rank if black) so we stop here: a promotion does not change pawn structure on the chessboard } // We have to recompute all that is relevant to passed and protected passed pawns: that is the simplest solution - computePassedAndProtectedPassedPawns(); + computePassedAndProtectedPassedPawns(board); return; } @@ -438,7 +438,7 @@ private void updatePassedAndProtectePassedPawns(MoveData move) { if (captured!=0) { if (Math.abs(captured) == PAWN) { // We have to recompute all that is relevant to passed and protected passed pawns: that is the simplest solution - computePassedAndProtectedPassedPawns(); + computePassedAndProtectedPassedPawns(board); } From 543b8fc5422925e6f0c2f9b090441b126bdd5d7e Mon Sep 17 00:00:00 2001 From: herve Date: Mon, 25 Nov 2024 08:17:34 +0100 Subject: [PATCH 52/55] cleaning --- ...bstractIncrementalSimplifiedEvaluator.java | 13 +--- .../chesslib/ai/eval/hbpg2/Hb2BasicState.java | 1 - .../ai/eval/hbpg2/Hb2BitboardsUtils.java | 67 ++++++++++--------- .../ai/eval/hbpg2/Hb2IncrementalState.java | 4 +- .../eval/hbpg2/additional/PawnsStrucEval.java | 6 +- 5 files changed, 41 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java index 883775b..805ff4c 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java @@ -4,13 +4,11 @@ import com.fathzer.chess.utils.adapters.MoveData; import com.fathzer.games.MoveGenerator; -import com.fathzer.games.MoveGenerator.MoveConfidence; import com.fathzer.games.ai.evaluation.Evaluator; import com.fathzer.games.ai.evaluation.ZeroSumEvaluator; import com.fathzer.games.util.Stack; import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; import com.github.bhlangonijr.chesslib.Board; -import com.github.bhlangonijr.chesslib.Square; import com.github.bhlangonijr.chesslib.move.Move; /** An incremental implementation of the simplified evaluator described at https://www.chessprogramming.org/Simplified_Evaluation_Function @@ -67,14 +65,9 @@ public void prepareMove(B board, M move) { Move lMove = (Move)move; bordAfterMove.doMove(lMove, true); - if (moveData.getMovingIndex() == 28) { - toCommit.update(moveData, bordAfterMove); // STALINE -// toCommit.update(moveData, ((ChessLibMoveGenerator)board).getBoard()); // STALINE - return; - } - toCommit.update(moveData, bordAfterMove); // STALINE -// toCommit.update(moveData, ((ChessLibMoveGenerator)board).getBoard()); // STALINE -// toCommit.update(moveData); + + toCommit.update(moveData, bordAfterMove); + } } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java index 0ffd23e..108ba63 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BasicState.java @@ -3,7 +3,6 @@ import com.fathzer.chess.utils.adapters.BoardExplorer; -import com.fathzer.jchess.chesslib.ChessLibBoardExplorer; import com.fathzer.jchess.chesslib.ai.eval.hbpg2.additional.ChessEvalAdditionalElems; import com.github.bhlangonijr.chesslib.Board; diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BitboardsUtils.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BitboardsUtils.java index 5f17728..94e55b1 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BitboardsUtils.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2BitboardsUtils.java @@ -1,31 +1,34 @@ package com.fathzer.jchess.chesslib.ai.eval.hbpg2; public class Hb2BitboardsUtils { - - public static final long h_file = 0x8080808080808080L; - public static final long g_file = h_file >>> 1; - public static final long f_file = h_file >>> 2; - public static final long e_file = h_file >>> 3; - public static final long d_file = h_file >>> 4; - public static final long c_file = h_file >>> 5; - public static final long b_file = h_file >>> 6; - public static final long a_file = h_file >>> 7; - - public static final long rank_1 = 0x00000000000000FFL; - public static final long rank_2 = rank_1 << 8; - public static final long rank_3 = rank_1 << 16; - public static final long rank_4 = rank_1 << 24; - public static final long rank_5 = rank_1 << 32; - public static final long rank_6 = rank_1 << 40; - public static final long rank_7 = rank_1 << 48; - public static final long rank_8 = rank_1 << 56; - - public static final long not_a_file = ~a_file; - public static final long not_h_file = ~h_file; - public static final long not_rank_1 = ~rank_1; - public static final long not_rank_8 = ~rank_8; - - public static final long[] whitePassedPawnMask = new long[] { 0x0303030303030300L, 0x0707070707070700L, + + // This class is built mainly thanks to shameful plagiarism from https://github.com/Luecx/Chess.git (GNU Public License) + // That said, the guy took probably his inspiration from the C++ code described here: https://habr.com/ru/articles/682122/ + + public static final long H_FILE = 0x8080808080808080L; + public static final long G_FILE = H_FILE >>> 1; + public static final long F_FILE = H_FILE >>> 2; + public static final long E_FILE = H_FILE >>> 3; + public static final long D_FILE = H_FILE >>> 4; + public static final long C_FILE = H_FILE >>> 5; + public static final long B_FILE = H_FILE >>> 6; + public static final long A_FILE = H_FILE >>> 7; + + public static final long RANK_1 = 0x00000000000000FFL; + public static final long RANK_2 = RANK_1 << 8; + public static final long RANK_3 = RANK_1 << 16; + public static final long RANK_4 = RANK_1 << 24; + public static final long RANK_5 = RANK_1 << 32; + public static final long RANK_6 = RANK_1 << 40; + public static final long RANK_7 = RANK_1 << 48; + public static final long RANK_8 = RANK_1 << 56; + + public static final long NOT_A_FILE = ~A_FILE; + public static final long NOT_H_FILE = ~H_FILE; + public static final long NOT_RANK_1 = ~RANK_1; + public static final long NOT_RANK_8 = ~RANK_8; + + public static final long[] WHITE_PASSED_PAWNS_MASK = new long[] { 0x0303030303030300L, 0x0707070707070700L, 0x0e0e0e0e0e0e0e00L, 0x1c1c1c1c1c1c1c00L, 0x3838383838383800L, 0x7070707070707000L, 0xe0e0e0e0e0e0e000L, 0xc0c0c0c0c0c0c000L, 0x0303030303030000L, 0x0707070707070000L, 0x0e0e0e0e0e0e0000L, 0x1c1c1c1c1c1c0000L, 0x3838383838380000L, 0x7070707070700000L, 0xe0e0e0e0e0e00000L, 0xc0c0c0c0c0c00000L, 0x0303030303000000L, @@ -40,7 +43,7 @@ public class Hb2BitboardsUtils { 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L }; - public static final long[] blackPassedPawnMask = new long[] { + public static final long[] BLACK_PASSED_PAWNS_MASK = new long[] { 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000003L, 0x0000000000000007L, @@ -57,11 +60,11 @@ public class Hb2BitboardsUtils { 0x0038383838383838L, 0x0070707070707070L, 0x00e0e0e0e0e0e0e0L, 0x00c0c0c0c0c0c0c0L, }; public static final long shiftWest(long b) { - return (b >>> 1) & not_h_file; + return (b >>> 1) & NOT_H_FILE; } public static final long shiftEast(long b) { - return (b << 1) & not_a_file; + return (b << 1) & NOT_A_FILE; } public static final long shiftSouth(long b) { @@ -73,19 +76,19 @@ public static final long shiftNorth(long b) { } public static final long shiftNorthEast(long b) { - return (b << 9) & not_a_file; + return (b << 9) & NOT_A_FILE; } public static final long shiftSouthEast(long b) { - return (b >>> 7) & not_a_file; + return (b >>> 7) & NOT_A_FILE; } public static final long shiftSouthWest(long b) { - return (b >>> 9) & not_h_file; + return (b >>> 9) & NOT_H_FILE; } public static final long shiftNorthWest(long b) { - return (b << 7) & not_h_file; + return (b << 7) & NOT_H_FILE; } } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index 7cdea57..03d3675 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -2,15 +2,13 @@ import static com.fathzer.chess.utils.Pieces.KING; import static com.fathzer.chess.utils.Pieces.PAWN; -import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValueMg; import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValueEg; +import static com.fathzer.jchess.chesslib.ai.eval.hbpg2.Hb2SimplifiedEvaluatorBase.getRawValueMg; import com.fathzer.chess.utils.Pieces; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; -import com.fathzer.games.MoveGenerator.MoveConfidence; import com.github.bhlangonijr.chesslib.Board; -import com.github.bhlangonijr.chesslib.move.Move; /** The current state of a {@link Hb2AbstractIncrementalSimplifiedEvaluator} */ diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index b6f7544..ab67069 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -3,7 +3,6 @@ import static com.fathzer.chess.utils.Pieces.PAWN; import java.util.Arrays; -import java.util.List; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; @@ -15,7 +14,6 @@ import com.github.bhlangonijr.chesslib.File; import com.github.bhlangonijr.chesslib.Piece; import com.github.bhlangonijr.chesslib.Rank; -import com.github.bhlangonijr.chesslib.Square; public class PawnsStrucEval { @@ -304,9 +302,9 @@ public static boolean isPawnPassedModernWay(int rowPawn, int colPawn , boolean i long testPassedPawn = 0L; if (!isBlack) { - testPassedPawn = Hb2BitboardsUtils.whitePassedPawnMask[ordinalSquarePawn] & bitboardBlackPawns; + testPassedPawn = Hb2BitboardsUtils.WHITE_PASSED_PAWNS_MASK[ordinalSquarePawn] & bitboardBlackPawns; } else { - testPassedPawn = Hb2BitboardsUtils.blackPassedPawnMask[ordinalSquarePawn] & bitboardWhitePawns; + testPassedPawn = Hb2BitboardsUtils.BLACK_PASSED_PAWNS_MASK[ordinalSquarePawn] & bitboardWhitePawns; } if (testPassedPawn == 0L) { From 1d1e15378cd2e613ca6d76a135ea92b6ae82a0de Mon Sep 17 00:00:00 2001 From: herve Date: Mon, 25 Nov 2024 08:21:53 +0100 Subject: [PATCH 53/55] more cleaning (suggested by sonarlint) --- .../chesslib/ai/eval/hbpg2/Hb2IncrementalState.java | 4 ++-- .../chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index 03d3675..6842955 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -66,7 +66,7 @@ private void updatePhase(MoveData move) { private int getIncrementMg(MoveData move) { final boolean isBlack = move.getMovingPiece()<0; int moving = Math.abs(move.getMovingPiece()); - final int movingIndex = move.getMovingIndex(); +// final int movingIndex = move.getMovingIndex(); // int inc; int inc = 0; if (moving==KING) { @@ -104,7 +104,7 @@ private int getIncrementMg(MoveData move) { private int getIncrementEg(MoveData move) { final boolean isBlack = move.getMovingPiece()<0; int moving = Math.abs(move.getMovingPiece()); - final int movingIndex = move.getMovingIndex(); +// final int movingIndex = move.getMovingIndex(); // int inc; int inc = 0; if (moving==KING) { diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index ab67069..a4b7598 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -300,7 +300,7 @@ public static boolean isPawnPassedModernWay(int rowPawn, int colPawn , boolean i int ordinalSquarePawn = (Hb2ChessConstants.NB_RANKS*rowPawn)+colPawn; - long testPassedPawn = 0L; + long testPassedPawn; if (!isBlack) { testPassedPawn = Hb2BitboardsUtils.WHITE_PASSED_PAWNS_MASK[ordinalSquarePawn] & bitboardBlackPawns; } else { @@ -332,7 +332,7 @@ public static boolean isPawnProtectedModernWay(int rowPawn, int colPawn , boolea isPawnProtected = ((1L << ordinalSquarePawn) & (connectedPawnsEastBlack | connectedPawnsWestBlack)) != 0; - }; + } return (isPawnProtected); @@ -367,7 +367,7 @@ private void updateDoubledPawns(MoveData move) { if (kind != PAWN) { return; } - boolean isBlack = (move.getMovingPiece()<0?true:false); + boolean isBlack = (move.getMovingPiece()<0); int columnPawn = move.getMovingIndex()%Hb2ChessConstants.NB_FILES; final int promoType = move.getPromotionType(); if (promoType!=0) { @@ -414,7 +414,7 @@ private void updateDoubledPawns(MoveData move) { private void updatePassedAndProtectePassedPawns(MoveData move, Board board) { - boolean isBlack = (move.getMovingPiece()<0?true:false); + int kind = Math.abs(move.getMovingPiece()); if (kind == PAWN) { From 327bcb450aadde51b4198174979c0e0e351ec3cc Mon Sep 17 00:00:00 2001 From: herve Date: Tue, 26 Nov 2024 11:35:40 +0100 Subject: [PATCH 54/55] Very basic first implementation of pieces's mobility in evaluation --- ...bstractIncrementalSimplifiedEvaluator.java | 1 + .../eval/hbpg2/Hb2ElementaryBasicState.java | 19 +-- .../ai/eval/hbpg2/Hb2IncrementalState.java | 1 + .../additional/ChessEvalAdditionalElems.java | 15 ++- .../eval/hbpg2/additional/MobilityEval.java | 127 ++++++++++++++++++ .../eval/hbpg2/additional/PawnsStrucEval.java | 28 ++-- 6 files changed, 156 insertions(+), 35 deletions(-) create mode 100644 src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/MobilityEval.java diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java index 805ff4c..8b8aecd 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2AbstractIncrementalSimplifiedEvaluator.java @@ -67,6 +67,7 @@ public void prepareMove(B board, M move) { toCommit.update(moveData, bordAfterMove); + } } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java index 2ed7511..0a0e05a 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2ElementaryBasicState.java @@ -86,24 +86,7 @@ public void copyTo(Hb2ElementaryBasicState other) { -// int getPhaseForTaperedEval(int computedPhaseValue) { -// return (Math.min(computedPhaseValue, Hb2Phase.PHASE_UPPER_BOUND)); -// } - - -// int evaluateAsWhite() { -// -// // pointsMg = material only! The white material minus the black material in the middlegame. -// // pointsEg = material only! The white material minus the black material in the endgame. -//// int phase = Hb2Phase.getPhaseForTaperedEval(computedPhase); -// // gets the borned phase: necessary for the tapered evaluation -// int phase= (computedPhase > Hb2Phase.PHASE_UPPER_BOUND?Hb2Phase.PHASE_UPPER_BOUND:computedPhase); -//// int pointsPosMg = Hb2SimplifiedEvaluatorBase.getPositionValueMg(board); -//// int pointsPosEg = Hb2SimplifiedEvaluatorBase.getPositionValueEg(board); -// int evalMg = pointsMg + pointsPosMg + Hb2SimplifiedEvaluatorBase.getKingPositionsValueMg(whiteKingIndex, blackKingIndex); -// int evalEg = pointsEg + pointsPosEg+ Hb2SimplifiedEvaluatorBase.getKingPositionsValueEg(whiteKingIndex, blackKingIndex); -// return ((evalMg * phase + evalEg * (Hb2Phase.NB_INCR_PHASE-phase)) / Hb2Phase.NB_INCR_PHASE); -// } + diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java index 6842955..69ad091 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/Hb2IncrementalState.java @@ -8,6 +8,7 @@ import com.fathzer.chess.utils.Pieces; import com.fathzer.chess.utils.adapters.BoardExplorer; import com.fathzer.chess.utils.adapters.MoveData; +import com.fathzer.jchess.chesslib.ChessLibMoveGenerator; import com.github.bhlangonijr.chesslib.Board; /** The current state of a {@link Hb2AbstractIncrementalSimplifiedEvaluator} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java index 394051c..14907e6 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/ChessEvalAdditionalElems.java @@ -11,23 +11,28 @@ public class ChessEvalAdditionalElems { private PawnsStrucEval pawnsStructEval; + private MobilityEval mobilityEval; public ChessEvalAdditionalElems(ChessEvalAdditionalElems ceae) { pawnsStructEval = new PawnsStrucEval(ceae.pawnsStructEval); + mobilityEval = new MobilityEval(ceae.mobilityEval); } public ChessEvalAdditionalElems(Board board) { pawnsStructEval = new PawnsStrucEval( board); + mobilityEval = new MobilityEval( board); } - public void copyTo(ChessEvalAdditionalElems other) { - pawnsStructEval.copyTo(other.pawnsStructEval); - - } +// public void copyTo(ChessEvalAdditionalElems other) { +// pawnsStructEval.copyTo(other.pawnsStructEval); +// mobilityEval.copyTo(other.mobilityEval); +// +// } public void updateEvalAdditionalElems(MoveData move, Board board) { pawnsStructEval.updatePawnsStructEval(move, board); + mobilityEval.computeMobility(move, board); } public PawnsStrucEval getPawnsStructEval() { @@ -41,6 +46,7 @@ public void setPawnsStructEval(PawnsStrucEval pawnsStructEval) { public int getContribMg() { int contrib = 0; contrib+= pawnsStructEval.getContribMg(); + contrib+= mobilityEval.getContribMg(); return(contrib); } @@ -48,6 +54,7 @@ public int getContribMg() { public int getContribEg() { int contrib = 0; contrib+= pawnsStructEval.getContribEg(); + contrib+= mobilityEval.getContribEg(); return(contrib); } diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/MobilityEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/MobilityEval.java new file mode 100644 index 0000000..2b630c8 --- /dev/null +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/MobilityEval.java @@ -0,0 +1,127 @@ +package com.fathzer.jchess.chesslib.ai.eval.hbpg2.additional; + + +import java.util.List; + + +import com.fathzer.chess.utils.adapters.MoveData; + +import com.github.bhlangonijr.chesslib.Board; +import com.github.bhlangonijr.chesslib.Side; +import com.github.bhlangonijr.chesslib.move.Move; + +//Config/EvaluationConfig.cs: public int MgKnightMobilityScale = 77; +//Config/EvaluationConfig.cs: public int EgKnightMobilityScale = 39; +//Config/EvaluationConfig.cs: public int MgBishopMobilityScale = 62; +//Config/EvaluationConfig.cs: public int EgBishopMobilityScale = 185; +//Config/EvaluationConfig.cs: public int MgRookMobilityScale = 85; +//Config/EvaluationConfig.cs: public int EgRookMobilityScale = 154; +//Config/EvaluationConfig.cs: public int MgQueenMobilityScale = 87; +//Config/EvaluationConfig.cs: public int EgQueenMobilityScale = 78; + +public class MobilityEval { + + private final static int MOBILITY_MULTIPLIER = 5; + private final static double MOBILITY_RATIO_FACTOR = 10.0d; + private final static int MOBILITY_MG_EG_RATIO_FACTOR_NUMERATOR = 110; + private final static int MOBILITY_MG_EG_RATIO_FACTOR_DENOMINATOR = 100; + + + private static int mobility(Board board, Side sidePointOfView) { + return MOBILITY_MULTIPLIER * mobilityRatio(board, sidePointOfView); + } + + private static int mobilityRatio(Board board, Side sidePointOfView) { + if (board.getSideToMove() == sidePointOfView) { + List lstMov = board.legalMoves(); + if (board.doNullMove()) { + List lstOpponenMov = board.legalMoves(); + + board.undoMove(); + return (int) ((lstMov.size() * MOBILITY_RATIO_FACTOR) / lstOpponenMov.size()); + } + + } else { + + List lstOpponenMov = board.legalMoves(); + if (board.doNullMove()) { + List lstMov = board.legalMoves(); + + board.undoMove(); + return (int) ((lstMov.size() * MOBILITY_RATIO_FACTOR) / lstOpponenMov.size()); + } + + } + // If we reach this point it's Stalingrad german side... + return(0); // no mobility in the evaluation function in case of error: better than nothing + } + + private int bonusWhiteMobilityMg; + private int bonusWhiteMobilityEg; + private int bonusBlackMobilityMg; + private int bonusBlackMobilityEg; + + public MobilityEval() { + + bonusWhiteMobilityMg = 0; + bonusWhiteMobilityEg = 0; + bonusBlackMobilityMg = 0; + bonusBlackMobilityEg = 0; + + } + + public MobilityEval(MobilityEval mbe) { + + + + + bonusWhiteMobilityMg = mbe.bonusWhiteMobilityMg; + bonusWhiteMobilityEg = mbe.bonusWhiteMobilityEg; + bonusBlackMobilityMg = mbe.bonusBlackMobilityMg; + bonusBlackMobilityEg = mbe.bonusBlackMobilityEg; + + } + + public MobilityEval( Board board) { + this(); + bonusWhiteMobilityMg = mobility(board, Side.WHITE); + bonusWhiteMobilityEg = bonusWhiteMobilityMg * MOBILITY_MG_EG_RATIO_FACTOR_NUMERATOR / MOBILITY_MG_EG_RATIO_FACTOR_DENOMINATOR; + bonusBlackMobilityMg = mobility(board, Side.BLACK); + bonusBlackMobilityEg = bonusWhiteMobilityMg * MOBILITY_MG_EG_RATIO_FACTOR_NUMERATOR / MOBILITY_MG_EG_RATIO_FACTOR_DENOMINATOR; + + + } + + public int getContribMg() { + + + return(bonusWhiteMobilityMg - bonusBlackMobilityMg); + + + } + + + + + + + public int getContribEg() { + + + return(bonusWhiteMobilityEg - bonusBlackMobilityEg); + + } + + + + public void computeMobility(MoveData move, Board board) { + bonusWhiteMobilityMg = mobility(board, Side.WHITE); + bonusWhiteMobilityEg = bonusWhiteMobilityMg * MOBILITY_MG_EG_RATIO_FACTOR_NUMERATOR / MOBILITY_MG_EG_RATIO_FACTOR_DENOMINATOR; + bonusBlackMobilityMg = mobility(board, Side.BLACK); + bonusBlackMobilityEg = bonusWhiteMobilityMg * MOBILITY_MG_EG_RATIO_FACTOR_NUMERATOR / MOBILITY_MG_EG_RATIO_FACTOR_DENOMINATOR; + + + } + + +} diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java index a4b7598..38e0712 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/PawnsStrucEval.java @@ -84,6 +84,16 @@ public PawnsStrucEval(PawnsStrucEval pse) { } + public PawnsStrucEval( Board board) { + this(); + + computeDoubledPawns( board); + computePassedAndProtectedPassedPawns( board); + + + + } + private void computeDoubledPawns(Board board) { @@ -189,15 +199,7 @@ private void computePassedAndProtectedPassedPawns(Board board) { } - public PawnsStrucEval( Board board) { - this(); - - computeDoubledPawns( board); - computePassedAndProtectedPassedPawns( board); - - - } static int getRgSquare (int rank, int file) { return((Hb2ChessConstants.NB_RANKS*rank)+file); @@ -343,11 +345,11 @@ public static boolean isPawnProtectedModernWay(int rowPawn, int colPawn , boolea - void copyTo(PawnsStrucEval other) { - - other.tabNbBlackPawnsByCol = tabNbBlackPawnsByCol.clone(); // not a shallow copy!!!! For integers are of primitive type... - other.tabNbWhitePawnsByCol = tabNbWhitePawnsByCol.clone(); // not a shallow copy!!!! - } +// void copyTo(PawnsStrucEval other) { +// +// other.tabNbBlackPawnsByCol = tabNbBlackPawnsByCol.clone(); // not a shallow copy!!!! For integers are of primitive type... +// other.tabNbWhitePawnsByCol = tabNbWhitePawnsByCol.clone(); // not a shallow copy!!!! +// } public void modifyNumberOfBlackPawnsofColumn(int column, int nbPawns ) { tabNbBlackPawnsByCol[column] += nbPawns; From b8c33bde993d129c0597fd777aa828dc840a7fe8 Mon Sep 17 00:00:00 2001 From: herve Date: Wed, 27 Nov 2024 05:24:27 +0100 Subject: [PATCH 55/55] Corrections of bugs in mobility evaluation --- .../chesslib/ai/eval/hbpg2/additional/MobilityEval.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/MobilityEval.java b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/MobilityEval.java index 2b630c8..6cb8ed2 100644 --- a/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/MobilityEval.java +++ b/src/main/java/com/fathzer/jchess/chesslib/ai/eval/hbpg2/additional/MobilityEval.java @@ -87,7 +87,7 @@ public MobilityEval( Board board) { bonusWhiteMobilityMg = mobility(board, Side.WHITE); bonusWhiteMobilityEg = bonusWhiteMobilityMg * MOBILITY_MG_EG_RATIO_FACTOR_NUMERATOR / MOBILITY_MG_EG_RATIO_FACTOR_DENOMINATOR; bonusBlackMobilityMg = mobility(board, Side.BLACK); - bonusBlackMobilityEg = bonusWhiteMobilityMg * MOBILITY_MG_EG_RATIO_FACTOR_NUMERATOR / MOBILITY_MG_EG_RATIO_FACTOR_DENOMINATOR; + bonusBlackMobilityEg = bonusBlackMobilityMg * MOBILITY_MG_EG_RATIO_FACTOR_NUMERATOR / MOBILITY_MG_EG_RATIO_FACTOR_DENOMINATOR; } @@ -118,7 +118,7 @@ public void computeMobility(MoveData move, Board board) { bonusWhiteMobilityMg = mobility(board, Side.WHITE); bonusWhiteMobilityEg = bonusWhiteMobilityMg * MOBILITY_MG_EG_RATIO_FACTOR_NUMERATOR / MOBILITY_MG_EG_RATIO_FACTOR_DENOMINATOR; bonusBlackMobilityMg = mobility(board, Side.BLACK); - bonusBlackMobilityEg = bonusWhiteMobilityMg * MOBILITY_MG_EG_RATIO_FACTOR_NUMERATOR / MOBILITY_MG_EG_RATIO_FACTOR_DENOMINATOR; + bonusBlackMobilityEg = bonusBlackMobilityMg * MOBILITY_MG_EG_RATIO_FACTOR_NUMERATOR / MOBILITY_MG_EG_RATIO_FACTOR_DENOMINATOR; }