package minechess.common.ai;
import minechess.common.EntityBaseChessPiece;
import minechess.common.EntityKing;
import org.apache.commons.lang3.time.StopWatch;
/**
* MineChess
* @author MineMaarten
* www.minemaarten.com
* @license Lesser GNU Public License v3 (http://www.gnu.org/licenses/lgpl.html)
*
* This class came from pate's ChessMate, found at https://github.com/pate/chessmate. Many thanks to him for allowing
* the usage of his code by others. These classes are a bit modified to be able to have more AI's running at the same time.
*/
public class AICaller extends Thread{
/**
* A reference to the parent Chess class.
* @see class Chess
*/
Chess chess;
public EntityBaseChessPiece entityPiece;
boolean bStart = false;
/**
* This method starts the AI
* @param entityPiece piece that the board is associated with. Always use a piece that is a computerpiece!
*/
public void go(EntityBaseChessPiece entityPiece){
if(!bStart) {
this.entityPiece = entityPiece;
chess.pos = new ChessPosition(entityPiece);
if(!entityPiece.isBlack()) {//when the computerpiece color is white, we need to inform the AI logic about that.
chess.HUMAN = chess.BLACK;
chess.PROGRAM = chess.WHITE;
}
entityPiece.sendChatToNearbyPlayers(null, AIPersonality.getPreTurnMessage(chess.positionEvaluation(chess.pos, chess.PROGRAM), ((EntityKing)entityPiece).lastPositionScore, entityPiece.getRNG()));
((EntityKing)entityPiece).lastPositionScore = chess.positionEvaluation(chess.pos, chess.PROGRAM);
bStart = true;
//System.out.println("AI going to run! Board received: ");
// chess.pos.printBoard();
}
}
public void cancel(){
bStart = false;
}
public void exit(){
bRunning = false;
}
/**
* A boolean variable indicating whether the AICaller class is running.
* This prevents the possibility of two threads simultaneously manipulating the
* chess board. This should never happen, but one can never be too safe.
*/
private boolean bRunning = false;
public AICaller(Chess chess){
this.chess = chess;
//Thread.currentThread().setPriority(MAX_PRIORITY);
}
/**
* This function is called when a player moves a piece and it is the AI's turn to
* make a move. It simply processes the search in a separate thread so the application is not
* locked up.
* The thread will exit if chess.bThinking is falsified.
*/
@Override
public void run(){
if(bRunning) return;
bRunning = true;
// System.out.println("AI initialized, waiting for a call...");
while(!chess.main.bQuit && bRunning) {
if(bStart) {
bStart = false;
try {
Thread.currentThread().sleep(1000);
} catch(InterruptedException ex) {
System.out.println("AICaller Thread Sleep Error");
}
StopWatch stopwatch = new StopWatch();
stopwatch.start();
chess.bThinking = true;
ChessMove n = chess.playGame(chess.pos, chess.PROGRAM);
if(chess.bThinking) {
chess.bThinking = false; // consider removing the bRunning?
entityPiece.executeMove(n);
chess.pos.makeMove(n);
entityPiece.sendChatToNearbyPlayers(null, AIPersonality.getPostTurnMessage(chess.positionEvaluation(chess.pos, chess.PROGRAM), ((EntityKing)entityPiece).lastPositionScore, (int)(stopwatch.getTime() / 1000), entityPiece.getRNG()));
//System.out.println("AI executed the move " + (n != null ? n.toString() : "NO MOVE FOUND"));
chess.main.bQuit = true;
}
}
try {
Thread.currentThread().sleep(50);
} catch(InterruptedException ex) {
System.out.println("AICaller Thread Sleep Error");
}
}
bRunning = false;
}
}