diff --git a/examples/fen.txt b/examples/fen.txt
new file mode 100644
index 000000000..f9c9ce27d
--- /dev/null
+++ b/examples/fen.txt
@@ -0,0 +1 @@
+rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
diff --git a/examples/pom.xml b/examples/pom.xml
index a1de3f159..4cc377711 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -12,6 +12,14 @@
jqf-examples
JQF: Feedback-directed Quickcheck for Java - Sample generators and benchmark tests
+
+
+ lila-maven
+ lichess/scalachess artifacts
+ https://raw.githubusercontent.com/ornicar/lila-maven/master
+
+
+
com.pholser
@@ -128,6 +136,11 @@
24.1-jre
test
+
+ org.lichess
+ scalachess_2.12
+ 8.6.8
+
diff --git a/examples/src/main/java/edu/berkeley/cs/jqf/examples/chess/FENGenerator.java b/examples/src/main/java/edu/berkeley/cs/jqf/examples/chess/FENGenerator.java
new file mode 100644
index 000000000..6b1774c4b
--- /dev/null
+++ b/examples/src/main/java/edu/berkeley/cs/jqf/examples/chess/FENGenerator.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2018, The Regents of the University of California
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package edu.berkeley.cs.jqf.examples.chess;
+
+import com.pholser.junit.quickcheck.generator.GenerationStatus;
+import com.pholser.junit.quickcheck.generator.Generator;
+import com.pholser.junit.quickcheck.random.SourceOfRandomness;
+
+/**
+ * @author Rohan Padhye
+ */
+public class FENGenerator extends Generator {
+
+ public FENGenerator() {
+ super(String.class);
+ }
+
+ @Override
+ public String generate(SourceOfRandomness r, GenerationStatus g) {
+ return String.join(" ", generateBoard(r), generateColor(r), generateCastles(r),
+ generateEnPassant(r), generateHalfMoveClock(r), generateFullMoveClock(r));
+ }
+
+ private char[] pieces = { 'K', 'Q', 'R', 'B', 'N', 'P', 'k', 'q', 'r', 'b', 'n', 'p'};
+
+ private String generateBoard(SourceOfRandomness r) {
+ String[] rows = new String[8];
+ for (int i = 0; i < 8; i++) {
+ String row = "";
+ for (int j = 0; j < 8; j++) {
+ if (r.nextBoolean()) {
+ // empty square
+ int skip = r.nextInt(0, 8-j);
+ j += skip;
+ row += String.valueOf(skip+1); // Upper bound is exclusive
+ } else {
+ // piece
+ row += pieces[r.nextInt(pieces.length)];
+ }
+ }
+ rows[i] = row;
+ }
+ return String.join("/", rows);
+ }
+
+ private String generateColor(SourceOfRandomness r) {
+ return r.nextBoolean() ? "w" : "b";
+ }
+
+ private String generateCastles(SourceOfRandomness r) {
+ if (r.nextBoolean()) {
+ return "-";
+ }
+ String castle = "";
+ if (r.nextBoolean()) {
+ castle += "K";
+ }
+ if (r.nextBoolean()) {
+ castle += "Q";
+ }
+ if (r.nextBoolean()) {
+ castle += "k";
+ }
+ if (r.nextBoolean()) {
+ castle += "q";
+ }
+ if (castle.isEmpty()) {
+ castle = "-";
+ }
+ return castle;
+ }
+
+ private String generateEnPassant(SourceOfRandomness r) {
+ if (r.nextBoolean()) {
+ return "-";
+ }
+ char x = r.nextChar('a', 'i'); // Upper-bound is exclusive
+ int y = r.nextInt(1, 9); // Upper-bound is exclusive
+ return String.valueOf(x) + String.valueOf(y);
+ }
+
+ private String generateHalfMoveClock(SourceOfRandomness r) {
+ return Integer.toString(r.nextInt(0, 50));
+ }
+
+ private String generateFullMoveClock(SourceOfRandomness r) {
+ return Integer.toString(r.nextInt(1, 100));
+ }
+}
diff --git a/examples/src/test/java/edu/berkeley/cs/jqf/examples/chess/FENTest.java b/examples/src/test/java/edu/berkeley/cs/jqf/examples/chess/FENTest.java
new file mode 100644
index 000000000..d5ded4851
--- /dev/null
+++ b/examples/src/test/java/edu/berkeley/cs/jqf/examples/chess/FENTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018, The Regents of the University of California
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package edu.berkeley.cs.jqf.examples.chess;
+
+import chess.Situation;
+import chess.format.Forsyth;
+import com.pholser.junit.quickcheck.From;
+import edu.berkeley.cs.jqf.examples.common.ArbitraryLengthStringGenerator;
+import edu.berkeley.cs.jqf.fuzz.Fuzz;
+import edu.berkeley.cs.jqf.fuzz.JQF;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import scala.Option;
+
+import static org.junit.Assume.*;
+import static org.junit.Assert.*;
+import static org.hamcrest.Matchers.*;
+
+/**
+ * @author Rohan Padhye
+ */
+@RunWith(JQF.class)
+public class FENTest {
+
+ public static final String INITIAL_FEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
+
+ @Test
+ public void test() {
+ testWithString(INITIAL_FEN);
+ }
+
+ @Test
+ public void debug() {
+ debugWithString(INITIAL_FEN);
+ debugWithString("Q");
+ }
+
+ private Situation parseFEN(String fen) {
+ Option situation = Forsyth.$less$less(fen);
+ Assume.assumeTrue(situation.isDefined());
+ return situation.get();
+ }
+
+ @Fuzz
+ public void testWithString(@From(ArbitraryLengthStringGenerator.class) String fen) {
+ Situation situation = parseFEN(fen);
+ assumeTrue(situation.playable(true));
+ assertThat(situation.moves().size(), greaterThan(0));
+ }
+
+ @Fuzz
+ public void debugWithString(@From(ArbitraryLengthStringGenerator.class) String fen) {
+ Situation situation = parseFEN(fen);
+ System.out.println(situation.moves().values());
+ }
+
+ @Fuzz
+ public void testWithGenerator(@From(FENGenerator.class) String fen) {
+ testWithString(fen);
+ }
+
+ @Fuzz
+ public void debugWithGenerator(@From(FENGenerator.class) String fen) {
+ System.out.println(fen);//debugWithString(fen);
+ }
+}
diff --git a/examples/src/test/java/edu/berkeley/cs/jqf/examples/chess/MoveTest.java b/examples/src/test/java/edu/berkeley/cs/jqf/examples/chess/MoveTest.java
new file mode 100644
index 000000000..fb82a435a
--- /dev/null
+++ b/examples/src/test/java/edu/berkeley/cs/jqf/examples/chess/MoveTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018, The Regents of the University of California
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package edu.berkeley.cs.jqf.examples.chess;
+
+import chess.Move;
+import chess.Situation;
+import chess.variant.Standard$;
+import com.pholser.junit.quickcheck.generator.InRange;
+import com.pholser.junit.quickcheck.generator.Size;
+import edu.berkeley.cs.jqf.fuzz.Fuzz;
+import edu.berkeley.cs.jqf.fuzz.JQF;
+import org.junit.runner.RunWith;
+import scala.collection.IndexedSeq;
+
+/**
+ * @author Rohan Padhye
+ */
+@RunWith(JQF.class)
+public class MoveTest {
+
+ private Situation initial = Situation.apply(Standard$.MODULE$);
+
+ @Fuzz
+ public void tryMoves(@InRange(minInt=0) int @Size(min=1, max=20)[] choices) {
+ Situation state = initial;
+ Move lastMove = null;
+ for (int i = 0; i < choices.length; i++) {
+ IndexedSeq moves = state.moves().values().flatten((x) -> x).toIndexedSeq();
+ int k = choices[i] % moves.size();
+ lastMove = moves.apply(k);
+ state = lastMove.situationAfter();
+ //System.out.print(Dumper.apply(lastMove));
+ //System.out.print(" ");
+ }
+ //System.out.println();
+ }
+
+}