mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2024-11-23 19:34:08 +01:00
Moved DroidFishTest project to trunk/
This commit is contained in:
parent
252789e186
commit
1f04910cc5
9
DroidFishTest/.classpath
Normal file
9
DroidFishTest/.classpath
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="src" path="gen"/>
|
||||||
|
<classpathentry combineaccessrules="false" kind="src" path="/DroidFish"/>
|
||||||
|
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||||
|
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||||
|
<classpathentry kind="output" path="bin/classes"/>
|
||||||
|
</classpath>
|
34
DroidFishTest/.project
Normal file
34
DroidFishTest/.project
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>DroidFishTest</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
<project>DroidFish</project>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
19
DroidFishTest/AndroidManifest.xml
Normal file
19
DroidFishTest/AndroidManifest.xml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="org.petero.droidfish.test"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0" >
|
||||||
|
|
||||||
|
<uses-sdk android:minSdkVersion="3" />
|
||||||
|
|
||||||
|
<instrumentation
|
||||||
|
android:name="android.test.InstrumentationTestRunner"
|
||||||
|
android:targetPackage="org.petero.droidfish" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:label="@string/app_name" >
|
||||||
|
<uses-library android:name="android.test.runner" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
BIN
DroidFishTest/bin/res/drawable-hdpi/ic_launcher.png
Normal file
BIN
DroidFishTest/bin/res/drawable-hdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
BIN
DroidFishTest/bin/res/drawable-ldpi/ic_launcher.png
Normal file
BIN
DroidFishTest/bin/res/drawable-ldpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
DroidFishTest/bin/res/drawable-mdpi/ic_launcher.png
Normal file
BIN
DroidFishTest/bin/res/drawable-mdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
40
DroidFishTest/proguard.cfg
Normal file
40
DroidFishTest/proguard.cfg
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
-optimizationpasses 5
|
||||||
|
-dontusemixedcaseclassnames
|
||||||
|
-dontskipnonpubliclibraryclasses
|
||||||
|
-dontpreverify
|
||||||
|
-verbose
|
||||||
|
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||||
|
|
||||||
|
-keep public class * extends android.app.Activity
|
||||||
|
-keep public class * extends android.app.Application
|
||||||
|
-keep public class * extends android.app.Service
|
||||||
|
-keep public class * extends android.content.BroadcastReceiver
|
||||||
|
-keep public class * extends android.content.ContentProvider
|
||||||
|
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||||
|
-keep public class * extends android.preference.Preference
|
||||||
|
-keep public class com.android.vending.licensing.ILicensingService
|
||||||
|
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
native <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers class * extends android.app.Activity {
|
||||||
|
public void *(android.view.View);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers enum * {
|
||||||
|
public static **[] values();
|
||||||
|
public static ** valueOf(java.lang.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep class * implements android.os.Parcelable {
|
||||||
|
public static final android.os.Parcelable$Creator *;
|
||||||
|
}
|
11
DroidFishTest/project.properties
Normal file
11
DroidFishTest/project.properties
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system use,
|
||||||
|
# "ant.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
|
||||||
|
# Project target.
|
||||||
|
target=android-10
|
BIN
DroidFishTest/res/drawable-hdpi/ic_launcher.png
Normal file
BIN
DroidFishTest/res/drawable-hdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
BIN
DroidFishTest/res/drawable-ldpi/ic_launcher.png
Normal file
BIN
DroidFishTest/res/drawable-ldpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
DroidFishTest/res/drawable-mdpi/ic_launcher.png
Normal file
BIN
DroidFishTest/res/drawable-mdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
12
DroidFishTest/res/layout/main.xml
Normal file
12
DroidFishTest/res/layout/main.xml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/hello" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
7
DroidFishTest/res/values/strings.xml
Normal file
7
DroidFishTest/res/values/strings.xml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string name="hello">Hello World!</string>
|
||||||
|
<string name="app_name">DroidFishTestTest</string>
|
||||||
|
|
||||||
|
</resources>
|
78
DroidFishTest/src/org/petero/droidfish/engine/BookTest.java
Normal file
78
DroidFishTest/src/org/petero/droidfish/engine/BookTest.java
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
DroidFish - An Android chess program.
|
||||||
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.petero.droidfish.engine;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.petero.droidfish.gamelogic.ChessParseError;
|
||||||
|
import org.petero.droidfish.gamelogic.Move;
|
||||||
|
import org.petero.droidfish.gamelogic.MoveGen;
|
||||||
|
import org.petero.droidfish.gamelogic.Position;
|
||||||
|
import org.petero.droidfish.gamelogic.TextIO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author petero
|
||||||
|
*/
|
||||||
|
public class BookTest extends TestCase {
|
||||||
|
|
||||||
|
public BookTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getBookMove method, of class Book.
|
||||||
|
*/
|
||||||
|
public void testGetBookMove() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
DroidBook book = DroidBook.getInstance();
|
||||||
|
Move move = book.getBookMove(pos);
|
||||||
|
checkValid(pos, move);
|
||||||
|
|
||||||
|
// Test "out of book" condition
|
||||||
|
pos.setCastleMask(0);
|
||||||
|
move = book.getBookMove(pos);
|
||||||
|
assertEquals(null, move);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getAllBookMoves method, of class Book.
|
||||||
|
*/
|
||||||
|
public void testGetAllBookMoves() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
DroidBook book = DroidBook.getInstance();
|
||||||
|
String moveListString = book.getAllBookMoves(pos).first;
|
||||||
|
String[] strMoves = moveListString.split(":[0-9]* ");
|
||||||
|
assertTrue(strMoves.length > 1);
|
||||||
|
for (String strMove : strMoves) {
|
||||||
|
Move m = TextIO.stringToMove(pos, strMove);
|
||||||
|
checkValid(pos, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check that move is a legal move in position pos. */
|
||||||
|
private void checkValid(Position pos, Move move) {
|
||||||
|
assertTrue(move != null);
|
||||||
|
ArrayList<Move> moveList = new MoveGen().pseudoLegalMoves(pos);
|
||||||
|
moveList = MoveGen.removeIllegal(pos, moveList);
|
||||||
|
assertTrue(moveList.contains(move));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
DroidFish - An Android chess program.
|
||||||
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.petero.droidfish.engine;
|
||||||
|
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.petero.droidfish.gamelogic.ChessParseError;
|
||||||
|
import org.petero.droidfish.gamelogic.Position;
|
||||||
|
import org.petero.droidfish.gamelogic.TextIO;
|
||||||
|
|
||||||
|
|
||||||
|
public class PolyglotBookTest extends TestCase {
|
||||||
|
public PolyglotBookTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getBookMove method, of class Book.
|
||||||
|
*/
|
||||||
|
public void testGetHashKey() throws ChessParseError {
|
||||||
|
// starting position
|
||||||
|
Position pos = TextIO.readFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
|
||||||
|
long key = 0x463b96181691fc9cL;
|
||||||
|
assertEquals(key, PolyglotBook.getHashKey(pos));
|
||||||
|
|
||||||
|
// position after e2e4
|
||||||
|
pos = TextIO.readFEN("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1");
|
||||||
|
key = 0x823c9b50fd114196L;
|
||||||
|
assertEquals(key, PolyglotBook.getHashKey(pos));
|
||||||
|
|
||||||
|
// position after e2e4 d75
|
||||||
|
pos = TextIO.readFEN("rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq d6 0 2");
|
||||||
|
key = 0x0756b94461c50fb0L;
|
||||||
|
assertEquals(key, PolyglotBook.getHashKey(pos));
|
||||||
|
|
||||||
|
// position after e2e4 d7d5 e4e5
|
||||||
|
pos = TextIO.readFEN("rnbqkbnr/ppp1pppp/8/3pP3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2");
|
||||||
|
key = 0x662fafb965db29d4L;
|
||||||
|
assertEquals(key, PolyglotBook.getHashKey(pos));
|
||||||
|
|
||||||
|
// position after e2e4 d7d5 e4e5 f7f5
|
||||||
|
pos = TextIO.readFEN("rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPP1PPP/RNBQKBNR w KQkq f6 0 3");
|
||||||
|
key = 0x22a48b5a8e47ff78L;
|
||||||
|
assertEquals(key, PolyglotBook.getHashKey(pos));
|
||||||
|
|
||||||
|
// position after e2e4 d7d5 e4e5 f7f5 e1e2
|
||||||
|
pos = TextIO.readFEN("rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPPKPPP/RNBQ1BNR b kq - 0 3");
|
||||||
|
key = 0x652a607ca3f242c1L;
|
||||||
|
assertEquals(key, PolyglotBook.getHashKey(pos));
|
||||||
|
|
||||||
|
// position after e2e4 d7d5 e4e5 f7f5 e1e2 e8f7
|
||||||
|
pos = TextIO.readFEN("rnbq1bnr/ppp1pkpp/8/3pPp2/8/8/PPPPKPPP/RNBQ1BNR w - - 0 4");
|
||||||
|
key = 0x00fdd303c946bdd9L;
|
||||||
|
assertEquals(key, PolyglotBook.getHashKey(pos));
|
||||||
|
|
||||||
|
// position after a2a4 b7b5 h2h4 b5b4 c2c4
|
||||||
|
pos = TextIO.readFEN("rnbqkbnr/p1pppppp/8/8/PpP4P/8/1P1PPPP1/RNBQKBNR b KQkq c3 0 3");
|
||||||
|
key = 0x3c8123ea7b067637L;
|
||||||
|
assertEquals(key, PolyglotBook.getHashKey(pos));
|
||||||
|
|
||||||
|
// position after a2a4 b7b5 h2h4 b5b4 c2c4 b4c3 a1a3
|
||||||
|
pos = TextIO.readFEN("rnbqkbnr/p1pppppp/8/8/P6P/R1p5/1P1PPPP1/1NBQKBNR b Kkq - 0 4");
|
||||||
|
key = 0x5c3f9b829b279560L;
|
||||||
|
assertEquals(key, PolyglotBook.getHashKey(pos));
|
||||||
|
}
|
||||||
|
}
|
461
DroidFishTest/src/org/petero/droidfish/gamelogic/GameTest.java
Normal file
461
DroidFishTest/src/org/petero/droidfish/gamelogic/GameTest.java
Normal file
|
@ -0,0 +1,461 @@
|
||||||
|
/*
|
||||||
|
DroidFish - An Android chess program.
|
||||||
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.petero.droidfish.gamelogic;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author petero
|
||||||
|
*/
|
||||||
|
public class GameTest extends TestCase {
|
||||||
|
|
||||||
|
public GameTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of haveDrawOffer method, of class Game.
|
||||||
|
*/
|
||||||
|
public void testHaveDrawOffer() {
|
||||||
|
Game game = new Game(null, null, 0, 0, 0);
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
|
||||||
|
boolean res = game.processString("e4");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
|
||||||
|
res = game.processString("draw offer e5");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(true, game.haveDrawOffer());
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Draw offer does not imply draw
|
||||||
|
assertEquals(Piece.BPAWN, game.currPos().getPiece(Position.getSquare(4, 4))); // e5 move made
|
||||||
|
|
||||||
|
res = game.processString("draw offer Nf3");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(true, game.haveDrawOffer());
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Draw offer does not imply draw
|
||||||
|
assertEquals(Piece.WKNIGHT, game.currPos().getPiece(Position.getSquare(5, 2))); // Nf3 move made
|
||||||
|
|
||||||
|
res = game.processString("Nc6");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
assertEquals(Piece.BKNIGHT, game.currPos().getPiece(Position.getSquare(2, 5))); // Nc6 move made
|
||||||
|
|
||||||
|
res = game.processString("draw offer Bb5");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(true, game.haveDrawOffer());
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
assertEquals(Piece.WBISHOP, game.currPos().getPiece(Position.getSquare(1, 4))); // Bb5 move made
|
||||||
|
|
||||||
|
res = game.processString("draw accept");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(Game.GameState.DRAW_AGREE, game.getGameState()); // Draw by agreement
|
||||||
|
|
||||||
|
game.undoMove(); // Undo "draw accept"
|
||||||
|
assertEquals(Piece.WBISHOP, game.currPos().getPiece(TextIO.getSquare("b5")));
|
||||||
|
assertEquals(true, game.haveDrawOffer());
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.undoMove(); // Undo "Bb5"
|
||||||
|
assertEquals(Piece.EMPTY, game.currPos().getPiece(Position.getSquare(1, 4))); // Bb5 move undone
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.undoMove();
|
||||||
|
assertEquals(Piece.EMPTY, game.currPos().getPiece(Position.getSquare(2, 5))); // Nc6 move undone
|
||||||
|
assertEquals(true, game.haveDrawOffer());
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
|
||||||
|
game.redoMove();
|
||||||
|
assertEquals(Piece.BKNIGHT, game.currPos().getPiece(Position.getSquare(2, 5))); // Nc6 move redone
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.redoMove();
|
||||||
|
assertEquals(Piece.WBISHOP, game.currPos().getPiece(Position.getSquare(1, 4))); // Bb5 move redone
|
||||||
|
assertEquals(true, game.haveDrawOffer());
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.redoMove();
|
||||||
|
assertEquals(Game.GameState.DRAW_AGREE, game.getGameState()); // Can redo draw accept
|
||||||
|
|
||||||
|
// Test draw offer in connection with invalid move
|
||||||
|
game.newGame();
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
|
||||||
|
res = game.processString("draw offer e5");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(TextIO.startPosFEN, TextIO.toFEN(game.currPos())); // Move invalid, not executed
|
||||||
|
res = game.processString("e4");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(true, game.haveDrawOffer()); // Previous draw offer still valid
|
||||||
|
assertEquals(Piece.WPAWN, game.currPos().getPiece(Position.getSquare(4, 3))); // e4 move made
|
||||||
|
|
||||||
|
// Undo/redo shall clear "pendingDrawOffer".
|
||||||
|
game.newGame();
|
||||||
|
game.processString("e4");
|
||||||
|
game.processString("draw offer e4"); // Invalid black move
|
||||||
|
assertEquals(true, game.pendingDrawOffer);
|
||||||
|
game.undoMove();
|
||||||
|
game.redoMove();
|
||||||
|
game.processString("e5");
|
||||||
|
assertEquals(true,game.currPos().whiteMove);
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of draw by 50 move rule, of class Game.
|
||||||
|
*/
|
||||||
|
public void testDraw50() throws ChessParseError {
|
||||||
|
Game game = new Game(null, null, 0, 0, 0);
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
boolean res = game.processString("draw 50");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Draw claim invalid
|
||||||
|
res = game.processString("e4");
|
||||||
|
assertEquals(true, game.haveDrawOffer()); // Invalid claim converted to draw offer
|
||||||
|
|
||||||
|
String fen = "8/4k3/8/P7/8/8/8/1N2K2R w K - 99 83";
|
||||||
|
game.setPos(TextIO.readFEN(fen));
|
||||||
|
res = game.processString("draw 50");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Draw claim invalid
|
||||||
|
|
||||||
|
game.setPos(TextIO.readFEN(fen));
|
||||||
|
game.processString("draw 50 Nc3");
|
||||||
|
assertEquals(Game.GameState.DRAW_50, game.getGameState()); // Draw claim valid
|
||||||
|
assertEquals("Game over, draw by 50 move rule! [Nc3]", game.getGameStateString());
|
||||||
|
|
||||||
|
game.setPos(TextIO.readFEN(fen));
|
||||||
|
game.processString("draw 50 a6");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Pawn move resets counter
|
||||||
|
assertEquals(Piece.WPAWN, game.currPos().getPiece(Position.getSquare(0, 5))); // Move a6 made
|
||||||
|
|
||||||
|
game.setPos(TextIO.readFEN(fen));
|
||||||
|
game.processString("draw 50 O-O");
|
||||||
|
assertEquals(Game.GameState.DRAW_50, game.getGameState()); // Castling doesn't reset counter
|
||||||
|
|
||||||
|
game.setPos(TextIO.readFEN(fen));
|
||||||
|
game.processString("draw 50 Kf2");
|
||||||
|
assertEquals(Game.GameState.DRAW_50, game.getGameState()); // Loss of castling right doesn't reset counter
|
||||||
|
|
||||||
|
game.setPos(TextIO.readFEN(fen));
|
||||||
|
game.processString("draw 50 Ke3");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Ke3 is invalid
|
||||||
|
assertEquals(true, game.currPos().whiteMove);
|
||||||
|
game.processString("a6");
|
||||||
|
assertEquals(true, game.haveDrawOffer()); // Previous invalid claim converted to offer
|
||||||
|
game.processString("draw 50");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState()); // 50 move counter reset.
|
||||||
|
res = game.processString("draw accept");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(Game.GameState.DRAW_AGREE, game.getGameState()); // Can accept previous implicit offer
|
||||||
|
|
||||||
|
fen = "3k4/R7/3K4/8/8/8/8/8 w - - 99 78";
|
||||||
|
game.setPos(TextIO.readFEN(fen));
|
||||||
|
game.processString("Ra8");
|
||||||
|
assertEquals(Game.GameState.WHITE_MATE, game.getGameState());
|
||||||
|
game.processString("draw 50");
|
||||||
|
assertEquals(Game.GameState.WHITE_MATE, game.getGameState()); // Can't claim draw when game over
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of draw by repetition, of class Game.
|
||||||
|
*/
|
||||||
|
public void testDrawRep() throws ChessParseError {
|
||||||
|
Game game = new Game(null, null, 0, 0, 0);
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
game.processString("Nc3");
|
||||||
|
game.processString("Nc6");
|
||||||
|
game.processString("Nb1");
|
||||||
|
game.processString("Nb8");
|
||||||
|
game.processString("Nf3");
|
||||||
|
game.processString("Nf6");
|
||||||
|
game.processString("Ng1");
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
game.processString("draw rep");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Claim not valid, one more move needed
|
||||||
|
game.processString("draw rep Nc6");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Claim not valid, wrong move claimed
|
||||||
|
assertEquals(Piece.BKNIGHT, game.currPos().getPiece(Position.getSquare(2, 5))); // Move Nc6 made
|
||||||
|
assertEquals(true, game.haveDrawOffer());
|
||||||
|
game.undoMove();
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
assertEquals(Piece.EMPTY, game.currPos().getPiece(Position.getSquare(2, 5)));
|
||||||
|
game.processString("draw rep Ng8");
|
||||||
|
assertEquals(Game.GameState.DRAW_REP, game.getGameState());
|
||||||
|
assertEquals(Piece.EMPTY, game.currPos().getPiece(Position.getSquare(6, 7))); // Ng8 not played
|
||||||
|
|
||||||
|
// Test draw by repetition when a "potential ep square but not real ep square" position is present.
|
||||||
|
game.newGame();
|
||||||
|
game.processString("e4"); // e3 is not a real epSquare here
|
||||||
|
game.processString("Nf6");
|
||||||
|
game.processString("Nf3");
|
||||||
|
game.processString("Ng8");
|
||||||
|
game.processString("Ng1");
|
||||||
|
game.processString("Nf6");
|
||||||
|
game.processString("Nf3");
|
||||||
|
game.processString("Ng8");
|
||||||
|
game.processString("draw rep Ng1");
|
||||||
|
assertEquals(Game.GameState.DRAW_REP, game.getGameState());
|
||||||
|
|
||||||
|
// Now check the case when e3 *is* an epSquare
|
||||||
|
game.newGame();
|
||||||
|
game.processString("Nf3");
|
||||||
|
game.processString("d5");
|
||||||
|
game.processString("Ng1");
|
||||||
|
game.processString("d4");
|
||||||
|
game.processString("e4"); // Here e3 is a real epSquare
|
||||||
|
game.processString("Nf6");
|
||||||
|
game.processString("Nf3");
|
||||||
|
game.processString("Ng8");
|
||||||
|
game.processString("Ng1");
|
||||||
|
game.processString("Nf6");
|
||||||
|
game.processString("Nf3");
|
||||||
|
game.processString("Ng8");
|
||||||
|
game.processString("draw rep Ng1");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
|
||||||
|
// EP capture not valid because it would leave the king in check. Therefore
|
||||||
|
// the position has been repeated three times at the end of the move sequence.
|
||||||
|
game.setPos(TextIO.readFEN("4k2n/8/8/8/4p3/8/3P4/3KR2N w - - 0 1"));
|
||||||
|
game.processString("d4");
|
||||||
|
game.processString("Ng6");
|
||||||
|
game.processString("Ng3");
|
||||||
|
game.processString("Nh8");
|
||||||
|
game.processString("Nh1");
|
||||||
|
game.processString("Ng6");
|
||||||
|
game.processString("Ng3");
|
||||||
|
game.processString("Nh8");
|
||||||
|
game.processString("draw rep Nh1");
|
||||||
|
assertEquals(Game.GameState.DRAW_REP, game.getGameState());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of draw offer/accept/request command.
|
||||||
|
*/
|
||||||
|
public void testDrawBug() throws ChessParseError {
|
||||||
|
Game game = new Game(null, null, 0, 0, 0);
|
||||||
|
assertEquals(false, game.haveDrawOffer());
|
||||||
|
game.processString("e4");
|
||||||
|
game.processString("c5");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.processString("draw accept");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.processString("draw rep");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.processString("draw 50");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
assertEquals(Piece.EMPTY, game.tree.currentPos.getPiece(TextIO.getSquare("e5")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of resign command, of class Game.
|
||||||
|
*/
|
||||||
|
public void testResign() throws ChessParseError {
|
||||||
|
Game game = new Game(null, null, 0, 0, 0);
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.processString("f3");
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.processString("resign");
|
||||||
|
assertEquals(Game.GameState.RESIGN_BLACK, game.getGameState());
|
||||||
|
game.undoMove();
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.processString("f3");
|
||||||
|
game.processString("e5");
|
||||||
|
game.processString("resign");
|
||||||
|
assertEquals(Game.GameState.RESIGN_WHITE, game.getGameState());
|
||||||
|
game.undoMove();
|
||||||
|
game.processString("e5");
|
||||||
|
game.processString("g4");
|
||||||
|
game.processString("Qh4");
|
||||||
|
assertEquals(Game.GameState.BLACK_MATE, game.getGameState());
|
||||||
|
game.processString("resign");
|
||||||
|
assertEquals(Game.GameState.BLACK_MATE, game.getGameState()); // Can't resign after game over
|
||||||
|
|
||||||
|
String fen = "8/1p6/2rp2p1/8/p3Qqk1/6R1/PP4PK/8 b - - 3 42";
|
||||||
|
game.setPos(TextIO.readFEN(fen));
|
||||||
|
game.processString("resign");
|
||||||
|
assertEquals(Game.GameState.RESIGN_BLACK, game.getGameState());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of processString method, of class Game.
|
||||||
|
*/
|
||||||
|
public void testProcessString() throws ChessParseError {
|
||||||
|
Game game = new Game(null, null, 0, 0, 0);
|
||||||
|
assertEquals(TextIO.startPosFEN, TextIO.toFEN(game.currPos()));
|
||||||
|
boolean res = game.processString("Nf3");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(1, game.currPos().halfMoveClock);
|
||||||
|
assertEquals(1, game.currPos().fullMoveCounter);
|
||||||
|
res = game.processString("d5");
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals(0, game.currPos().halfMoveClock);
|
||||||
|
assertEquals(2, game.currPos().fullMoveCounter);
|
||||||
|
|
||||||
|
game.undoMove();
|
||||||
|
assertEquals(1, game.currPos().halfMoveClock);
|
||||||
|
assertEquals(1, game.currPos().fullMoveCounter);
|
||||||
|
game.undoMove();
|
||||||
|
assertEquals(TextIO.startPosFEN, TextIO.toFEN(game.currPos()));
|
||||||
|
game.undoMove();
|
||||||
|
assertEquals(TextIO.startPosFEN, TextIO.toFEN(game.currPos()));
|
||||||
|
|
||||||
|
game.redoMove();
|
||||||
|
assertEquals(1, game.currPos().halfMoveClock);
|
||||||
|
assertEquals(1, game.currPos().fullMoveCounter);
|
||||||
|
game.redoMove();
|
||||||
|
assertEquals(0, game.currPos().halfMoveClock);
|
||||||
|
assertEquals(2, game.currPos().fullMoveCounter);
|
||||||
|
game.redoMove();
|
||||||
|
assertEquals(0, game.currPos().halfMoveClock);
|
||||||
|
assertEquals(2, game.currPos().fullMoveCounter);
|
||||||
|
|
||||||
|
game.newGame();
|
||||||
|
assertEquals(TextIO.startPosFEN, TextIO.toFEN(game.currPos()));
|
||||||
|
|
||||||
|
String fen = "8/8/8/4k3/8/8/2p5/5K2 b - - 47 68";
|
||||||
|
Position pos = TextIO.readFEN(fen);
|
||||||
|
game.setPos(TextIO.readFEN(fen));
|
||||||
|
assertEquals(pos, game.currPos());
|
||||||
|
|
||||||
|
res = game.processString("junk");
|
||||||
|
assertEquals(false, res);
|
||||||
|
|
||||||
|
game.newGame();
|
||||||
|
res = game.processString("e7e5");
|
||||||
|
assertEquals(false, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getGameState method, of class Game.
|
||||||
|
*/
|
||||||
|
public void testGetGameState() throws ChessParseError {
|
||||||
|
Game game = new Game(null, null, 0, 0, 0);
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.processString("f3");
|
||||||
|
game.processString("e5");
|
||||||
|
game.processString("g4");
|
||||||
|
game.processString("Qh4");
|
||||||
|
assertEquals(Game.GameState.BLACK_MATE, game.getGameState());
|
||||||
|
|
||||||
|
game.setPos(TextIO.readFEN("5k2/5P2/5K2/8/8/8/8/8 b - - 0 1"));
|
||||||
|
assertEquals(Game.GameState.BLACK_STALEMATE, game.getGameState());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of insufficientMaterial method, of class Game.
|
||||||
|
*/
|
||||||
|
public void testInsufficientMaterial() throws ChessParseError {
|
||||||
|
Game game = new Game(null, null, 0, 0, 0);
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
game.setPos(TextIO.readFEN("4k3/8/8/8/8/8/8/4K3 w - - 0 1"));
|
||||||
|
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||||
|
final int a1 = Position.getSquare(0, 0);
|
||||||
|
Position pos = new Position(game.currPos());
|
||||||
|
pos.setPiece(a1, Piece.WROOK); game.setPos(pos);
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
pos.setPiece(a1, Piece.BQUEEN); game.setPos(pos);
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
pos.setPiece(a1, Piece.WPAWN); game.setPos(pos);
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
pos.setPiece(a1, Piece.BKNIGHT); game.setPos(pos);
|
||||||
|
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||||
|
pos.setPiece(a1, Piece.WBISHOP); game.setPos(pos);
|
||||||
|
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||||
|
|
||||||
|
final int c1 = Position.getSquare(2, 0);
|
||||||
|
pos.setPiece(c1, Piece.WKNIGHT); game.setPos(pos);
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
pos.setPiece(c1, Piece.BBISHOP); game.setPos(pos);
|
||||||
|
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||||
|
pos.setPiece(c1, Piece.WBISHOP); game.setPos(pos);
|
||||||
|
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||||
|
|
||||||
|
final int b2 = Position.getSquare(1, 1);
|
||||||
|
pos.setPiece(b2, Piece.WBISHOP); game.setPos(pos);
|
||||||
|
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||||
|
pos.setPiece(b2, Piece.BBISHOP); game.setPos(pos);
|
||||||
|
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||||
|
|
||||||
|
final int b3 = Position.getSquare(1, 2);
|
||||||
|
pos.setPiece(b3, Piece.WBISHOP); game.setPos(pos);
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
|
||||||
|
// Can't force mate with KNNK, but still not an automatic draw.
|
||||||
|
game.setPos(TextIO.readFEN("8/8/8/8/8/8/8/K3nnk1 w - - 0 1"));
|
||||||
|
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Test that UCI history is not longer than necessary.
|
||||||
|
* We can't expect engines to handle null moves, for example. */
|
||||||
|
public void testUCIHistory() throws ChessParseError {
|
||||||
|
Game game = new Game(null, null, 0, 0, 0);
|
||||||
|
|
||||||
|
Pair<Position, ArrayList<Move>> hist = game.getUCIHistory();
|
||||||
|
assertEquals(0, hist.second.size());
|
||||||
|
Position expectedPos = new Position(game.currPos());
|
||||||
|
assertEquals(expectedPos, hist.first);
|
||||||
|
|
||||||
|
game.processString("Nf3");
|
||||||
|
hist = game.getUCIHistory();
|
||||||
|
assertEquals(1, hist.second.size());
|
||||||
|
assertEquals(TextIO.UCIstringToMove("g1f3"), hist.second.get(0));
|
||||||
|
assertEquals(expectedPos, hist.first);
|
||||||
|
|
||||||
|
game.processString("e5");
|
||||||
|
hist = game.getUCIHistory();
|
||||||
|
expectedPos = new Position(game.currPos());
|
||||||
|
assertEquals(0, hist.second.size());
|
||||||
|
assertEquals(expectedPos, hist.first);
|
||||||
|
|
||||||
|
game.processString("Nc3");
|
||||||
|
hist = game.getUCIHistory();
|
||||||
|
assertEquals(1, hist.second.size());
|
||||||
|
assertEquals(TextIO.UCIstringToMove("b1c3"), hist.second.get(0));
|
||||||
|
assertEquals(expectedPos, hist.first);
|
||||||
|
|
||||||
|
game.processString("Nc6");
|
||||||
|
hist = game.getUCIHistory();
|
||||||
|
assertEquals(2, hist.second.size());
|
||||||
|
assertEquals(TextIO.UCIstringToMove("b1c3"), hist.second.get(0));
|
||||||
|
assertEquals(TextIO.UCIstringToMove("b8c6"), hist.second.get(1));
|
||||||
|
assertEquals(expectedPos, hist.first);
|
||||||
|
|
||||||
|
game.processString("--");
|
||||||
|
hist = game.getUCIHistory();
|
||||||
|
expectedPos = new Position(game.currPos());
|
||||||
|
assertEquals(0, hist.second.size());
|
||||||
|
assertEquals(expectedPos, hist.first);
|
||||||
|
|
||||||
|
game.processString("Nf6");
|
||||||
|
hist = game.getUCIHistory();
|
||||||
|
assertEquals(1, hist.second.size());
|
||||||
|
assertEquals(TextIO.UCIstringToMove("g8f6"), hist.second.get(0));
|
||||||
|
assertEquals(expectedPos, hist.first);
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
game.undoMove();
|
||||||
|
hist = game.getUCIHistory();
|
||||||
|
assertEquals(0, hist.second.size());
|
||||||
|
expectedPos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
assertEquals(expectedPos, hist.first);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,651 @@
|
||||||
|
/*
|
||||||
|
DroidFish - An Android chess program.
|
||||||
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.petero.droidfish.gamelogic;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.petero.droidfish.PGNOptions;
|
||||||
|
import org.petero.droidfish.gamelogic.Game.GameState;
|
||||||
|
import org.petero.droidfish.gamelogic.GameTree.Node;
|
||||||
|
import org.petero.droidfish.gamelogic.GameTree.PgnScanner;
|
||||||
|
|
||||||
|
public class GameTreeTest extends TestCase {
|
||||||
|
|
||||||
|
public final void testGameTree() throws ChessParseError {
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
Position expectedPos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
|
||||||
|
List<Move> varList = gt.variations();
|
||||||
|
assertEquals(0, varList.size());
|
||||||
|
|
||||||
|
int varNo = gt.addMove("e4", "", 0, "", "");
|
||||||
|
assertEquals(0, varNo);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
|
||||||
|
gt.goForward(varNo);
|
||||||
|
Move move = TextIO.UCIstringToMove("e2e4");
|
||||||
|
UndoInfo ui = new UndoInfo();
|
||||||
|
expectedPos.makeMove(move, ui);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
|
||||||
|
gt.goBack();
|
||||||
|
expectedPos.unMakeMove(move, ui);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
|
||||||
|
varNo = gt.addMove("d4", "", 0, "", "");
|
||||||
|
assertEquals(1, varNo);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
varList = gt.variations();
|
||||||
|
assertEquals(2, varList.size());
|
||||||
|
|
||||||
|
gt.goForward(varNo);
|
||||||
|
move = TextIO.UCIstringToMove("d2d4");
|
||||||
|
expectedPos.makeMove(move, ui);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
|
||||||
|
varNo = gt.addMove("g8f6", "", 0, "", "");
|
||||||
|
assertEquals(0, varNo);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
varList = gt.variations();
|
||||||
|
assertEquals(1, varList.size());
|
||||||
|
|
||||||
|
gt.goForward(-1);
|
||||||
|
Move move2 = TextIO.UCIstringToMove("g8f6");
|
||||||
|
UndoInfo ui2 = new UndoInfo();
|
||||||
|
expectedPos.makeMove(move2, ui2);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
assertEquals("Nf6", gt.currentNode.moveStr);
|
||||||
|
|
||||||
|
gt.goBack();
|
||||||
|
assertEquals("d4", gt.currentNode.moveStr);
|
||||||
|
gt.goBack();
|
||||||
|
expectedPos.unMakeMove(move2, ui2);
|
||||||
|
expectedPos.unMakeMove(move, ui);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
assertEquals("", gt.currentNode.moveStr);
|
||||||
|
|
||||||
|
gt.goForward(-1); // Should remember that d2d4 was last visited branch
|
||||||
|
expectedPos.makeMove(move, ui);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
|
||||||
|
byte[] serialState = gt.toByteArray();
|
||||||
|
gt = new GameTree(null);
|
||||||
|
gt.fromByteArray(serialState);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
|
||||||
|
gt.goBack();
|
||||||
|
expectedPos.unMakeMove(move, ui);
|
||||||
|
assertEquals(expectedPos, gt.currentPos);
|
||||||
|
varList = gt.variations();
|
||||||
|
assertEquals(2, varList.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String getMoveListAsString(GameTree gt) {
|
||||||
|
StringBuilder ret = new StringBuilder();
|
||||||
|
Pair<List<Node>, Integer> ml = gt.getMoveList();
|
||||||
|
List<Node> lst = ml.first;
|
||||||
|
final int numMovesPlayed = ml.second;
|
||||||
|
for (int i = 0; i < lst.size(); i++) {
|
||||||
|
if (i == numMovesPlayed)
|
||||||
|
ret.append('*');
|
||||||
|
if (i > 0)
|
||||||
|
ret.append(' ');
|
||||||
|
ret.append(lst.get(i).moveStr);
|
||||||
|
}
|
||||||
|
if (lst.size() == numMovesPlayed)
|
||||||
|
ret.append('*');
|
||||||
|
return ret.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testGetMoveList() throws ChessParseError {
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
gt.addMove("e4", "", 0, "", "");
|
||||||
|
gt.addMove("d4", "", 0, "", "");
|
||||||
|
assertEquals("*e4", getMoveListAsString(gt));
|
||||||
|
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals("e4*", getMoveListAsString(gt));
|
||||||
|
|
||||||
|
gt.addMove("e5", "", 0, "", "");
|
||||||
|
gt.addMove("c5", "", 0, "", "");
|
||||||
|
assertEquals("e4* e5", getMoveListAsString(gt));
|
||||||
|
|
||||||
|
gt.goForward(1);
|
||||||
|
assertEquals("e4 c5*", getMoveListAsString(gt));
|
||||||
|
|
||||||
|
gt.addMove("Nf3", "", 0, "", "");
|
||||||
|
gt.addMove("d4", "", 0, "", "");
|
||||||
|
assertEquals("e4 c5* Nf3", getMoveListAsString(gt));
|
||||||
|
|
||||||
|
gt.goForward(1);
|
||||||
|
assertEquals("e4 c5 d4*", getMoveListAsString(gt));
|
||||||
|
|
||||||
|
gt.goBack();
|
||||||
|
assertEquals("e4 c5* d4", getMoveListAsString(gt));
|
||||||
|
|
||||||
|
gt.goBack();
|
||||||
|
assertEquals("e4* c5 d4", getMoveListAsString(gt));
|
||||||
|
|
||||||
|
gt.goBack();
|
||||||
|
assertEquals("*e4 c5 d4", getMoveListAsString(gt));
|
||||||
|
|
||||||
|
gt.goForward(1);
|
||||||
|
assertEquals("d4*", getMoveListAsString(gt));
|
||||||
|
|
||||||
|
gt.goBack();
|
||||||
|
assertEquals("*d4", getMoveListAsString(gt));
|
||||||
|
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals("e4* c5 d4", getMoveListAsString(gt));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testReorderVariation() throws ChessParseError {
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
gt.addMove("e4", "", 0, "", "");
|
||||||
|
gt.addMove("d4", "", 0, "", "");
|
||||||
|
gt.addMove("c4", "", 0, "", "");
|
||||||
|
assertEquals("e4 d4 c4", getVariationsAsString(gt));
|
||||||
|
assertEquals(0, gt.currentNode.defaultChild);
|
||||||
|
|
||||||
|
gt.reorderVariation(1, 0);
|
||||||
|
assertEquals("d4 e4 c4", getVariationsAsString(gt));
|
||||||
|
assertEquals(1, gt.currentNode.defaultChild);
|
||||||
|
|
||||||
|
gt.reorderVariation(0, 2);
|
||||||
|
assertEquals("e4 c4 d4", getVariationsAsString(gt));
|
||||||
|
assertEquals(0, gt.currentNode.defaultChild);
|
||||||
|
|
||||||
|
gt.reorderVariation(1, 2);
|
||||||
|
assertEquals("e4 d4 c4", getVariationsAsString(gt));
|
||||||
|
assertEquals(0, gt.currentNode.defaultChild);
|
||||||
|
|
||||||
|
gt.reorderVariation(0, 1);
|
||||||
|
assertEquals("d4 e4 c4", getVariationsAsString(gt));
|
||||||
|
assertEquals(1, gt.currentNode.defaultChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testDeleteVariation() throws ChessParseError {
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
gt.addMove("e4", "", 0, "", "");
|
||||||
|
gt.addMove("d4", "", 0, "", "");
|
||||||
|
gt.addMove("c4", "", 0, "", "");
|
||||||
|
gt.addMove("f4", "", 0, "", "");
|
||||||
|
gt.deleteVariation(0);
|
||||||
|
assertEquals("d4 c4 f4", getVariationsAsString(gt));
|
||||||
|
assertEquals(0, gt.currentNode.defaultChild);
|
||||||
|
|
||||||
|
gt.reorderVariation(0, 2);
|
||||||
|
assertEquals("c4 f4 d4", getVariationsAsString(gt));
|
||||||
|
assertEquals(2, gt.currentNode.defaultChild);
|
||||||
|
gt.deleteVariation(1);
|
||||||
|
assertEquals("c4 d4", getVariationsAsString(gt));
|
||||||
|
assertEquals(1, gt.currentNode.defaultChild);
|
||||||
|
|
||||||
|
gt.addMove("g4", "", 0, "", "");
|
||||||
|
gt.addMove("h4", "", 0, "", "");
|
||||||
|
assertEquals("c4 d4 g4 h4", getVariationsAsString(gt));
|
||||||
|
assertEquals(1, gt.currentNode.defaultChild);
|
||||||
|
gt.reorderVariation(1, 2);
|
||||||
|
assertEquals("c4 g4 d4 h4", getVariationsAsString(gt));
|
||||||
|
assertEquals(2, gt.currentNode.defaultChild);
|
||||||
|
gt.deleteVariation(2);
|
||||||
|
assertEquals("c4 g4 h4", getVariationsAsString(gt));
|
||||||
|
assertEquals(0, gt.currentNode.defaultChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String getVariationsAsString(GameTree gt) {
|
||||||
|
StringBuilder ret = new StringBuilder();
|
||||||
|
List<Move> vars = gt.variations();
|
||||||
|
for (int i = 0; i < vars.size(); i++) {
|
||||||
|
if (i > 0)
|
||||||
|
ret.append(' ');
|
||||||
|
String moveStr = TextIO.moveToString(gt.currentPos, vars.get(i), false);
|
||||||
|
ret.append(moveStr);
|
||||||
|
}
|
||||||
|
return ret.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testGetRemainingTime() throws ChessParseError {
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
int initialTime = 60000;
|
||||||
|
assertEquals(initialTime, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(initialTime, gt.getRemainingTime(false, initialTime));
|
||||||
|
|
||||||
|
gt.addMove("e4", "", 0, "", "");
|
||||||
|
gt.goForward(-1);
|
||||||
|
assertEquals(initialTime, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(initialTime, gt.getRemainingTime(false, initialTime));
|
||||||
|
gt.setRemainingTime(45000);
|
||||||
|
assertEquals(45000, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(initialTime, gt.getRemainingTime(false, initialTime));
|
||||||
|
|
||||||
|
gt.addMove("e5", "", 0, "", "");
|
||||||
|
assertEquals(45000, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(initialTime, gt.getRemainingTime(false, initialTime));
|
||||||
|
|
||||||
|
gt.goForward(-1);
|
||||||
|
assertEquals(45000, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(initialTime, gt.getRemainingTime(false, initialTime));
|
||||||
|
|
||||||
|
gt.addMove("Nf3", "", 0, "", "");
|
||||||
|
gt.goForward(-1);
|
||||||
|
gt.addMove("Nc6", "", 0, "", "");
|
||||||
|
gt.goForward(-1);
|
||||||
|
assertEquals(45000, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(initialTime, gt.getRemainingTime(false, initialTime));
|
||||||
|
|
||||||
|
gt.setRemainingTime(30000);
|
||||||
|
assertEquals(45000, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(30000, gt.getRemainingTime(false, initialTime));
|
||||||
|
|
||||||
|
gt.addMove("Bb5", "", 0, "", "");
|
||||||
|
gt.goForward(-1);
|
||||||
|
gt.setRemainingTime(20000);
|
||||||
|
assertEquals(20000, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(30000, gt.getRemainingTime(false, initialTime));
|
||||||
|
|
||||||
|
gt.addMove("a6", "", 0, "", "");
|
||||||
|
gt.goForward(-1);
|
||||||
|
gt.setRemainingTime(15000);
|
||||||
|
assertEquals(20000, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(15000, gt.getRemainingTime(false, initialTime));
|
||||||
|
|
||||||
|
gt.goBack();
|
||||||
|
assertEquals(20000, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(30000, gt.getRemainingTime(false, initialTime));
|
||||||
|
|
||||||
|
gt.goBack();
|
||||||
|
assertEquals(45000, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(30000, gt.getRemainingTime(false, initialTime));
|
||||||
|
|
||||||
|
gt.goBack();
|
||||||
|
assertEquals(45000, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(initialTime, gt.getRemainingTime(false, initialTime));
|
||||||
|
|
||||||
|
gt.goBack();
|
||||||
|
gt.goBack();
|
||||||
|
gt.goBack();
|
||||||
|
assertEquals(initialTime, gt.getRemainingTime(true, initialTime));
|
||||||
|
assertEquals(initialTime, gt.getRemainingTime(false, initialTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<PgnToken> getAllTokens(String s) {
|
||||||
|
PgnScanner sc = new PgnScanner(s);
|
||||||
|
List<PgnToken> ret = new ArrayList<PgnToken>();
|
||||||
|
while (true) {
|
||||||
|
PgnToken tok = sc.nextToken();
|
||||||
|
if (tok.type == PgnToken.EOF)
|
||||||
|
break;
|
||||||
|
ret.add(tok);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testPgnScanner() throws ChessParseError {
|
||||||
|
List<PgnToken> lst = getAllTokens("a\nb\n%junk\nc3"); // a b c3
|
||||||
|
assertEquals(3, lst.size());
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(0).type);
|
||||||
|
assertEquals("a", lst.get(0).token);
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(1).type);
|
||||||
|
assertEquals("b", lst.get(1).token);
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(2).type);
|
||||||
|
assertEquals("c3", lst.get(2).token);
|
||||||
|
|
||||||
|
lst = getAllTokens("e2 ; e5\nc5"); // e2 comment c5
|
||||||
|
assertEquals(3, lst.size());
|
||||||
|
assertEquals("e2", lst.get(0).token);
|
||||||
|
assertEquals(PgnToken.COMMENT, lst.get(1).type);
|
||||||
|
assertEquals(" e5", lst.get(1).token);
|
||||||
|
assertEquals("c5", lst.get(2).token);
|
||||||
|
|
||||||
|
lst = getAllTokens("e4?? { comment ; } e5!?"); // e4?? comment e5!?
|
||||||
|
assertEquals(3, lst.size());
|
||||||
|
assertEquals("e4??", lst.get(0).token);
|
||||||
|
assertEquals(" comment ; ", lst.get(1).token);
|
||||||
|
assertEquals("e5!?", lst.get(2).token);
|
||||||
|
|
||||||
|
lst = getAllTokens("e4! { comment { } e5?"); // e4! comment e5?
|
||||||
|
assertEquals(3, lst.size());
|
||||||
|
assertEquals("e4!", lst.get(0).token);
|
||||||
|
assertEquals(" comment { ", lst.get(1).token);
|
||||||
|
assertEquals("e5?", lst.get(2).token);
|
||||||
|
|
||||||
|
lst = getAllTokens("e4(c4 {(()\\} c5 ( e5))Nf6"); // e4 ( c4 comment c5 ( e5 ) ) Nf6
|
||||||
|
assertEquals(10, lst.size());
|
||||||
|
assertEquals("e4", lst.get(0).token);
|
||||||
|
assertEquals(PgnToken.LEFT_PAREN, lst.get(1).type);
|
||||||
|
assertEquals("c4", lst.get(2).token);
|
||||||
|
assertEquals("(()\\", lst.get(3).token);
|
||||||
|
assertEquals("c5", lst.get(4).token);
|
||||||
|
assertEquals(PgnToken.LEFT_PAREN, lst.get(5).type);
|
||||||
|
assertEquals("e5", lst.get(6).token);
|
||||||
|
assertEquals(PgnToken.RIGHT_PAREN, lst.get(7).type);
|
||||||
|
assertEquals(PgnToken.RIGHT_PAREN, lst.get(8).type);
|
||||||
|
assertEquals("Nf6", lst.get(9).token);
|
||||||
|
|
||||||
|
lst = getAllTokens("[a \"string\"]"); // [ a string ]
|
||||||
|
assertEquals(4, lst.size());
|
||||||
|
assertEquals(PgnToken.LEFT_BRACKET, lst.get(0).type);
|
||||||
|
assertEquals("a", lst.get(1).token);
|
||||||
|
assertEquals(PgnToken.STRING, lst.get(2).type);
|
||||||
|
assertEquals("string", lst.get(2).token);
|
||||||
|
assertEquals(PgnToken.RIGHT_BRACKET, lst.get(3).type);
|
||||||
|
|
||||||
|
lst = getAllTokens("[a \"str\\\"in\\\\g\"]"); // [ a str"in\g ]
|
||||||
|
assertEquals(4, lst.size());
|
||||||
|
assertEquals(PgnToken.LEFT_BRACKET, lst.get(0).type);
|
||||||
|
assertEquals("a", lst.get(1).token);
|
||||||
|
assertEquals(PgnToken.STRING, lst.get(2).type);
|
||||||
|
assertEquals("str\"in\\g", lst.get(2).token);
|
||||||
|
assertEquals(PgnToken.RIGHT_BRACKET, lst.get(3).type);
|
||||||
|
|
||||||
|
lst = getAllTokens("1...Nf6$23Nf3 12 e4_+#=:-*"); // 1 . . . Nf6 $23 Nf3 12 e4_+#=:- *
|
||||||
|
assertEquals(10, lst.size());
|
||||||
|
assertEquals(PgnToken.INTEGER, lst.get(0).type);
|
||||||
|
assertEquals("1", lst.get(0).token);
|
||||||
|
assertEquals(PgnToken.PERIOD, lst.get(1).type);
|
||||||
|
assertEquals(PgnToken.PERIOD, lst.get(2).type);
|
||||||
|
assertEquals(PgnToken.PERIOD, lst.get(3).type);
|
||||||
|
assertEquals("Nf6", lst.get(4).token);
|
||||||
|
assertEquals(PgnToken.NAG, lst.get(5).type);
|
||||||
|
assertEquals("23", lst.get(5).token);
|
||||||
|
assertEquals("Nf3", lst.get(6).token);
|
||||||
|
assertEquals(PgnToken.INTEGER, lst.get(7).type);
|
||||||
|
assertEquals("12", lst.get(7).token);
|
||||||
|
assertEquals("e4_+#=:-", lst.get(8).token);
|
||||||
|
assertEquals(PgnToken.ASTERISK, lst.get(9).type);
|
||||||
|
|
||||||
|
lst = getAllTokens("1/2-1/2 1-0 0-1");
|
||||||
|
assertEquals(3, lst.size());
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(0).type);
|
||||||
|
assertEquals("1/2-1/2", lst.get(0).token);
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(1).type);
|
||||||
|
assertEquals("1-0", lst.get(1).token);
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(2).type);
|
||||||
|
assertEquals("0-1", lst.get(2).token);
|
||||||
|
|
||||||
|
// Test invalid data, unterminated tokens
|
||||||
|
lst = getAllTokens("e4 e5 ; ( )"); // e4 e5 comment
|
||||||
|
assertEquals(3, lst.size());
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(0).type);
|
||||||
|
assertEquals("e4", lst.get(0).token);
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(1).type);
|
||||||
|
assertEquals("e5", lst.get(1).token);
|
||||||
|
assertEquals(PgnToken.COMMENT, lst.get(2).type);
|
||||||
|
assertEquals(" ( )", lst.get(2).token);
|
||||||
|
|
||||||
|
lst = getAllTokens("e4 e5 {"); // e4 e5 ?
|
||||||
|
assertTrue(lst.size() >= 2);
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(0).type);
|
||||||
|
assertEquals("e4", lst.get(0).token);
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(1).type);
|
||||||
|
assertEquals("e5", lst.get(1).token);
|
||||||
|
|
||||||
|
lst = getAllTokens("e4 e5 \""); // e4 e5 ?
|
||||||
|
assertTrue(lst.size() >= 2);
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(0).type);
|
||||||
|
assertEquals("e4", lst.get(0).token);
|
||||||
|
assertEquals(PgnToken.SYMBOL, lst.get(1).type);
|
||||||
|
assertEquals("e5", lst.get(1).token);
|
||||||
|
|
||||||
|
// Test that reading beyond EOF produces more EOF tokens
|
||||||
|
PgnScanner sc = new PgnScanner("e4 e5");
|
||||||
|
assertEquals(PgnToken.SYMBOL, sc.nextToken().type);
|
||||||
|
assertEquals(PgnToken.SYMBOL, sc.nextToken().type);
|
||||||
|
assertEquals(PgnToken.EOF, sc.nextToken().type);
|
||||||
|
assertEquals(PgnToken.EOF, sc.nextToken().type);
|
||||||
|
assertEquals(PgnToken.EOF, sc.nextToken().type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testReadPGN() throws ChessParseError {
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
PGNOptions options = new PGNOptions();
|
||||||
|
options.imp.variations = true;
|
||||||
|
options.imp.comments = true;
|
||||||
|
options.imp.nag = true;
|
||||||
|
boolean res = gt.readPGN("", options);
|
||||||
|
assertEquals(false, res);
|
||||||
|
|
||||||
|
res = gt.readPGN("[White \"a\"][Black \"b\"] {comment} e4 {x}", options);
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals("a", gt.white);
|
||||||
|
assertEquals("b", gt.black);
|
||||||
|
assertEquals("e4", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals("comment", gt.currentNode.preComment);
|
||||||
|
assertEquals("x", gt.currentNode.postComment);
|
||||||
|
|
||||||
|
res = gt.readPGN("e4 e5 Nf3", options);
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals("e4", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals("e5", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals("Nf3", getVariationsAsString(gt));
|
||||||
|
|
||||||
|
res = gt.readPGN("e4 e5 (c5 (c6) d4) (d5) Nf3", options);
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals("e4", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals("e5 c5 c6 d5", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals("Nf3", getVariationsAsString(gt));
|
||||||
|
|
||||||
|
res = gt.readPGN("e4 e5 (c5 (c3) d4 (Nc3)) (d5) Nf3", options); // c3 invalid, should be removed
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals("e4", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals("e5 c5 d5", getVariationsAsString(gt));
|
||||||
|
gt.goForward(1);
|
||||||
|
assertEquals("d4 Nc3", getVariationsAsString(gt));
|
||||||
|
|
||||||
|
res = gt.readPGN("e4 + e5", options); // Extra + should be ignored
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals("e4", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals("e5", getVariationsAsString(gt));
|
||||||
|
|
||||||
|
// Test for broken PGN headers: [White "A "good" player"]
|
||||||
|
res = gt.readPGN("[White \"A \"good\" player\"]\ne4", options);
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals("A \"good\" player", gt.white);
|
||||||
|
assertEquals("e4", getVariationsAsString(gt));
|
||||||
|
|
||||||
|
// Test for broken PGN headers: [White "A "good" player"]
|
||||||
|
res = gt.readPGN("[White \"A \"good old\" player\"]\ne4", options);
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals("A \"good old\" player", gt.white);
|
||||||
|
assertEquals("e4", getVariationsAsString(gt));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testStringEscape() throws ChessParseError {
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
PGNOptions options = new PGNOptions();
|
||||||
|
gt.white = "test \"x\"";
|
||||||
|
String pgn = gt.toPGN(options);
|
||||||
|
gt.white = "";
|
||||||
|
boolean res = gt.readPGN(pgn, options);
|
||||||
|
assertEquals(true, res);
|
||||||
|
assertEquals("test \"x\"", gt.white);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testNAG() throws ChessParseError {
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
PGNOptions options = new PGNOptions();
|
||||||
|
options.imp.variations = true;
|
||||||
|
options.imp.comments = true;
|
||||||
|
options.imp.nag = true;
|
||||||
|
boolean res = gt.readPGN("e4! e5 ? Nf3?! Nc6 !? Bb5!! a6?? Ba4 $14", options);
|
||||||
|
assertEquals(true, res);
|
||||||
|
|
||||||
|
assertEquals("e4", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(1, gt.currentNode.nag);
|
||||||
|
|
||||||
|
assertEquals("e5", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(2, gt.currentNode.nag);
|
||||||
|
|
||||||
|
assertEquals("Nf3", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(6, gt.currentNode.nag);
|
||||||
|
|
||||||
|
assertEquals("Nc6", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(5, gt.currentNode.nag);
|
||||||
|
|
||||||
|
assertEquals("Bb5", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(3, gt.currentNode.nag);
|
||||||
|
|
||||||
|
assertEquals("a6", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(4, gt.currentNode.nag);
|
||||||
|
|
||||||
|
assertEquals("Ba4", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(14, gt.currentNode.nag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testTime() throws ChessParseError {
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
PGNOptions options = new PGNOptions();
|
||||||
|
options.imp.variations = true;
|
||||||
|
options.imp.comments = true;
|
||||||
|
options.imp.nag = true;
|
||||||
|
boolean res = gt.readPGN("e4 { x [%clk 0:0:43] y} e5 {[%clk\n1:2:3]} Nf3 Nc6 {[%clk -1:2 ]}", options);
|
||||||
|
assertEquals(true, res);
|
||||||
|
|
||||||
|
assertEquals("e4", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(43000, gt.currentNode.remainingTime);
|
||||||
|
assertEquals(" x y", gt.currentNode.postComment);
|
||||||
|
|
||||||
|
assertEquals("e5", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(((1*60+2)*60+3)*1000, gt.currentNode.remainingTime);
|
||||||
|
assertEquals("", gt.currentNode.postComment);
|
||||||
|
|
||||||
|
assertEquals("Nf3", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(Integer.MIN_VALUE, gt.currentNode.remainingTime);
|
||||||
|
assertEquals("", gt.currentNode.postComment);
|
||||||
|
|
||||||
|
assertEquals("Nc6", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(-(1*60+2)*1000, gt.currentNode.remainingTime);
|
||||||
|
assertEquals("", gt.currentNode.postComment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testPlayerAction() throws ChessParseError {
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
int varNo = gt.addMove("--", "resign", 0, "", "");
|
||||||
|
assertEquals(0, varNo);
|
||||||
|
|
||||||
|
PGNOptions options = new PGNOptions();
|
||||||
|
|
||||||
|
String pgn = gt.toPGN(options);
|
||||||
|
assertEquals(-1, pgn.indexOf("--"));
|
||||||
|
|
||||||
|
options.exp.playerAction = true;
|
||||||
|
pgn = gt.toPGN(options);
|
||||||
|
assertTrue(pgn.indexOf("--") >= 0);
|
||||||
|
|
||||||
|
gt = new GameTree(null);
|
||||||
|
gt.readPGN(pgn, options);
|
||||||
|
assertEquals("--", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(GameState.RESIGN_WHITE, gt.getGameState());
|
||||||
|
|
||||||
|
gt = new GameTree(null);
|
||||||
|
gt.readPGN("1. -- {[%playeraction resign]}", options);
|
||||||
|
assertEquals("--", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(GameState.RESIGN_WHITE, gt.getGameState());
|
||||||
|
|
||||||
|
gt.readPGN("1. e4 -- {[%playeraction resign]}", options);
|
||||||
|
assertEquals("e4", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals("--", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
assertEquals(GameState.RESIGN_BLACK, gt.getGameState());
|
||||||
|
|
||||||
|
// Even if playerActions are not exported, moves corresponding
|
||||||
|
// to draw offers must still be exported
|
||||||
|
gt = new GameTree(null);
|
||||||
|
varNo = gt.addMove("e4", "draw offer", 0, "", "");
|
||||||
|
assertEquals(0, varNo);
|
||||||
|
assertEquals("e4", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
varNo = gt.addMove("e5", "", 0, "", "");
|
||||||
|
assertEquals(0, varNo);
|
||||||
|
assertEquals("e5", getVariationsAsString(gt));
|
||||||
|
gt.goForward(0);
|
||||||
|
options.exp.playerAction = false;
|
||||||
|
pgn = gt.toPGN(options);
|
||||||
|
assertTrue(pgn.indexOf("e4") >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testGameResult() throws ChessParseError {
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
int varNo = gt.addMove("e4", "", 0, "", "");
|
||||||
|
gt.goForward(varNo);
|
||||||
|
varNo = gt.addMove("e5", "", 0, "", "");
|
||||||
|
gt.goForward(varNo);
|
||||||
|
varNo = gt.addMove("--", "resign", 0, "", "");
|
||||||
|
gt.goBack();
|
||||||
|
gt.goBack();
|
||||||
|
varNo = gt.addMove("d4", "", 0, "", "");
|
||||||
|
gt.goForward(varNo);
|
||||||
|
varNo = gt.addMove("--", "resign", 0, "", "");
|
||||||
|
gt.goForward(varNo);
|
||||||
|
|
||||||
|
// Black has resigned in a variation, but white resigned in the mainline,
|
||||||
|
// so the PGN result should be "0-1";
|
||||||
|
PGNOptions options = new PGNOptions();
|
||||||
|
options.exp.variations = true;
|
||||||
|
// options.exp.playerAction = true;
|
||||||
|
String pgn = gt.toPGN(options);
|
||||||
|
assertTrue(pgn.indexOf("1-0") < 0);
|
||||||
|
assertTrue(pgn.indexOf("0-1") >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void testPGNPromotion() throws ChessParseError {
|
||||||
|
// PGN standard specifies that promotion moves shall have an = sign
|
||||||
|
// before the promotion piece
|
||||||
|
GameTree gt = new GameTree(null);
|
||||||
|
gt.setStartPos(TextIO.readFEN("rnbqkbnr/ppPppppp/8/8/8/8/PP1PPPPP/RNBQKBNR w KQkq - 0 1"));
|
||||||
|
int varNo = gt.addMove("cxb8N", "", 0, "", "");
|
||||||
|
assertEquals(0, varNo);
|
||||||
|
varNo = gt.addMove("cxd8R+", "", 0, "", "");
|
||||||
|
assertEquals(1, varNo);
|
||||||
|
assertEquals("cxb8N cxd8R+", getVariationsAsString(gt)); // Normal short alg notation does not have =
|
||||||
|
PGNOptions options = new PGNOptions();
|
||||||
|
options.exp.variations = true;
|
||||||
|
String pgn = gt.toPGN(options);
|
||||||
|
assertTrue(pgn.indexOf("cxb8=N") >= 0); // ... but PGN promotions do have the = sign
|
||||||
|
assertTrue(pgn.indexOf("cxd8=R+") >= 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,204 @@
|
||||||
|
/*
|
||||||
|
DroidFish - An Android chess program.
|
||||||
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.petero.droidfish.gamelogic;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author petero
|
||||||
|
*/
|
||||||
|
public class MoveGenTest extends TestCase {
|
||||||
|
|
||||||
|
public MoveGenTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of pseudoLegalMoves method, of class MoveGen.
|
||||||
|
*/
|
||||||
|
public void testPseudoLegalMoves() throws ChessParseError {
|
||||||
|
String fen = "8/3k4/8/2n2pP1/1P6/1NB5/2QP4/R3K2R w KQ f6 0 2";
|
||||||
|
Position pos = TextIO.readFEN(fen);
|
||||||
|
assertEquals(fen, TextIO.toFEN(pos));
|
||||||
|
List<String> strMoves = getMoveList(pos, false);
|
||||||
|
assertTrue(strMoves.contains("Ra1-d1"));
|
||||||
|
assertTrue(!strMoves.contains("Ra1-e1"));
|
||||||
|
assertTrue(!strMoves.contains("Ra1-f1"));
|
||||||
|
assertTrue(strMoves.contains("Ra1-a7+"));
|
||||||
|
assertTrue(strMoves.contains("Ke1-f2"));
|
||||||
|
assertTrue(!strMoves.contains("Ke1-g3"));
|
||||||
|
assertTrue(strMoves.contains("Bc3-f6"));
|
||||||
|
assertTrue(!strMoves.contains("Nb3xd2"));
|
||||||
|
|
||||||
|
// Test castling
|
||||||
|
assertTrue(strMoves.contains("O-O"));
|
||||||
|
assertTrue(strMoves.contains("O-O-O"));
|
||||||
|
assertEquals(49, strMoves.size());
|
||||||
|
|
||||||
|
pos.setPiece(Position.getSquare(4,3), Piece.BROOK);
|
||||||
|
strMoves = getMoveList(pos, false);
|
||||||
|
assertTrue(!strMoves.contains("O-O")); // In check, not castling possible
|
||||||
|
assertTrue(!strMoves.contains("O-O-O"));
|
||||||
|
|
||||||
|
pos.setPiece(Position.getSquare(4, 3), Piece.EMPTY);
|
||||||
|
pos.setPiece(Position.getSquare(5, 3), Piece.BROOK);
|
||||||
|
strMoves = getMoveList(pos, false);
|
||||||
|
assertTrue(!strMoves.contains("O-O")); // f1 attacked, short castle not possible
|
||||||
|
assertTrue(strMoves.contains("O-O-O"));
|
||||||
|
|
||||||
|
pos.setPiece(Position.getSquare(5, 3), Piece.EMPTY);
|
||||||
|
pos.setPiece(Position.getSquare(6, 3), Piece.BBISHOP);
|
||||||
|
strMoves = getMoveList(pos, false);
|
||||||
|
assertTrue(strMoves.contains("O-O")); // d1 attacked, long castle not possible
|
||||||
|
assertTrue(!strMoves.contains("O-O-O"));
|
||||||
|
|
||||||
|
pos.setPiece(Position.getSquare(6, 3), Piece.EMPTY);
|
||||||
|
pos.setCastleMask(1 << Position.A1_CASTLE);
|
||||||
|
strMoves = getMoveList(pos, false);
|
||||||
|
assertTrue(!strMoves.contains("O-O")); // short castle right has been lost
|
||||||
|
assertTrue(strMoves.contains("O-O-O"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of pseudoLegalMoves method, of class MoveGen. Pawn moves.
|
||||||
|
*/
|
||||||
|
public void testPawnMoves() throws ChessParseError {
|
||||||
|
String fen = "1r2k3/P1pppp1p/8/1pP3p1/1nPp2P1/n4p1P/1P2PP2/4KBNR w K b6 0 1";
|
||||||
|
Position pos = TextIO.readFEN(fen);
|
||||||
|
assertEquals(fen, TextIO.toFEN(pos));
|
||||||
|
List<String> strMoves = getMoveList(pos, false);
|
||||||
|
assertTrue(strMoves.contains("c5xb6")); // En passant capture
|
||||||
|
assertTrue(strMoves.contains("a7-a8Q")); // promotion
|
||||||
|
assertTrue(strMoves.contains("a7-a8N")); // under promotion
|
||||||
|
assertTrue(strMoves.contains("a7xb8R#")); // capture promotion
|
||||||
|
assertTrue(strMoves.contains("b2-b3")); // pawn single move
|
||||||
|
assertTrue(strMoves.contains("b2xa3")); // pawn capture to the left
|
||||||
|
assertTrue(strMoves.contains("e2-e4")); // pawn double move
|
||||||
|
assertTrue(strMoves.contains("e2xf3")); // pawn capture to the right
|
||||||
|
assertEquals(22, strMoves.size());
|
||||||
|
|
||||||
|
pos.setEpSquare(-1);
|
||||||
|
strMoves = getMoveList(pos, false);
|
||||||
|
assertEquals(21, strMoves.size()); // No ep, one less move possible
|
||||||
|
|
||||||
|
// Check black pawn moves
|
||||||
|
pos.setWhiteMove(false);
|
||||||
|
strMoves = getMoveList(pos, false);
|
||||||
|
assertTrue(strMoves.contains("f3xe2"));
|
||||||
|
assertTrue(strMoves.contains("d4-d3"));
|
||||||
|
assertTrue(strMoves.contains("e7-e6"));
|
||||||
|
assertTrue(strMoves.contains("e7-e5"));
|
||||||
|
assertEquals(28, strMoves.size());
|
||||||
|
|
||||||
|
// Check black pawn promotion
|
||||||
|
pos.setPiece(Position.getSquare(0,1), Piece.BPAWN);
|
||||||
|
strMoves = getMoveList(pos, false);
|
||||||
|
assertTrue(strMoves.contains("a2-a1Q+"));
|
||||||
|
assertTrue(strMoves.contains("a2-a1R+"));
|
||||||
|
assertTrue(strMoves.contains("a2-a1N"));
|
||||||
|
assertTrue(strMoves.contains("a2-a1B"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of inCheck method, of class MoveGen.
|
||||||
|
*/
|
||||||
|
public void testInCheck() {
|
||||||
|
Position pos = new Position();
|
||||||
|
pos.setPiece(Position.getSquare(4,2), Piece.WKING);
|
||||||
|
pos.setPiece(Position.getSquare(4,7), Piece.BKING);
|
||||||
|
assertEquals(false, MoveGen.inCheck(pos));
|
||||||
|
|
||||||
|
pos.setPiece(Position.getSquare(3,3), Piece.BQUEEN);
|
||||||
|
assertEquals(true, MoveGen.inCheck(pos));
|
||||||
|
pos.setPiece(Position.getSquare(3,3), Piece.BROOK);
|
||||||
|
assertEquals(false, MoveGen.inCheck(pos));
|
||||||
|
pos.setPiece(Position.getSquare(3,3), Piece.BPAWN);
|
||||||
|
assertEquals(true, MoveGen.inCheck(pos));
|
||||||
|
|
||||||
|
pos.setPiece(Position.getSquare(3,3), Piece.EMPTY);
|
||||||
|
pos.setPiece(Position.getSquare(5,3), Piece.WQUEEN);
|
||||||
|
assertEquals(false, MoveGen.inCheck(pos));
|
||||||
|
|
||||||
|
pos.setPiece(Position.getSquare(4, 6), Piece.BROOK);
|
||||||
|
assertEquals(true, MoveGen.inCheck(pos));
|
||||||
|
pos.setPiece(Position.getSquare(4, 4), Piece.WPAWN);
|
||||||
|
assertEquals(false, MoveGen.inCheck(pos));
|
||||||
|
|
||||||
|
pos.setPiece(Position.getSquare(2, 3), Piece.BKNIGHT);
|
||||||
|
assertEquals(true, MoveGen.inCheck(pos));
|
||||||
|
|
||||||
|
pos.setPiece(Position.getSquare(2, 3), Piece.EMPTY);
|
||||||
|
pos.setPiece(Position.getSquare(0, 4), Piece.BKNIGHT);
|
||||||
|
assertEquals(false, MoveGen.inCheck(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of removeIllegal method, of class MoveGen.
|
||||||
|
*/
|
||||||
|
public void testRemoveIllegal() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN("8/3k4/8/2n1rpP1/1P6/1NB5/2QP4/R3K2R w KQ f6 0 1");
|
||||||
|
List<String> strMoves = getMoveList(pos, true);
|
||||||
|
assertTrue(strMoves.contains("Qc2-e4"));
|
||||||
|
assertTrue(strMoves.contains("Bc3xe5"));
|
||||||
|
assertTrue(strMoves.contains("Ke1-d1"));
|
||||||
|
assertTrue(strMoves.contains("Ke1-f1"));
|
||||||
|
assertTrue(strMoves.contains("Ke1-f2"));
|
||||||
|
assertEquals(5, strMoves.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that if king capture is possible, only a king capture move is returned in the move list.
|
||||||
|
*/
|
||||||
|
public void testKingCapture() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN("8/4k3/8/8/8/8/8/4RK2 b - - 0 1");
|
||||||
|
pos.setWhiteMove(true);
|
||||||
|
List<String> strMoves = getMoveList(pos, false);
|
||||||
|
assertEquals(1, strMoves.size());
|
||||||
|
assertEquals("Re1xe7", strMoves.get(0));
|
||||||
|
|
||||||
|
pos.setPiece(Position.getSquare(0, 2), Piece.WBISHOP);
|
||||||
|
pos.setPiece(Position.getSquare(4, 1), Piece.WPAWN);
|
||||||
|
strMoves = getMoveList(pos, false);
|
||||||
|
assertEquals(1, strMoves.size());
|
||||||
|
assertEquals("Ba3xe7", strMoves.get(0));
|
||||||
|
|
||||||
|
pos.setPiece(Position.getSquare(1, 3), Piece.WPAWN);
|
||||||
|
pos.setPiece(Position.getSquare(5, 5), Piece.WPAWN);
|
||||||
|
strMoves = getMoveList(pos, false);
|
||||||
|
assertEquals(1, strMoves.size());
|
||||||
|
assertEquals("f6xe7", strMoves.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getMoveList(Position pos, boolean onlyLegal) {
|
||||||
|
ArrayList<Move> moves = new MoveGen().pseudoLegalMoves(pos);
|
||||||
|
if (onlyLegal) {
|
||||||
|
moves = MoveGen.removeIllegal(pos, moves);
|
||||||
|
}
|
||||||
|
ArrayList<String> strMoves = new ArrayList<String>();
|
||||||
|
for (Move m : moves) {
|
||||||
|
String mStr = TextIO.moveToString(pos, m, true);
|
||||||
|
strMoves.add(mStr);
|
||||||
|
// System.out.println(mStr);
|
||||||
|
}
|
||||||
|
return strMoves;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
DroidFish - An Android chess program.
|
||||||
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.petero.droidfish.gamelogic;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author petero
|
||||||
|
*/
|
||||||
|
public class MoveTest extends TestCase {
|
||||||
|
|
||||||
|
public MoveTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of move constructor, of class Move.
|
||||||
|
*/
|
||||||
|
public void testMoveConstructor() {
|
||||||
|
int f = Position.getSquare(4, 1);
|
||||||
|
int t = Position.getSquare(4, 3);
|
||||||
|
int p = Piece.WROOK;
|
||||||
|
Move move = new Move(f, t, p);
|
||||||
|
assertEquals(move.from, f);
|
||||||
|
assertEquals(move.to,t);
|
||||||
|
assertEquals(move.promoteTo, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of equals, of class Move.
|
||||||
|
*/
|
||||||
|
public void testEquals() {
|
||||||
|
Move m1 = new Move(Position.getSquare(0, 6), Position.getSquare(1, 7), Piece.WROOK);
|
||||||
|
Move m2 = new Move(Position.getSquare(0, 6), Position.getSquare(0, 7), Piece.WROOK);
|
||||||
|
Move m3 = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WROOK);
|
||||||
|
Move m4 = new Move(Position.getSquare(0, 6), Position.getSquare(1, 7), Piece.WKNIGHT);
|
||||||
|
Move m5 = new Move(Position.getSquare(0, 6), Position.getSquare(1, 7), Piece.WROOK);
|
||||||
|
assertTrue(!m1.equals(m2));
|
||||||
|
assertTrue(!m1.equals(m3));
|
||||||
|
assertTrue(!m1.equals(m4));
|
||||||
|
assertTrue(m1.equals(m5));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
DroidFish - An Android chess program.
|
||||||
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.petero.droidfish.gamelogic;
|
||||||
|
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author petero
|
||||||
|
*/
|
||||||
|
public class PieceTest extends TestCase {
|
||||||
|
|
||||||
|
public PieceTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of isWhite method, of class Piece.
|
||||||
|
*/
|
||||||
|
public void testIsWhite() {
|
||||||
|
assertEquals(false, Piece.isWhite(Piece.BBISHOP));
|
||||||
|
assertEquals(true , Piece.isWhite(Piece.WBISHOP));
|
||||||
|
assertEquals(true , Piece.isWhite(Piece.WKING));
|
||||||
|
assertEquals(false, Piece.isWhite(Piece.BKING));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,455 @@
|
||||||
|
/*
|
||||||
|
DroidFish - An Android chess program.
|
||||||
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.petero.droidfish.gamelogic;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author petero
|
||||||
|
*/
|
||||||
|
public class PositionTest extends TestCase {
|
||||||
|
|
||||||
|
public PositionTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getPiece method, of class Position.
|
||||||
|
*/
|
||||||
|
public void testGetPiece() throws ChessParseError {
|
||||||
|
Position pos = new Position();
|
||||||
|
int result = pos.getPiece(0);
|
||||||
|
assertEquals(result, Piece.EMPTY);
|
||||||
|
|
||||||
|
pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
result = pos.getPiece(0);
|
||||||
|
assertEquals(result, Piece.WROOK);
|
||||||
|
for (int x = 0; x < 8; x++) {
|
||||||
|
for (int y = 0; y < 2; y++) {
|
||||||
|
int p1 = pos.getPiece(Position.getSquare(x, y));
|
||||||
|
int p2 = pos.getPiece(Position.getSquare(x, 7-y));
|
||||||
|
int bwDiff = Piece.BPAWN - Piece.WPAWN;
|
||||||
|
assertEquals(p2, p1 + bwDiff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getIndex method, of class Position.
|
||||||
|
*/
|
||||||
|
public void testGetIndex() {
|
||||||
|
for (int x = 0; x < 8; x++) {
|
||||||
|
for (int y = 0; y < 8; y++) {
|
||||||
|
int sq = Position.getSquare(x, y);
|
||||||
|
int x2 = Position.getX(sq);
|
||||||
|
int y2 = Position.getY(sq);
|
||||||
|
assertEquals(x, x2);
|
||||||
|
assertEquals(y, y2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of setPiece method, of class Position.
|
||||||
|
*/
|
||||||
|
public void testSetPiece() {
|
||||||
|
Position instance = new Position();
|
||||||
|
assertEquals(Piece.EMPTY, instance.getPiece(Position.getSquare(0, 0)));
|
||||||
|
instance.setPiece(Position.getSquare(3, 4), Piece.WKING);
|
||||||
|
assertEquals(Piece.WKING, instance.getPiece(Position.getSquare(3, 4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of makeMove method, of class Position.
|
||||||
|
*/
|
||||||
|
public void testMakeMove() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
Position origPos = new Position(pos);
|
||||||
|
assertTrue(pos.equals(origPos));
|
||||||
|
Move move = new Move(Position.getSquare(4,1), Position.getSquare(4,3), Piece.EMPTY);
|
||||||
|
UndoInfo ui = new UndoInfo();
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(pos.whiteMove, false);
|
||||||
|
assertEquals(-1, pos.getEpSquare());
|
||||||
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(4,1)));
|
||||||
|
assertEquals(Piece.WPAWN, pos.getPiece(Position.getSquare(4,3)));
|
||||||
|
assertTrue(!pos.equals(origPos));
|
||||||
|
int castleMask = (1 << Position.A1_CASTLE) |
|
||||||
|
(1 << Position.H1_CASTLE) |
|
||||||
|
(1 << Position.A8_CASTLE) |
|
||||||
|
(1 << Position.H8_CASTLE);
|
||||||
|
assertEquals(castleMask,pos.getCastleMask());
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
assertEquals(pos.whiteMove, true);
|
||||||
|
assertEquals(Piece.WPAWN, pos.getPiece(Position.getSquare(4,1)));
|
||||||
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(4,3)));
|
||||||
|
assertTrue(pos.equals(origPos));
|
||||||
|
|
||||||
|
String fen = "r1bqk2r/2ppbppp/p1n2n2/1pP1p3/B3P3/5N2/PP1P1PPP/RNBQK2R w KQkq b6 0 2";
|
||||||
|
pos = TextIO.readFEN(fen);
|
||||||
|
assertEquals(fen, TextIO.toFEN(pos));
|
||||||
|
origPos = new Position(pos);
|
||||||
|
assertEquals(Position.getSquare(1,5), pos.getEpSquare());
|
||||||
|
|
||||||
|
// Test capture
|
||||||
|
move = new Move(Position.getSquare(0, 3), Position.getSquare(1,4), Piece.EMPTY);
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(-1, pos.getEpSquare());
|
||||||
|
assertEquals(Piece.WBISHOP, pos.getPiece(Position.getSquare(1,4)));
|
||||||
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(0,3)));
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
assertTrue(pos.equals(origPos));
|
||||||
|
|
||||||
|
// Test castling
|
||||||
|
move = new Move(Position.getSquare(4, 0), Position.getSquare(6,0), Piece.EMPTY);
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(Piece.WROOK, pos.getPiece(Position.getSquare(5,0)));
|
||||||
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(7,0)));
|
||||||
|
castleMask = (1 << Position.A8_CASTLE) |
|
||||||
|
(1 << Position.H8_CASTLE);
|
||||||
|
assertEquals(castleMask,pos.getCastleMask());
|
||||||
|
assertEquals(-1, pos.getEpSquare());
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
assertTrue(pos.equals(origPos));
|
||||||
|
|
||||||
|
// Test castling rights (king move)
|
||||||
|
move = new Move(Position.getSquare(4, 0), Position.getSquare(4,1), Piece.EMPTY);
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
castleMask = (1 << Position.A8_CASTLE) |
|
||||||
|
(1 << Position.H8_CASTLE);
|
||||||
|
assertEquals(castleMask,pos.getCastleMask());
|
||||||
|
assertEquals(-1, pos.getEpSquare());
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
assertTrue(pos.equals(origPos));
|
||||||
|
|
||||||
|
// Test castling rights (rook move)
|
||||||
|
move = new Move(Position.getSquare(7, 0), Position.getSquare(6,0), Piece.EMPTY);
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
castleMask = (1 << Position.A1_CASTLE) |
|
||||||
|
(1 << Position.A8_CASTLE) |
|
||||||
|
(1 << Position.H8_CASTLE);
|
||||||
|
assertEquals(castleMask,pos.getCastleMask());
|
||||||
|
assertEquals(-1, pos.getEpSquare());
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
assertTrue(pos.equals(origPos));
|
||||||
|
|
||||||
|
// Test en passant
|
||||||
|
move = new Move(Position.getSquare(2, 4), Position.getSquare(1,5), Piece.EMPTY);
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(Piece.WPAWN, pos.getPiece(Position.getSquare(1,5)));
|
||||||
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(2,4)));
|
||||||
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(1,4)));
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
assertTrue(pos.equals(origPos));
|
||||||
|
|
||||||
|
// Test castling rights loss when rook captured
|
||||||
|
pos.setPiece(Position.getSquare(6,2), Piece.BKNIGHT);
|
||||||
|
pos.setWhiteMove(false);
|
||||||
|
Position origPos2 = new Position(pos);
|
||||||
|
move = new Move(Position.getSquare(6,2), Position.getSquare(7,0), Piece.EMPTY);
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
castleMask = (1 << Position.A1_CASTLE) |
|
||||||
|
(1 << Position.A8_CASTLE) |
|
||||||
|
(1 << Position.H8_CASTLE);
|
||||||
|
assertEquals(castleMask,pos.getCastleMask());
|
||||||
|
assertEquals(-1, pos.getEpSquare());
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
assertTrue(pos.equals(origPos2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of makeMove method, of class Position.
|
||||||
|
*/
|
||||||
|
public void testPromotion() throws ChessParseError {
|
||||||
|
String fen = "r1bqk2r/1Pppbppp/p1n2n2/2P1p3/B3P3/5N2/Pp1P1PPP/R1BQK2R w KQkq - 0 1";
|
||||||
|
Position pos = TextIO.readFEN(fen);
|
||||||
|
assertEquals(fen, TextIO.toFEN(pos));
|
||||||
|
Position origPos = new Position(pos);
|
||||||
|
assertEquals(origPos, pos);
|
||||||
|
|
||||||
|
Move move = new Move(Position.getSquare(1, 6), Position.getSquare(0,7), Piece.WQUEEN);
|
||||||
|
UndoInfo ui = new UndoInfo();
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(1,6)));
|
||||||
|
assertEquals(Piece.WQUEEN, pos.getPiece(Position.getSquare(0,7)));
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
assertEquals(origPos, pos);
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(1, 6), Position.getSquare(1,7), Piece.WKNIGHT);
|
||||||
|
ui = new UndoInfo();
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(1,6)));
|
||||||
|
assertEquals(Piece.WKNIGHT, pos.getPiece(Position.getSquare(1,7)));
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
assertEquals(origPos, pos);
|
||||||
|
|
||||||
|
pos.setWhiteMove(false);
|
||||||
|
origPos = new Position(pos);
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(1, 1), Position.getSquare(2, 0), Piece.BROOK);
|
||||||
|
ui = new UndoInfo();
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(1,1)));
|
||||||
|
assertEquals(Piece.BROOK, pos.getPiece(Position.getSquare(2,0)));
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
assertEquals(origPos, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test move counters, of class Position.
|
||||||
|
*/
|
||||||
|
public void testMoveCounters() throws ChessParseError {
|
||||||
|
String fen = "r1bqk2r/2ppbppp/p1n2n2/1pP1p3/B3P3/5N2/PP1P1PPP/RNBQK2R w KQkq b6 0 7";
|
||||||
|
Position pos = TextIO.readFEN(fen);
|
||||||
|
|
||||||
|
Move move = TextIO.stringToMove(pos, "Nc3");
|
||||||
|
UndoInfo ui = new UndoInfo();
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(1, pos.halfMoveClock);
|
||||||
|
assertEquals(7, pos.fullMoveCounter);
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
|
||||||
|
move = TextIO.stringToMove(pos, "O-O");
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(1, pos.halfMoveClock); // Castling does not reset 50 move counter
|
||||||
|
assertEquals(7, pos.fullMoveCounter);
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
|
||||||
|
move = TextIO.stringToMove(pos, "a3");
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(0, pos.halfMoveClock); // Pawn move resets 50 move counter
|
||||||
|
assertEquals(7, pos.fullMoveCounter);
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
|
||||||
|
move = TextIO.stringToMove(pos, "Nxe5");
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(0, pos.halfMoveClock); // Capture move resets 50 move counter
|
||||||
|
assertEquals(7, pos.fullMoveCounter);
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
|
||||||
|
move = TextIO.stringToMove(pos, "cxb6");
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(0, pos.halfMoveClock); // EP capture move resets 50 move counter
|
||||||
|
assertEquals(7, pos.fullMoveCounter);
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
|
||||||
|
move = TextIO.stringToMove(pos, "Kf1");
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(1, pos.halfMoveClock); // Loss of castling rights does not reset 50 move counter
|
||||||
|
assertEquals(7, pos.fullMoveCounter);
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
|
||||||
|
Move firstMove = TextIO.stringToMove(pos, "Nc3");
|
||||||
|
UndoInfo firstUi = new UndoInfo();
|
||||||
|
pos.makeMove(move, firstUi);
|
||||||
|
move = TextIO.stringToMove(pos, "O-O");
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(2, pos.halfMoveClock);
|
||||||
|
assertEquals(8, pos.fullMoveCounter); // Black move increases fullMoveCounter
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
pos.unMakeMove(firstMove, firstUi);
|
||||||
|
|
||||||
|
fen = "8/8/8/4k3/8/8/2p5/5K2 b - - 47 68";
|
||||||
|
pos = TextIO.readFEN(fen);
|
||||||
|
move = TextIO.stringToMove(pos, "c1Q");
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertEquals(0, pos.halfMoveClock); // Pawn promotion resets 50 move counter
|
||||||
|
assertEquals(69, pos.fullMoveCounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of drawRuleEquals, of class Position.
|
||||||
|
*/
|
||||||
|
public void testDrawRuleEquals() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
Position origPos = new Position(pos);
|
||||||
|
UndoInfo ui = new UndoInfo();
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Nf3"), ui);
|
||||||
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Nf6"), ui);
|
||||||
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Ng1"), ui);
|
||||||
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Ng8"), ui);
|
||||||
|
assertEquals(true, pos.drawRuleEquals(origPos));
|
||||||
|
assertEquals(false, pos.equals(origPos)); // Move counters have changed
|
||||||
|
|
||||||
|
String fen = "r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 0 1";
|
||||||
|
pos = TextIO.readFEN(fen);
|
||||||
|
origPos = new Position(pos);
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Ke2"), ui);
|
||||||
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Be7"), ui);
|
||||||
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Ke1"), ui);
|
||||||
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Bf8"), ui);
|
||||||
|
assertEquals(false, pos.drawRuleEquals(origPos)); // Not equal, castling rights lost
|
||||||
|
|
||||||
|
pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "c4"), ui);
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "a6"), ui);
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "c5"), ui);
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "b5"), ui);
|
||||||
|
assertEquals(Position.getSquare(1, 5), pos.getEpSquare());
|
||||||
|
origPos = new Position(pos);
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Nc3"), ui);
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Nc6"), ui);
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Nb1"), ui);
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Nb8"), ui);
|
||||||
|
assertEquals(false, pos.drawRuleEquals(origPos)); // Not equal, en passant rights lost
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of hashCode method, of class Position.
|
||||||
|
*/
|
||||||
|
public void testHashCode() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
long h1 = pos.zobristHash();
|
||||||
|
assertEquals(h1, pos.computeZobristHash());
|
||||||
|
UndoInfo ui = new UndoInfo();
|
||||||
|
Move move = TextIO.stringToMove(pos, "e4");
|
||||||
|
pos.makeMove(move, ui);
|
||||||
|
assertTrue(h1 != pos.zobristHash());
|
||||||
|
pos.unMakeMove(move, ui);
|
||||||
|
assertTrue(h1 == pos.zobristHash());
|
||||||
|
|
||||||
|
pos.setWhiteMove(!pos.whiteMove);
|
||||||
|
long h4 = pos.zobristHash();
|
||||||
|
assertEquals(h4, pos.computeZobristHash());
|
||||||
|
assertTrue(h1 != pos.zobristHash());
|
||||||
|
pos.setWhiteMove(!pos.whiteMove);
|
||||||
|
assertTrue(h1 == pos.zobristHash());
|
||||||
|
|
||||||
|
pos.setCastleMask(0);
|
||||||
|
assertTrue(h1 != pos.zobristHash());
|
||||||
|
|
||||||
|
pos = TextIO.readFEN("rnbqkbnr/pppp1ppp/8/2P1p3/8/8/PP1PPPPP/RNBQKBNR b KQkq - 0 1");
|
||||||
|
h1 = pos.zobristHash();
|
||||||
|
assertEquals(h1, pos.computeZobristHash());
|
||||||
|
|
||||||
|
String[] moves = {
|
||||||
|
"b5", "Nc3", "Nf6", "Nb1", "Ng8", "Nc3", "Nf6", "Nb1", "Ng8", "Nc3", "d5",
|
||||||
|
"cxd6", "Qxd6", "h4", "Be6", "h5", "Nc6", "h6", "o-o-o", "hxg7", "Nf6", "gxh8Q", "Be7"
|
||||||
|
};
|
||||||
|
List<UndoInfo> uiList = new ArrayList<UndoInfo>();
|
||||||
|
List<Long> hashList = new ArrayList<Long>();
|
||||||
|
List<Move> moveList = new ArrayList<Move>();
|
||||||
|
for (int i = 0; i < moves.length; i++) {
|
||||||
|
uiList.add(new UndoInfo());
|
||||||
|
Move m = TextIO.stringToMove(pos, moves[i]);
|
||||||
|
moveList.add(m);
|
||||||
|
pos.makeMove(m, uiList.get(i));
|
||||||
|
long h = pos.zobristHash();
|
||||||
|
assertEquals(h, pos.computeZobristHash());
|
||||||
|
hashList.add(h);
|
||||||
|
}
|
||||||
|
assertTrue(!hashList.get(0).equals(hashList.get(4)));
|
||||||
|
assertTrue(hashList.get(4).equals(hashList.get(8)));
|
||||||
|
for (int i = moves.length - 1; i >= 0; i--) {
|
||||||
|
pos.unMakeMove(moveList.get(i), uiList.get(i));
|
||||||
|
long h = pos.zobristHash();
|
||||||
|
assertEquals(h, pos.computeZobristHash());
|
||||||
|
assertEquals(h, i > 0 ? hashList.get(i - 1) : h1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getKingSq method, of class Position.
|
||||||
|
*/
|
||||||
|
public void testGetKingSq() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
assertEquals(TextIO.getSquare("e1"), pos.getKingSq(true));
|
||||||
|
assertEquals(TextIO.getSquare("e8"), pos.getKingSq(false));
|
||||||
|
pos = TextIO.readFEN("r1bq1bnr/ppppkppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R w KQ - 0 4");
|
||||||
|
assertEquals(TextIO.getSquare("e1"), pos.getKingSq(true));
|
||||||
|
assertEquals(TextIO.getSquare("e7"), pos.getKingSq(false));
|
||||||
|
UndoInfo ui = new UndoInfo();
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "o-o"), ui);
|
||||||
|
assertEquals(TextIO.getSquare("g1"), pos.getKingSq(true));
|
||||||
|
assertEquals(TextIO.getSquare("e7"), pos.getKingSq(false));
|
||||||
|
pos.makeMove(TextIO.stringToMove(pos, "Kd6"), ui);
|
||||||
|
assertEquals(TextIO.getSquare("g1"), pos.getKingSq(true));
|
||||||
|
assertEquals(TextIO.getSquare("d6"), pos.getKingSq(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNullMove() throws ChessParseError {
|
||||||
|
Move nullMove = new Move(0, 0, 0);
|
||||||
|
UndoInfo ui = new UndoInfo();
|
||||||
|
|
||||||
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
Position origPos = new Position(pos);
|
||||||
|
pos.makeMove(nullMove, ui);
|
||||||
|
assertEquals(false, pos.whiteMove);
|
||||||
|
assertEquals(true, pos.a1Castle());
|
||||||
|
assertEquals(Piece.WROOK, pos.getPiece(0));
|
||||||
|
pos.unMakeMove(nullMove, ui);
|
||||||
|
assertTrue(pos.equals(origPos));
|
||||||
|
|
||||||
|
pos = TextIO.readFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w Kkq - 5 1");
|
||||||
|
origPos = new Position(pos);
|
||||||
|
pos.makeMove(nullMove, ui);
|
||||||
|
assertEquals(false, pos.whiteMove);
|
||||||
|
assertEquals(false, pos.a1Castle());
|
||||||
|
assertEquals(Piece.WROOK, pos.getPiece(0));
|
||||||
|
assertEquals(0, pos.halfMoveClock);
|
||||||
|
pos.unMakeMove(nullMove, ui);
|
||||||
|
assertTrue(pos.equals(origPos));
|
||||||
|
|
||||||
|
pos = TextIO.readFEN("7k/8/8/8/8/8/4P3/K7 w - - 5 1");
|
||||||
|
origPos = new Position(pos);
|
||||||
|
pos.makeMove(nullMove, ui);
|
||||||
|
assertEquals(false, pos.whiteMove);
|
||||||
|
assertEquals(false, pos.a1Castle());
|
||||||
|
assertEquals(0, pos.halfMoveClock);
|
||||||
|
assertEquals(0, pos.getKingSq(true));
|
||||||
|
assertEquals(63, pos.getKingSq(false));
|
||||||
|
|
||||||
|
UndoInfo ui2 = new UndoInfo();
|
||||||
|
pos.makeMove(nullMove, ui2);
|
||||||
|
assertEquals(true, pos.whiteMove);
|
||||||
|
assertEquals(false, pos.a1Castle());
|
||||||
|
assertEquals(0, pos.halfMoveClock);
|
||||||
|
assertEquals(0, pos.getKingSq(true));
|
||||||
|
assertEquals(63, pos.getKingSq(false));
|
||||||
|
|
||||||
|
pos.unMakeMove(nullMove, ui2);
|
||||||
|
assertEquals(false, pos.whiteMove);
|
||||||
|
assertEquals(false, pos.a1Castle());
|
||||||
|
assertEquals(0, pos.halfMoveClock);
|
||||||
|
assertEquals(0, pos.getKingSq(true));
|
||||||
|
assertEquals(63, pos.getKingSq(false));
|
||||||
|
|
||||||
|
pos.unMakeMove(nullMove, ui);
|
||||||
|
assertTrue(pos.equals(origPos));
|
||||||
|
|
||||||
|
pos = TextIO.readFEN("5k2/8/4R1K1/8/8/8/8/8 b - - 5 1");
|
||||||
|
origPos = new Position(pos);
|
||||||
|
pos.makeMove(nullMove, ui);
|
||||||
|
assertEquals(true, pos.whiteMove);
|
||||||
|
assertEquals(false, pos.a1Castle());
|
||||||
|
assertEquals(0, pos.halfMoveClock);
|
||||||
|
|
||||||
|
pos.unMakeMove(nullMove, ui);
|
||||||
|
assertTrue(pos.equals(origPos));
|
||||||
|
}
|
||||||
|
}
|
382
DroidFishTest/src/org/petero/droidfish/gamelogic/TextIOTest.java
Normal file
382
DroidFishTest/src/org/petero/droidfish/gamelogic/TextIOTest.java
Normal file
|
@ -0,0 +1,382 @@
|
||||||
|
/*
|
||||||
|
DroidFish - An Android chess program.
|
||||||
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.petero.droidfish.gamelogic;
|
||||||
|
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author petero
|
||||||
|
*/
|
||||||
|
public class TextIOTest extends TestCase {
|
||||||
|
|
||||||
|
public TextIOTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of readFEN method, of class TextIO.
|
||||||
|
*/
|
||||||
|
public void testReadFEN() throws ChessParseError {
|
||||||
|
String fen = "rnbqk2r/1p3ppp/p7/1NpPp3/QPP1P1n1/P4N2/4KbPP/R1B2B1R b kq - 0 1";
|
||||||
|
Position pos = TextIO.readFEN(fen);
|
||||||
|
assertEquals(fen, TextIO.toFEN(pos));
|
||||||
|
assertEquals(pos.getPiece(Position.getSquare(0, 3)), Piece.WQUEEN);
|
||||||
|
assertEquals(pos.getPiece(Position.getSquare(4, 7)), Piece.BKING);
|
||||||
|
assertEquals(pos.getPiece(Position.getSquare(4, 1)), Piece.WKING);
|
||||||
|
assertEquals(pos.whiteMove, false);
|
||||||
|
assertEquals(pos.a1Castle(), false);
|
||||||
|
assertEquals(pos.h1Castle(), false);
|
||||||
|
assertEquals(pos.a8Castle(), true);
|
||||||
|
assertEquals(pos.h8Castle(), true);
|
||||||
|
|
||||||
|
fen = "8/3k4/8/5pP1/1P6/1NB5/2QP4/R3K2R w KQ f6 1 2";
|
||||||
|
pos = TextIO.readFEN(fen);
|
||||||
|
assertEquals(fen, TextIO.toFEN(pos));
|
||||||
|
assertEquals(1, pos.halfMoveClock);
|
||||||
|
assertEquals(2, pos.fullMoveCounter);
|
||||||
|
|
||||||
|
// Must have exactly one king
|
||||||
|
boolean wasError = testFENParseError("8/8/8/8/8/8/8/kk1K4 w - - 0 1");
|
||||||
|
assertEquals(true, wasError);
|
||||||
|
|
||||||
|
// Must not be possible to capture the king
|
||||||
|
wasError = testFENParseError("8/8/8/8/8/8/8/k1RK4 w - - 0 1");
|
||||||
|
assertEquals(true, wasError);
|
||||||
|
|
||||||
|
// Make sure bogus en passant square information is removed
|
||||||
|
fen = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1";
|
||||||
|
pos = TextIO.readFEN(fen);
|
||||||
|
assertEquals(-1, pos.getEpSquare());
|
||||||
|
|
||||||
|
// Test for too many rows (slashes)
|
||||||
|
wasError = testFENParseError("8/8/8/8/4k3/8/8/8/KBN5 w - - 0 1");
|
||||||
|
assertEquals(true, wasError);
|
||||||
|
|
||||||
|
// Test for too many columns
|
||||||
|
wasError = testFENParseError("8K/8/8/8/4k3/8/8/8 w - - 0 1");
|
||||||
|
assertEquals(true, wasError);
|
||||||
|
|
||||||
|
// Pawns must not be on first/last rank
|
||||||
|
wasError = testFENParseError("kp6/8/8/8/8/8/8/K7 w - - 0 1");
|
||||||
|
assertEquals(true, wasError);
|
||||||
|
|
||||||
|
wasError = testFENParseError("kr/pppp/8/8/8/8/8/KBR w");
|
||||||
|
assertEquals(false, wasError); // OK not to specify castling flags and ep square
|
||||||
|
|
||||||
|
wasError = testFENParseError("k/8/8/8/8/8/8/K");
|
||||||
|
assertEquals(true, wasError); // Error side to move not specified
|
||||||
|
|
||||||
|
wasError = testFENParseError("");
|
||||||
|
assertEquals(true, wasError);
|
||||||
|
|
||||||
|
wasError = testFENParseError(" |");
|
||||||
|
assertEquals(true, wasError);
|
||||||
|
|
||||||
|
wasError = testFENParseError("1B1B4/6k1/7r/7P/6q1/r7/q7/7K b - - acn 6; acs 0;");
|
||||||
|
assertEquals(false, wasError); // Extra stuff after FEN string is allowed
|
||||||
|
|
||||||
|
pos = TextIO.readFEN("3r2k1/p4p1p/1ppq2p1/8/2PpQ3/1P5P/P4PP1/3R1K2 b - - 1 26\n");
|
||||||
|
assertEquals(26, pos.fullMoveCounter);
|
||||||
|
|
||||||
|
// Test that insane move numbers are rejected. Otherwise, could cause problems
|
||||||
|
// (excessive memory usage) for the clock history class.
|
||||||
|
pos = TextIO.readFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 10000");
|
||||||
|
assertEquals(10000, pos.fullMoveCounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that readFEN removes bogus castle flags.
|
||||||
|
*/
|
||||||
|
public void testReadFENCastleFlags() throws ChessParseError {
|
||||||
|
String fenBogus = "rnbqk2r/1p3ppp/p7/1NpPp3/QPP1P1n1/P4N2/4KbPP/R1B2B1R w KQkq - 0 1";
|
||||||
|
Position pos = TextIO.readFEN(fenBogus);
|
||||||
|
String fenCorrect = "rnbqk2r/1p3ppp/p7/1NpPp3/QPP1P1n1/P4N2/4KbPP/R1B2B1R w kq - 0 1";
|
||||||
|
assertEquals(fenCorrect, TextIO.toFEN(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tests if trying to parse a FEN string causes an error. */
|
||||||
|
private boolean testFENParseError(String fen) {
|
||||||
|
boolean wasError;
|
||||||
|
wasError = false;
|
||||||
|
try {
|
||||||
|
TextIO.readFEN(fen);
|
||||||
|
} catch (ChessParseError err) {
|
||||||
|
wasError = true;
|
||||||
|
}
|
||||||
|
return wasError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of moveToString method, of class TextIO.
|
||||||
|
*/
|
||||||
|
public void testMoveToString() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
assertEquals(TextIO.startPosFEN, TextIO.toFEN(pos));
|
||||||
|
Move move = new Move(Position.getSquare(4, 1), Position.getSquare(4, 3),
|
||||||
|
Piece.EMPTY);
|
||||||
|
boolean longForm = true;
|
||||||
|
String result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("e2-e4", result);
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(6, 0), Position.getSquare(5, 2), Piece.EMPTY);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("Ng1-f3", result);
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(4, 7), Position.getSquare(2, 7),
|
||||||
|
Piece.EMPTY);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("O-O-O", result);
|
||||||
|
|
||||||
|
String fen = "1r3k2/2P5/8/8/8/4K3/8/8 w - - 0 1";
|
||||||
|
pos = TextIO.readFEN(fen);
|
||||||
|
assertEquals(fen, TextIO.toFEN(pos));
|
||||||
|
move = new Move(Position.getSquare(2,6), Position.getSquare(1,7), Piece.WROOK);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("c7xb8R+", result);
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(2,6), Position.getSquare(2,7), Piece.WKNIGHT);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("c7-c8N", result);
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(2,6), Position.getSquare(2,7), Piece.WQUEEN);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("c7-c8Q+", result);
|
||||||
|
|
||||||
|
// Test null move
|
||||||
|
pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
Move nullMove = new Move(0, 0, 0);
|
||||||
|
result = TextIO.moveToString(pos, nullMove, false);
|
||||||
|
assertEquals("--", result);
|
||||||
|
result = TextIO.moveToString(pos, nullMove, true);
|
||||||
|
assertEquals("--", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of moveToString method, of class TextIO, mate/stalemate tests.
|
||||||
|
*/
|
||||||
|
public void testMoveToStringMate() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN("3k4/1PR5/3N4/8/4K3/8/8/8 w - - 0 1");
|
||||||
|
boolean longForm = true;
|
||||||
|
|
||||||
|
Move move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WROOK);
|
||||||
|
String result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("b7-b8R+", result); // check
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WQUEEN);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("b7-b8Q#", result); // check mate
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WKNIGHT);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("b7-b8N", result);
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WBISHOP);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("b7-b8B", result); // stalemate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of moveToString method, of class TextIO, short form.
|
||||||
|
*/
|
||||||
|
public void testMoveToStringShortForm() throws ChessParseError {
|
||||||
|
String fen = "r4rk1/2pn3p/2q1q1n1/8/2q2p2/6R1/p4PPP/1R4K1 b - - 0 1";
|
||||||
|
Position pos = TextIO.readFEN(fen);
|
||||||
|
assertEquals(fen, TextIO.toFEN(pos));
|
||||||
|
boolean longForm = false;
|
||||||
|
|
||||||
|
Move move = new Move(Position.getSquare(4,5), Position.getSquare(4,3), Piece.EMPTY);
|
||||||
|
String result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("Qee4", result); // File disambiguation needed
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(2,5), Position.getSquare(4,3), Piece.EMPTY);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("Qc6e4", result); // Full disambiguation needed
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(2,3), Position.getSquare(4,3), Piece.EMPTY);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("Q4e4", result); // Row disambiguation needed
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(2,3), Position.getSquare(2,0), Piece.EMPTY);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("Qc1+", result); // No disambiguation needed
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(0,1), Position.getSquare(0,0), Piece.BQUEEN);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("a1Q", result); // Normal promotion
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(0,1), Position.getSquare(1,0), Piece.BQUEEN);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("axb1Q#", result); // Capture promotion and check mate
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(0,1), Position.getSquare(1,0), Piece.BKNIGHT);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("axb1N", result); // Capture promotion
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(3,6), Position.getSquare(4,4), Piece.EMPTY);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("Ne5", result); // Other knight pinned, no disambiguation needed
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(7,6), Position.getSquare(7,4), Piece.EMPTY);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("h5", result); // Regular pawn move
|
||||||
|
|
||||||
|
move = new Move(Position.getSquare(5,7), Position.getSquare(3,7), Piece.EMPTY);
|
||||||
|
result = TextIO.moveToString(pos, move, longForm);
|
||||||
|
assertEquals("Rfd8", result); // File disambiguation needed
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of stringToMove method, of class TextIO.
|
||||||
|
*/
|
||||||
|
public void testStringToMove() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN("r4rk1/2pn3p/2q1q1n1/8/2q2p2/6R1/p4PPP/1R4K1 b - - 0 1");
|
||||||
|
|
||||||
|
Move mNe5 = new Move(Position.getSquare(3, 6), Position.getSquare(4, 4), Piece.EMPTY);
|
||||||
|
Move m = TextIO.stringToMove(pos, "Ne5");
|
||||||
|
assertEquals(mNe5, m);
|
||||||
|
m = TextIO.stringToMove(pos, "ne");
|
||||||
|
assertEquals(mNe5, m);
|
||||||
|
m = TextIO.stringToMove(pos, "N");
|
||||||
|
assertEquals(null, m);
|
||||||
|
|
||||||
|
Move mQc6e4 = new Move(Position.getSquare(2, 5), Position.getSquare(4, 3), Piece.EMPTY);
|
||||||
|
m = TextIO.stringToMove(pos, "Qc6-e4");
|
||||||
|
assertEquals(mQc6e4, m);
|
||||||
|
m = TextIO.stringToMove(pos, "Qc6e4");
|
||||||
|
assertEquals(mQc6e4, m);
|
||||||
|
m = TextIO.stringToMove(pos, "Qce4");
|
||||||
|
assertEquals(null, m);
|
||||||
|
m = TextIO.stringToMove(pos, "Q6e4");
|
||||||
|
assertEquals(null, m);
|
||||||
|
|
||||||
|
Move maxb1Q = new Move(Position.getSquare(0, 1), Position.getSquare(1, 0), Piece.BQUEEN);
|
||||||
|
m = TextIO.stringToMove(pos, "axb1Q");
|
||||||
|
assertEquals(maxb1Q, m);
|
||||||
|
m = TextIO.stringToMove(pos, "axb1Q#");
|
||||||
|
assertEquals(maxb1Q, m);
|
||||||
|
m = TextIO.stringToMove(pos, "axb1Q+");
|
||||||
|
assertEquals(maxb1Q, m);
|
||||||
|
|
||||||
|
Move mh5= new Move(Position.getSquare(7, 6), Position.getSquare(7, 4), Piece.EMPTY);
|
||||||
|
m = TextIO.stringToMove(pos, "h5");
|
||||||
|
assertEquals(mh5, m);
|
||||||
|
m = TextIO.stringToMove(pos, "h7-h5");
|
||||||
|
assertEquals(mh5, m);
|
||||||
|
m = TextIO.stringToMove(pos, "h");
|
||||||
|
assertEquals(null, m);
|
||||||
|
|
||||||
|
pos = TextIO.readFEN("r1b1k2r/1pqpppbp/p5pn/3BP3/8/2pP4/PPPBQPPP/R3K2R w KQkq - 0 12");
|
||||||
|
m = TextIO.stringToMove(pos, "bxc3");
|
||||||
|
assertEquals(TextIO.getSquare("b2"), m.from);
|
||||||
|
m = TextIO.stringToMove(pos, "Bxc3");
|
||||||
|
assertEquals(TextIO.getSquare("d2"), m.from);
|
||||||
|
m = TextIO.stringToMove(pos, "bxc");
|
||||||
|
assertEquals(TextIO.getSquare("b2"), m.from);
|
||||||
|
m = TextIO.stringToMove(pos, "Bxc");
|
||||||
|
assertEquals(TextIO.getSquare("d2"), m.from);
|
||||||
|
|
||||||
|
// Test castling. o-o is a substring of o-o-o, which could cause problems.
|
||||||
|
pos = TextIO.readFEN("5k2/p1pQn3/1p2Bp1r/8/4P1pN/2N5/PPP2PPP/R3K2R w KQ - 0 16");
|
||||||
|
Move kCastle = new Move(Position.getSquare(4,0), Position.getSquare(6,0), Piece.EMPTY);
|
||||||
|
Move qCastle = new Move(Position.getSquare(4,0), Position.getSquare(2,0), Piece.EMPTY);
|
||||||
|
m = TextIO.stringToMove(pos, "o");
|
||||||
|
assertEquals(null, m);
|
||||||
|
m = TextIO.stringToMove(pos, "o-o");
|
||||||
|
assertEquals(kCastle, m);
|
||||||
|
m = TextIO.stringToMove(pos, "O-O");
|
||||||
|
assertEquals(kCastle, m);
|
||||||
|
m = TextIO.stringToMove(pos, "0-0");
|
||||||
|
assertEquals(kCastle, m);
|
||||||
|
m = TextIO.stringToMove(pos, "O-O-O");
|
||||||
|
assertEquals(qCastle, m);
|
||||||
|
m = TextIO.stringToMove(pos, "o-o-o");
|
||||||
|
assertEquals(qCastle, m);
|
||||||
|
m = TextIO.stringToMove(pos, "0-0-0");
|
||||||
|
assertEquals(qCastle, m);
|
||||||
|
|
||||||
|
// Test 'o-o+'
|
||||||
|
pos.setPiece(Position.getSquare(5,1), Piece.EMPTY);
|
||||||
|
pos.setPiece(Position.getSquare(5,5), Piece.EMPTY);
|
||||||
|
m = TextIO.stringToMove(pos, "o");
|
||||||
|
assertEquals(null, m);
|
||||||
|
m = TextIO.stringToMove(pos, "o-o");
|
||||||
|
assertEquals(kCastle, m);
|
||||||
|
m = TextIO.stringToMove(pos, "o-o-o");
|
||||||
|
assertEquals(qCastle, m);
|
||||||
|
m = TextIO.stringToMove(pos, "o-o+");
|
||||||
|
assertEquals(kCastle, m);
|
||||||
|
|
||||||
|
// Test d8=Q+ syntax
|
||||||
|
pos = TextIO.readFEN("1r3r2/2kP2Rp/p1bN1p2/2p5/5P2/2P5/P5PP/3R2K1 w - -");
|
||||||
|
m = TextIO.stringToMove(pos, "d8=Q+");
|
||||||
|
Move m2 = TextIO.stringToMove(pos, "d8Q");
|
||||||
|
assertEquals(m2, m);
|
||||||
|
|
||||||
|
// Test null move
|
||||||
|
pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
Move nullMove = new Move(0, 0, 0);
|
||||||
|
m = TextIO.stringToMove(pos, "--");
|
||||||
|
assertEquals(nullMove, m);
|
||||||
|
|
||||||
|
// Test extra characters
|
||||||
|
pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||||
|
Move mNf3 = new Move(TextIO.getSquare("g1"), TextIO.getSquare("f3"), Piece.EMPTY);
|
||||||
|
assertEquals(mNf3, TextIO.stringToMove(pos, "Ngf3"));
|
||||||
|
assertEquals(mNf3, TextIO.stringToMove(pos, "Ng1f3"));
|
||||||
|
assertEquals(mNf3, TextIO.stringToMove(pos, "Ng1-f3"));
|
||||||
|
assertEquals(mNf3, TextIO.stringToMove(pos, "g1f3"));
|
||||||
|
assertEquals(mNf3, TextIO.stringToMove(pos, "N1f3"));
|
||||||
|
assertEquals(mNf3, TextIO.stringToMove(pos, "Ngf"));
|
||||||
|
assertEquals(mNf3, TextIO.stringToMove(pos, "Nf"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getSquare method, of class TextIO.
|
||||||
|
*/
|
||||||
|
public void testGetSquare() throws ChessParseError {
|
||||||
|
assertEquals(Position.getSquare(0, 0), TextIO.getSquare("a1"));
|
||||||
|
assertEquals(Position.getSquare(1, 7), TextIO.getSquare("b8"));
|
||||||
|
assertEquals(Position.getSquare(3, 3), TextIO.getSquare("d4"));
|
||||||
|
assertEquals(Position.getSquare(4, 3), TextIO.getSquare("e4"));
|
||||||
|
assertEquals(Position.getSquare(3, 1), TextIO.getSquare("d2"));
|
||||||
|
assertEquals(Position.getSquare(7, 7), TextIO.getSquare("h8"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of squareToString method, of class TextIO.
|
||||||
|
*/
|
||||||
|
public void testSquareToString() {
|
||||||
|
assertEquals("a1", TextIO.squareToString(Position.getSquare(0, 0)));
|
||||||
|
assertEquals("h6", TextIO.squareToString(Position.getSquare(7, 5)));
|
||||||
|
assertEquals("e4", TextIO.squareToString(Position.getSquare(4, 3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of asciiBoard method, of class TextIO.
|
||||||
|
*/
|
||||||
|
public void testAsciiBoard() throws ChessParseError {
|
||||||
|
Position pos = TextIO.readFEN("r4rk1/2pn3p/2q1q1n1/8/2q2p2/6R1/p4PPP/1R4K1 b - - 0 1");
|
||||||
|
String aBrd = TextIO.asciiBoard(pos);
|
||||||
|
// System.out.print(aBrd);
|
||||||
|
assertEquals(12, aBrd.length() - aBrd.replaceAll("\\*", "").length()); // 12 black pieces
|
||||||
|
assertEquals(3, aBrd.length() - aBrd.replaceAll("\\*Q", " ").length()); // 3 black queens
|
||||||
|
assertEquals(3, aBrd.length() - aBrd.replaceAll(" P", " ").length()); // 3 white pawns
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
DroidFish - An Android chess program.
|
||||||
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.petero.droidfish.gamelogic;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
|
||||||
|
public class TimeControlTest extends TestCase {
|
||||||
|
public TimeControlTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testElapsedTime() {
|
||||||
|
TimeControl tc = new TimeControl();
|
||||||
|
long totTime = 5 * 60 * 1000;
|
||||||
|
long t0 = 1000;
|
||||||
|
tc.setTimeControl(totTime, 0, 0);
|
||||||
|
tc.setCurrentMove(1, true, totTime, totTime);
|
||||||
|
assertEquals(0, tc.getMovesToTC());
|
||||||
|
assertEquals(0, tc.getIncrement());
|
||||||
|
assertEquals(totTime, tc.getRemainingTime(true, 0));
|
||||||
|
tc.startTimer(t0);
|
||||||
|
int remain = tc.moveMade(t0 + 1000, true);
|
||||||
|
assertEquals(totTime - 1000, remain);
|
||||||
|
|
||||||
|
tc.setCurrentMove(2, true, totTime - 1000, totTime);
|
||||||
|
assertEquals(0, tc.getMovesToTC());
|
||||||
|
assertEquals(totTime - 1000, tc.getRemainingTime(true, t0 + 4711));
|
||||||
|
assertEquals(totTime, tc.getRemainingTime(false, t0 + 4711));
|
||||||
|
|
||||||
|
tc.setCurrentMove(1, false, totTime - 1000, totTime);
|
||||||
|
assertEquals(0, tc.getMovesToTC());
|
||||||
|
assertEquals(totTime - 1000, tc.getRemainingTime(true, t0 + 4711));
|
||||||
|
assertEquals(totTime, tc.getRemainingTime(false, t0 + 4711));
|
||||||
|
|
||||||
|
tc.startTimer(t0 + 3000);
|
||||||
|
assertEquals(totTime - 1000, tc.getRemainingTime(true, t0 + 5000));
|
||||||
|
assertEquals(totTime - 2000, tc.getRemainingTime(false, t0 + 5000));
|
||||||
|
tc.stopTimer(t0 + 8000);
|
||||||
|
assertEquals(totTime - 1000, tc.getRemainingTime(true, t0 + 4711));
|
||||||
|
assertEquals(totTime - 5000, tc.getRemainingTime(false, t0 + 4711));
|
||||||
|
remain = tc.moveMade(t0 + 8000, true);
|
||||||
|
assertEquals(totTime - 5000, remain);
|
||||||
|
tc.setCurrentMove(2, true, totTime - 1000, totTime - 5000);
|
||||||
|
assertEquals(totTime - 1000, tc.getRemainingTime(true, t0 + 4711));
|
||||||
|
assertEquals(totTime - 5000, tc.getRemainingTime(false, t0 + 4711));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Test getMovesToTC */
|
||||||
|
public void testTimeControl() {
|
||||||
|
TimeControl tc = new TimeControl();
|
||||||
|
tc.setTimeControl(2 * 60 * 1000, 40, 0);
|
||||||
|
tc.setCurrentMove(1, true, 0, 0);
|
||||||
|
assertEquals(40, tc.getMovesToTC());
|
||||||
|
tc.setCurrentMove(1, false, 0, 0);
|
||||||
|
assertEquals(40, tc.getMovesToTC());
|
||||||
|
|
||||||
|
tc.setCurrentMove(2, true, 0, 0);
|
||||||
|
assertEquals(39, tc.getMovesToTC());
|
||||||
|
|
||||||
|
tc.setCurrentMove(40, true, 0, 0);
|
||||||
|
assertEquals(1, tc.getMovesToTC());
|
||||||
|
|
||||||
|
tc.setCurrentMove(41, true, 0, 0);
|
||||||
|
assertEquals(40, tc.getMovesToTC());
|
||||||
|
|
||||||
|
tc.setCurrentMove(80, true, 0, 0);
|
||||||
|
assertEquals(1, tc.getMovesToTC());
|
||||||
|
|
||||||
|
tc.setCurrentMove(81, true, 0, 0);
|
||||||
|
assertEquals(40, tc.getMovesToTC());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExtraTime() {
|
||||||
|
TimeControl tc = new TimeControl();
|
||||||
|
final long timeCont = 60 * 1000;
|
||||||
|
int wBaseTime = (int)timeCont;
|
||||||
|
int bBaseTime = (int)timeCont;
|
||||||
|
final long inc = 700;
|
||||||
|
tc.setTimeControl(timeCont, 5, inc);
|
||||||
|
tc.setCurrentMove(5, true, wBaseTime, bBaseTime);
|
||||||
|
long t0 = 1342134;
|
||||||
|
assertEquals(timeCont, tc.getRemainingTime(true, t0 + 4711));
|
||||||
|
assertEquals(timeCont, tc.getRemainingTime(false, t0 + 4711));
|
||||||
|
|
||||||
|
tc.startTimer(t0 + 1000);
|
||||||
|
wBaseTime = tc.moveMade(t0 + 2000, true);
|
||||||
|
tc.setCurrentMove(5, false, wBaseTime, bBaseTime);
|
||||||
|
assertEquals(timeCont - 1000 + timeCont + inc, tc.getRemainingTime(true, t0 + 4711));
|
||||||
|
assertEquals(timeCont, tc.getRemainingTime(false, t0 + 4711));
|
||||||
|
|
||||||
|
tc.startTimer(t0 + 2000);
|
||||||
|
bBaseTime = tc.moveMade(t0 + 6000, true);
|
||||||
|
tc.setCurrentMove(6, true, wBaseTime, bBaseTime);
|
||||||
|
assertEquals(timeCont - 1000 + timeCont + inc, tc.getRemainingTime(true, t0 + 4711));
|
||||||
|
assertEquals(timeCont - 4000 + timeCont + inc, tc.getRemainingTime(false, t0 + 4711));
|
||||||
|
|
||||||
|
tc.startTimer(t0 + 6000);
|
||||||
|
wBaseTime = tc.moveMade(t0 + 9000, true);
|
||||||
|
tc.setCurrentMove(6, false, wBaseTime, bBaseTime);
|
||||||
|
assertEquals(timeCont - 1000 + timeCont + inc - 3000 + inc, tc.getRemainingTime(true, t0 + 4711));
|
||||||
|
assertEquals(timeCont - 4000 + timeCont + inc, tc.getRemainingTime(false, t0 + 4711));
|
||||||
|
|
||||||
|
// No increment when move made int paused mode, ie analysis mode
|
||||||
|
tc.startTimer(t0 + 9000);
|
||||||
|
bBaseTime = tc.moveMade(t0 + 10000, false);
|
||||||
|
tc.setCurrentMove(7, true, wBaseTime, bBaseTime);
|
||||||
|
assertEquals(timeCont - 1000 + timeCont + inc - 3000 + inc, tc.getRemainingTime(true, t0 + 4711));
|
||||||
|
assertEquals(timeCont - 4000 + timeCont + inc - 1000, tc.getRemainingTime(false, t0 + 4711));
|
||||||
|
|
||||||
|
// No extra time when passing time control in analysis mode
|
||||||
|
tc.setTimeControl(timeCont, 1, inc);
|
||||||
|
wBaseTime = bBaseTime = (int)timeCont;
|
||||||
|
tc.setCurrentMove(1, true, wBaseTime, bBaseTime);
|
||||||
|
tc.startTimer(t0 + 1000);
|
||||||
|
wBaseTime = tc.moveMade(t0 + 3000, false);
|
||||||
|
tc.setCurrentMove(1, false, wBaseTime, bBaseTime);
|
||||||
|
assertEquals(timeCont - 2000 + (timeCont + inc)*0, tc.getRemainingTime(true, t0 + 4711));
|
||||||
|
assertEquals(timeCont, tc.getRemainingTime(false, t0 + 4711));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user