248 lines
6 KiB
Java
248 lines
6 KiB
Java
import java.util.*;
|
|
|
|
/**
|
|
* Player class
|
|
*/
|
|
public class Player {
|
|
|
|
/**
|
|
* Player's chessboard
|
|
*/
|
|
private Chessboard chessboard;
|
|
|
|
/**
|
|
* Player's piece color
|
|
*/
|
|
private PieceColor color;
|
|
|
|
/**
|
|
* Player's start position
|
|
*/
|
|
private StartPosition startPosition;
|
|
|
|
/**
|
|
* King piece
|
|
*/
|
|
private King king;
|
|
|
|
/**
|
|
* Active CPU mode
|
|
*/
|
|
private CPUMode cpu;
|
|
|
|
/**
|
|
* Waiting for CPU move
|
|
*/
|
|
private boolean isPlaying = false;
|
|
|
|
/**
|
|
* Delays between player's moves
|
|
*/
|
|
private ArrayList<Integer> delays = new ArrayList<>();
|
|
|
|
/**
|
|
* Player's constructor
|
|
* @param chessboard player's chessboard
|
|
* @param startPosition player's start position
|
|
* @param color player's color
|
|
*/
|
|
public Player(Chessboard chessboard, StartPosition startPosition, PieceColor color) {
|
|
this.chessboard = chessboard;
|
|
this.color = color;
|
|
this.startPosition = startPosition;
|
|
}
|
|
|
|
/**
|
|
* Detects if player is in check
|
|
* @return true, if in check
|
|
*/
|
|
public boolean inCheck() {
|
|
return king.isEndangered();
|
|
}
|
|
|
|
/**
|
|
* Detects if player has no possible moves
|
|
* @return true, if no possible moves
|
|
*/
|
|
public boolean hasNoPossibleMove() {
|
|
for (APiece piece : getPieces()) {
|
|
boolean[][] possibleMoves = piece.getPossibleMoves();
|
|
for (int y = 0; y < possibleMoves.length; y++) {
|
|
for (int x = 0; x < possibleMoves[y].length; x++) {
|
|
if(possibleMoves[y][x]) return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Play automatically as CPU
|
|
*/
|
|
public void play() {
|
|
if(cpu == null) return;
|
|
isPlaying = true;
|
|
Timer t = new Timer();
|
|
t.schedule(new TimerTask() {
|
|
@Override
|
|
public void run() {
|
|
if (cpu != null) {
|
|
if (cpu == CPUMode.RANDOM) randomMove();
|
|
if (cpu == CPUMode.SMART) smartMove();
|
|
}
|
|
isPlaying = false;
|
|
t.cancel();
|
|
}
|
|
}, 1000);
|
|
}
|
|
|
|
/**
|
|
* Select random piece and move it randomly
|
|
* @return true, if piece was moved
|
|
*/
|
|
public boolean randomMove() {
|
|
ArrayList<APiece> myPieces = getPieces();
|
|
while(myPieces.size() != 0) {
|
|
Random r = new Random();
|
|
APiece selectedPiece = myPieces.get(r.nextInt(myPieces.size()));
|
|
ArrayList<PiecePosition> possibleMoves = new ArrayList<>();
|
|
myPieces.remove(selectedPiece);
|
|
|
|
boolean[][] possibleMoveMap = selectedPiece.getPossibleMoves();
|
|
for (int y = 0; y < possibleMoveMap.length; y++) {
|
|
for (int x = 0; x < possibleMoveMap[y].length; x++) {
|
|
if(possibleMoveMap[y][x]) {
|
|
possibleMoves.add(new PiecePosition(x, y));
|
|
}
|
|
}
|
|
}
|
|
|
|
int moveCount = possibleMoves.size();
|
|
if(moveCount == 0) {
|
|
continue;
|
|
}
|
|
|
|
PiecePosition randomMove = possibleMoves.get(r.nextInt(moveCount));
|
|
selectedPiece.move(randomMove.x, randomMove.y, true);
|
|
chessboard.changeActivePlayer();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Move piece according to the stockfish engine
|
|
* @return true, if piece was moved
|
|
*/
|
|
public boolean smartMove() {
|
|
Stockfish stockfish = Stockfish.getInstance();
|
|
if(stockfish == null) return false;
|
|
String fen = chessboard.toFEN();
|
|
String bestMove = stockfish.getBestMove(fen, 0, 500);
|
|
if(bestMove == null) return false;
|
|
PiecePosition fromPos = PiecePosition.fromString(bestMove.substring(0, 2));
|
|
PiecePosition toPos = PiecePosition.fromString(bestMove.substring(2, 4));
|
|
if(fromPos == null || toPos == null) return false;
|
|
APiece piece = chessboard.getPiece(fromPos.x, fromPos.y);
|
|
piece.move(toPos.x, toPos.y);
|
|
chessboard.changeActivePlayer();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get player's chessboard
|
|
* @return chessboard
|
|
*/
|
|
public Chessboard getChessboard() {
|
|
return chessboard;
|
|
}
|
|
|
|
/**
|
|
* Get player's piece color
|
|
* @return piece color
|
|
*/
|
|
public PieceColor getColor() {
|
|
return color;
|
|
}
|
|
|
|
/**
|
|
* Get player's start position
|
|
* @return start position
|
|
*/
|
|
public StartPosition getStartPosition() {
|
|
return startPosition;
|
|
}
|
|
|
|
/**
|
|
* Get player's King piece
|
|
* @return King
|
|
*/
|
|
public King getKing() {
|
|
return king;
|
|
}
|
|
|
|
/**
|
|
* Set player's King piece
|
|
* @param king new King
|
|
*/
|
|
public void setKing(King king) {
|
|
this.king = king;
|
|
}
|
|
|
|
/**
|
|
* Get all player's pieces
|
|
* @return player's pieces
|
|
*/
|
|
public ArrayList<APiece> getPieces() {
|
|
ArrayList<APiece> myPieces = new ArrayList<>();
|
|
for (APiece[] pieces : chessboard.pieces) {
|
|
for (APiece piece : pieces) {
|
|
if(piece != null && piece.getPlayer() == this) {
|
|
myPieces.add(piece);
|
|
}
|
|
}
|
|
}
|
|
return myPieces;
|
|
}
|
|
|
|
/**
|
|
* Set player's CPU mode
|
|
* @param cpu CPU mode
|
|
*/
|
|
public void setCPU(CPUMode cpu) {
|
|
// TODO: use enums
|
|
this.cpu = cpu;
|
|
if(chessboard.getActivePlayer() == this && !isPlaying) play();
|
|
}
|
|
|
|
/**
|
|
* Get player's CPU mode
|
|
* @return CPU mode
|
|
*/
|
|
public CPUMode getCPU() {
|
|
return cpu;
|
|
}
|
|
|
|
/**
|
|
* Add new delay before last move
|
|
* @param delay delay in ms
|
|
*/
|
|
public void addDelay(int delay) {
|
|
delays.add(delay);
|
|
}
|
|
|
|
/**
|
|
* Get all delays between moves
|
|
* @return delays list
|
|
*/
|
|
public List<Integer> getDelays() {
|
|
return delays;
|
|
}
|
|
|
|
}
|
|
|
|
enum CPUMode {
|
|
|
|
RANDOM, SMART;
|
|
|
|
} |