/*
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;
public class TimeControl {
private long timeControl;
private int movesPerSession;
private long increment;
private long whiteBaseTime;
private long blackBaseTime;
int currentMove;
boolean whiteToMove;
long elapsed; // Accumulated elapsed time for this move.
long timerT0; // Time when timer started. 0 if timer is stopped.
/** Constructor. Sets time control to "game in 5min". */
public TimeControl() {
setTimeControl(5 * 60 * 1000, 0, 0);
reset();
}
public final void reset() {
currentMove = 1;
whiteToMove = true;
elapsed = 0;
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) {
timeControl = time;
movesPerSession = moves;
increment = inc;
}
public final void setCurrentMove(int move, boolean whiteToMove, long whiteBaseTime, long blackBaseTime) {
currentMove = move;
this.whiteToMove = whiteToMove;
this.whiteBaseTime = whiteBaseTime;
this.blackBaseTime = blackBaseTime;
timerT0 = 0;
elapsed = 0;
}
public final boolean clockRunning() {
return timerT0 != 0;
}
public final void startTimer(long now) {
if (!clockRunning()) {
timerT0 = now;
}
}
public final void stopTimer(long now) {
if (clockRunning()) {
long timerT1 = now;
long currElapsed = timerT1 - timerT0;
timerT0 = 0;
if (currElapsed > 0) {
elapsed += currElapsed;
}
}
}
/** Compute new remaining time after a move is made. */
public final int moveMade(long now, boolean useIncrement) {
stopTimer(now);
long remaining = getRemainingTime(whiteToMove, now);
if (useIncrement) {
remaining += increment;
if (getMovesToTC() == 1)
remaining += timeControl;
}
elapsed = 0;
return (int)remaining;
}
/** Get remaining time */
public final int getRemainingTime(boolean whiteToMove, long now) {
long remaining = whiteToMove ? whiteBaseTime : blackBaseTime;
if (whiteToMove == this.whiteToMove) {
remaining -= elapsed;
if (timerT0 != 0) {
remaining -= now - timerT0;
}
}
return (int)remaining;
}
public final int getInitialTime() {
return (int)timeControl;
}
public final int getIncrement() {
return (int)increment;
}
public final int getMovesToTC() {
if (movesPerSession <= 0)
return 0;
int nextTC = 1;
while (nextTC <= currentMove)
nextTC += movesPerSession;
return nextTC - currentMove;
}
public final int getMovesPerSession() {
return movesPerSession;
}
}