mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2024-11-27 14:15:16 +01:00
DroidFish: Added support for multiple time controls in the DroidChessController class.
This commit is contained in:
parent
8ef8fbe3cd
commit
da625e085d
|
@ -34,6 +34,7 @@ import org.petero.droidfish.engine.DroidComputerPlayer.SearchRequest;
|
|||
import org.petero.droidfish.engine.DroidComputerPlayer.SearchType;
|
||||
import org.petero.droidfish.gamelogic.Game.GameState;
|
||||
import org.petero.droidfish.gamelogic.GameTree.Node;
|
||||
import org.petero.droidfish.gamelogic.TimeControlData.TimeControlField;
|
||||
|
||||
/**
|
||||
* The glue between the chess engine and the GUI.
|
||||
|
@ -54,9 +55,7 @@ public class DroidChessController {
|
|||
private int strength = 1000;
|
||||
private int numPV = 1;
|
||||
|
||||
private int timeControl;
|
||||
private int movesPerSession;
|
||||
private int timeIncrement;
|
||||
private TimeControlData tcData;
|
||||
|
||||
private SearchListener listener;
|
||||
private boolean guiPaused = false;
|
||||
|
@ -72,6 +71,7 @@ public class DroidChessController {
|
|||
this.gameTextListener = gameTextListener;
|
||||
gameMode = new GameMode(GameMode.TWO_PLAYERS);
|
||||
pgnOptions = options;
|
||||
tcData = new TimeControlData();
|
||||
listener = new SearchListener();
|
||||
searchId = 0;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ public class DroidChessController {
|
|||
}
|
||||
computerPlayer.queueStartEngine(searchId, engine);
|
||||
searchId++;
|
||||
game = new Game(gameTextListener, timeControl, movesPerSession, timeIncrement);
|
||||
game = new Game(gameTextListener, tcData);
|
||||
computerPlayer.clearTT();
|
||||
setPlayerNames(game);
|
||||
updateGameMode();
|
||||
|
@ -105,11 +105,9 @@ public class DroidChessController {
|
|||
|
||||
/** Set time control parameters. */
|
||||
public final synchronized void setTimeLimit(int time, int moves, int inc) {
|
||||
timeControl = time;
|
||||
movesPerSession = moves;
|
||||
timeIncrement = inc;
|
||||
tcData.setTimeControl(time, moves, inc);
|
||||
if (game != null)
|
||||
game.timeController.setTimeControl(timeControl, movesPerSession, timeIncrement);
|
||||
game.timeController.setTimeControl(tcData);
|
||||
}
|
||||
|
||||
/** @return Array containing time control, moves per session and time increment. */
|
||||
|
@ -117,9 +115,10 @@ public class DroidChessController {
|
|||
if (game != null)
|
||||
return game.timeController.getTimeLimit(game.currPos().whiteMove);
|
||||
int[] ret = new int[3];
|
||||
ret[0] = timeControl;
|
||||
ret[1] = movesPerSession;
|
||||
ret[2] = timeIncrement;
|
||||
TimeControlField tc = tcData.getTC(true).get(0);
|
||||
ret[0] = (int)tc.timeControl;
|
||||
ret[1] = tc.movesPerSession;
|
||||
ret[2] = (int)tc.increment;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -237,7 +236,7 @@ public class DroidChessController {
|
|||
|
||||
/** Parse a string as FEN or PGN data. */
|
||||
public final synchronized void setFENOrPGN(String fenPgn) throws ChessParseError {
|
||||
Game newGame = new Game(gameTextListener, timeControl, movesPerSession, timeIncrement);
|
||||
Game newGame = new Game(gameTextListener, tcData);
|
||||
try {
|
||||
Position pos = TextIO.readFEN(fenPgn);
|
||||
newGame.setPos(pos);
|
||||
|
|
|
@ -38,12 +38,11 @@ public class Game {
|
|||
|
||||
PgnToken.PgnTokenReceiver gameTextListener;
|
||||
|
||||
public Game(PgnToken.PgnTokenReceiver gameTextListener,
|
||||
int timeControl, int movesPerSession, int timeIncrement) {
|
||||
public Game(PgnToken.PgnTokenReceiver gameTextListener, TimeControlData tcData) {
|
||||
this.gameTextListener = gameTextListener;
|
||||
tree = new GameTree(gameTextListener);
|
||||
timeController = new TimeControl();
|
||||
timeController.setTimeControl(timeControl, movesPerSession, timeIncrement);
|
||||
timeController.setTimeControl(tcData);
|
||||
gamePaused = false;
|
||||
newGame();
|
||||
}
|
||||
|
|
|
@ -20,22 +20,11 @@ package org.petero.droidfish.gamelogic;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.petero.droidfish.gamelogic.TimeControlData.TimeControlField;
|
||||
|
||||
/** Keep track of time control information for both players. */
|
||||
public class TimeControl {
|
||||
public static final class TimeControlField {
|
||||
long timeControl;
|
||||
int movesPerSession;
|
||||
long increment;
|
||||
|
||||
public TimeControlField(long time, int moves, long inc) {
|
||||
timeControl = time;
|
||||
movesPerSession = moves;
|
||||
increment = inc;
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<TimeControlField> tcW;
|
||||
private ArrayList<TimeControlField> tcB;
|
||||
private TimeControlData tcData;
|
||||
|
||||
private long whiteBaseTime; // Current remaining time, or remaining time when clock started
|
||||
private long blackBaseTime; // Current remaining time, or remaining time when clock started
|
||||
|
@ -49,7 +38,7 @@ public class TimeControl {
|
|||
|
||||
/** Constructor. Sets time control to "game in 5min". */
|
||||
public TimeControl() {
|
||||
setTimeControl(5 * 60 * 1000, 0, 0);
|
||||
tcData = new TimeControlData();
|
||||
reset();
|
||||
}
|
||||
|
||||
|
@ -60,19 +49,9 @@ public class TimeControl {
|
|||
timerT0 = 0;
|
||||
}
|
||||
|
||||
/** Set time control to "moves" moves in "time" milliseconds, + inc milliseconds per move. */
|
||||
public final void setTimeControl(long time, int moves, long inc) {
|
||||
tcW = new ArrayList<TimeControlField>();
|
||||
tcW.add(new TimeControlField(time, moves, inc));
|
||||
tcB = new ArrayList<TimeControlField>();
|
||||
tcB.add(new TimeControlField(time, moves, inc));
|
||||
}
|
||||
|
||||
/** Set time controls for white and black players. */
|
||||
public final void setTimeControl(ArrayList<TimeControlField> whiteTC,
|
||||
ArrayList<TimeControlField> blackTC) {
|
||||
tcW = whiteTC;
|
||||
tcB = blackTC;
|
||||
public final void setTimeControl(TimeControlData tcData) {
|
||||
this.tcData = tcData;
|
||||
}
|
||||
|
||||
public final void setCurrentMove(int move, boolean whiteToMove, long whiteBaseTime, long blackBaseTime) {
|
||||
|
@ -109,7 +88,7 @@ public class TimeControl {
|
|||
public final int moveMade(long now, boolean useIncrement) {
|
||||
stopTimer(now);
|
||||
|
||||
ArrayList<TimeControlField> tc = whiteToMove ? tcW : tcB;
|
||||
ArrayList<TimeControlField> tc = tcData.getTC(whiteToMove);
|
||||
Pair<Integer,Integer> tcInfo = getCurrentTC(whiteToMove);
|
||||
int tcIdx = tcInfo.first;
|
||||
int movesToTc = tcInfo.second;
|
||||
|
@ -141,13 +120,13 @@ public class TimeControl {
|
|||
|
||||
/** Get initial thinking time in milliseconds. */
|
||||
public final int getInitialTime(boolean whiteMove) {
|
||||
ArrayList<TimeControlField> tc = whiteMove ? tcW : tcB;
|
||||
ArrayList<TimeControlField> tc = tcData.getTC(whiteMove);
|
||||
return (int)tc.get(0).timeControl;
|
||||
}
|
||||
|
||||
/** Get time increment in milliseconds after playing next move. */
|
||||
public final int getIncrement(boolean whiteMove) {
|
||||
ArrayList<TimeControlField> tc = whiteMove ? tcW : tcB;
|
||||
ArrayList<TimeControlField> tc = tcData.getTC(whiteMove);
|
||||
int tcIdx = getCurrentTC(whiteMove).first;
|
||||
return (int)tc.get(tcIdx).increment;
|
||||
}
|
||||
|
@ -159,7 +138,7 @@ public class TimeControl {
|
|||
|
||||
/** @return Array containing time control, moves per session and time increment. */
|
||||
public int[] getTimeLimit(boolean whiteMove) {
|
||||
ArrayList<TimeControlField> tc = whiteMove ? tcW : tcB;
|
||||
ArrayList<TimeControlField> tc = tcData.getTC(whiteMove);
|
||||
int tcIdx = getCurrentTC(whiteMove).first;
|
||||
TimeControlField t = tc.get(tcIdx);
|
||||
return new int[]{(int)t.timeControl, t.movesPerSession, (int)t.increment};
|
||||
|
@ -167,7 +146,7 @@ public class TimeControl {
|
|||
|
||||
/** Return the current active time control index and number of moves to next time control. */
|
||||
private Pair<Integer,Integer> getCurrentTC(boolean whiteMove) {
|
||||
ArrayList<TimeControlField> tc = whiteMove ? tcW : tcB;
|
||||
ArrayList<TimeControlField> tc = tcData.getTC(whiteMove);
|
||||
int tcIdx = 0;
|
||||
final int lastTcIdx = tc.size() - 1;
|
||||
int nextTC = 1;
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package org.petero.droidfish.gamelogic;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public final class TimeControlData {
|
||||
public static final class TimeControlField {
|
||||
long timeControl;
|
||||
int movesPerSession;
|
||||
long increment;
|
||||
|
||||
public TimeControlField(long time, int moves, long inc) {
|
||||
timeControl = time;
|
||||
movesPerSession = moves;
|
||||
increment = inc;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<TimeControlField> tcW, tcB;
|
||||
|
||||
TimeControlData() {
|
||||
tcW = new ArrayList<TimeControlField>();
|
||||
tcW.add(new TimeControlField(5*60*1000, 60, 0));
|
||||
tcB = new ArrayList<TimeControlField>();
|
||||
tcB.add(new TimeControlField(5*60*1000, 60, 0));
|
||||
}
|
||||
|
||||
public final void setTimeControl(long time, int moves, long inc) {
|
||||
tcW = new ArrayList<TimeControlField>();
|
||||
tcW.add(new TimeControlField(time, moves, inc));
|
||||
tcB = new ArrayList<TimeControlField>();
|
||||
tcB.add(new TimeControlField(time, moves, inc));
|
||||
}
|
||||
|
||||
/** Get time control data array for white or black player. */
|
||||
public ArrayList<TimeControlField> getTC(boolean whiteMove) {
|
||||
return whiteMove ? tcW : tcB;
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ public class GameTest extends TestCase {
|
|||
* Test of haveDrawOffer method, of class Game.
|
||||
*/
|
||||
public void testHaveDrawOffer() {
|
||||
Game game = new Game(null, 0, 0, 0);
|
||||
Game game = new Game(null, new TimeControlData());
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
|
||||
boolean res = game.processString("e4");
|
||||
|
@ -124,7 +124,7 @@ public class GameTest extends TestCase {
|
|||
* Test of draw by 50 move rule, of class Game.
|
||||
*/
|
||||
public void testDraw50() throws ChessParseError {
|
||||
Game game = new Game(null, 0, 0, 0);
|
||||
Game game = new Game(null, new TimeControlData());
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
boolean res = game.processString("draw 50");
|
||||
assertEquals(true, res);
|
||||
|
@ -179,7 +179,7 @@ public class GameTest extends TestCase {
|
|||
* Test of draw by repetition, of class Game.
|
||||
*/
|
||||
public void testDrawRep() throws ChessParseError {
|
||||
Game game = new Game(null, 0, 0, 0);
|
||||
Game game = new Game(null, new TimeControlData());
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
game.processString("Nc3");
|
||||
game.processString("Nc6");
|
||||
|
@ -251,7 +251,7 @@ public class GameTest extends TestCase {
|
|||
* Test of draw offer/accept/request command.
|
||||
*/
|
||||
public void testDrawBug() throws ChessParseError {
|
||||
Game game = new Game(null, 0, 0, 0);
|
||||
Game game = new Game(null, new TimeControlData());
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
game.processString("e4");
|
||||
game.processString("c5");
|
||||
|
@ -269,7 +269,7 @@ public class GameTest extends TestCase {
|
|||
* Test of resign command, of class Game.
|
||||
*/
|
||||
public void testResign() throws ChessParseError {
|
||||
Game game = new Game(null, 0, 0, 0);
|
||||
Game game = new Game(null, new TimeControlData());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
game.processString("f3");
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
|
@ -299,7 +299,7 @@ public class GameTest extends TestCase {
|
|||
* Test of processString method, of class Game.
|
||||
*/
|
||||
public void testProcessString() throws ChessParseError {
|
||||
Game game = new Game(null, 0, 0, 0);
|
||||
Game game = new Game(null, new TimeControlData());
|
||||
assertEquals(TextIO.startPosFEN, TextIO.toFEN(game.currPos()));
|
||||
boolean res = game.processString("Nf3");
|
||||
assertEquals(true, res);
|
||||
|
@ -348,7 +348,7 @@ public class GameTest extends TestCase {
|
|||
* Test of getGameState method, of class Game.
|
||||
*/
|
||||
public void testGetGameState() throws ChessParseError {
|
||||
Game game = new Game(null, 0, 0, 0);
|
||||
Game game = new Game(null, new TimeControlData());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
game.processString("f3");
|
||||
game.processString("e5");
|
||||
|
@ -364,7 +364,7 @@ public class GameTest extends TestCase {
|
|||
* Test of insufficientMaterial method, of class Game.
|
||||
*/
|
||||
public void testInsufficientMaterial() throws ChessParseError {
|
||||
Game game = new Game(null, 0, 0, 0);
|
||||
Game game = new Game(null, new TimeControlData());
|
||||
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());
|
||||
|
@ -407,7 +407,7 @@ public class GameTest extends TestCase {
|
|||
/** 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, 0, 0, 0);
|
||||
Game game = new Game(null, new TimeControlData());
|
||||
|
||||
Pair<Position, ArrayList<Move>> hist = game.getUCIHistory();
|
||||
assertEquals(0, hist.second.size());
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.petero.droidfish.gamelogic;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.petero.droidfish.gamelogic.TimeControlData.TimeControlField;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
||||
|
@ -31,7 +33,9 @@ public class TimeControlTest extends TestCase {
|
|||
TimeControl tc = new TimeControl();
|
||||
long totTime = 5 * 60 * 1000;
|
||||
long t0 = 1000;
|
||||
tc.setTimeControl(totTime, 0, 0);
|
||||
TimeControlData tcData = new TimeControlData();
|
||||
tcData.setTimeControl(totTime, 0, 0);
|
||||
tc.setTimeControl(tcData);
|
||||
tc.setCurrentMove(1, true, totTime, totTime);
|
||||
assertEquals(0, tc.getMovesToTC(true));
|
||||
assertEquals(0, tc.getMovesToTC(false));
|
||||
|
@ -70,7 +74,9 @@ public class TimeControlTest extends TestCase {
|
|||
/** Test getMovesToTC */
|
||||
public void testTimeControl() {
|
||||
TimeControl tc = new TimeControl();
|
||||
tc.setTimeControl(2 * 60 * 1000, 40, 0);
|
||||
TimeControlData tcData = new TimeControlData();
|
||||
tcData.setTimeControl(2 * 60 * 1000, 40, 0);
|
||||
tc.setTimeControl(tcData);
|
||||
tc.setCurrentMove(1, true, 0, 0);
|
||||
assertEquals(40, tc.getMovesToTC(true));
|
||||
assertEquals(40, tc.getMovesToTC(false));
|
||||
|
@ -107,20 +113,21 @@ public class TimeControlTest extends TestCase {
|
|||
assertEquals(40, tc.getMovesToTC(false));
|
||||
}
|
||||
|
||||
private TimeControl.TimeControlField tcf(long time, int moves, long inc) {
|
||||
return new TimeControl.TimeControlField(time, moves, inc);
|
||||
private TimeControlField tcf(long time, int moves, long inc) {
|
||||
return new TimeControlField(time, moves, inc);
|
||||
}
|
||||
|
||||
/** Test multiple time controls. */
|
||||
public void testMultiTimeControl() {
|
||||
TimeControl tc = new TimeControl();
|
||||
ArrayList<TimeControl.TimeControlField> tcW = new ArrayList<TimeControl.TimeControlField>();
|
||||
tcW.add(tcf(120*60*1000, 40, 0));
|
||||
tcW.add(tcf(60*60*1000, 20, 0));
|
||||
tcW.add(tcf(30*60*1000, 0, 15*1000));
|
||||
ArrayList<TimeControl.TimeControlField> tcB = new ArrayList<TimeControl.TimeControlField>();
|
||||
tcB.add(tcf(5*60*1000, 60, 1000));
|
||||
tc.setTimeControl(tcW, tcB);
|
||||
TimeControlData tcData = new TimeControlData();
|
||||
tcData.tcW = new ArrayList<TimeControlField>();
|
||||
tcData.tcW.add(tcf(120*60*1000, 40, 0));
|
||||
tcData.tcW.add(tcf(60*60*1000, 20, 0));
|
||||
tcData.tcW.add(tcf(30*60*1000, 0, 15*1000));
|
||||
tcData.tcB = new ArrayList<TimeControlField>();
|
||||
tcData.tcB.add(tcf(5*60*1000, 60, 1000));
|
||||
tc.setTimeControl(tcData);
|
||||
|
||||
assertEquals(40, tc.getMovesToTC(true));
|
||||
assertEquals(60, tc.getMovesToTC(false));
|
||||
|
@ -176,7 +183,9 @@ public class TimeControlTest extends TestCase {
|
|||
int wBaseTime = (int)timeCont;
|
||||
int bBaseTime = (int)timeCont;
|
||||
final long inc = 700;
|
||||
tc.setTimeControl(timeCont, 5, inc);
|
||||
TimeControlData tcData = new TimeControlData();
|
||||
tcData.setTimeControl(timeCont, 5, inc);
|
||||
tc.setTimeControl(tcData);
|
||||
tc.setCurrentMove(5, true, wBaseTime, bBaseTime);
|
||||
long t0 = 1342134;
|
||||
assertEquals(timeCont, tc.getRemainingTime(true, t0 + 4711));
|
||||
|
@ -208,7 +217,8 @@ public class TimeControlTest extends TestCase {
|
|||
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);
|
||||
tcData.setTimeControl(timeCont, 1, inc);
|
||||
tc.setTimeControl(tcData);
|
||||
wBaseTime = bBaseTime = (int)timeCont;
|
||||
tc.setCurrentMove(1, true, wBaseTime, bBaseTime);
|
||||
tc.startTimer(t0 + 1000);
|
||||
|
|
Loading…
Reference in New Issue
Block a user