224 lines
5.2 KiB
Java
224 lines
5.2 KiB
Java
package dev.kske.chess.board;
|
|
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
|
|
/**
|
|
* Represents a piece on a board with a color.<br>
|
|
* <br>
|
|
* Project: <strong>Chess</strong><br>
|
|
* File: <strong>Piece.java</strong><br>
|
|
* Created: <strong>01.07.2019</strong><br>
|
|
*
|
|
* @since Chess v0.1-alpha
|
|
* @author Kai S. K. Engelbart
|
|
*/
|
|
public abstract class Piece implements Cloneable {
|
|
|
|
private final Color color;
|
|
protected Board board;
|
|
|
|
/**
|
|
* Initializes a piece.
|
|
*
|
|
* @param color the color of this piece
|
|
* @param board the board on which this piece is placed
|
|
*/
|
|
public Piece(Color color, Board board) {
|
|
this.color = color;
|
|
this.board = board;
|
|
}
|
|
|
|
/**
|
|
* Generated a list of legal moves this piece can make.
|
|
*
|
|
* @param pos the position of this piece
|
|
* @return a list of legal moves this piece can make
|
|
*/
|
|
public List<Move> getMoves(Position pos) {
|
|
List<Move> moves = getPseudolegalMoves(pos);
|
|
for (Iterator<Move> iterator = moves.iterator(); iterator.hasNext();) {
|
|
Move move = iterator.next();
|
|
board.move(move);
|
|
if (board.checkCheck(getColor()))
|
|
iterator.remove();
|
|
board.revert();
|
|
}
|
|
return moves;
|
|
}
|
|
|
|
/**
|
|
* Generates a list of pseudo legal moves this piece can make.
|
|
*
|
|
* @param pos the position of this piece
|
|
* @return a list of pseudo legal moves this piece can make
|
|
*/
|
|
protected abstract List<Move> getPseudolegalMoves(Position pos);
|
|
|
|
/**
|
|
* Checks, if a given move is valid.
|
|
*
|
|
* @param move the move to check
|
|
* @return {@code true} if the move is valid
|
|
*/
|
|
public abstract boolean isValidMove(Move move);
|
|
|
|
/**
|
|
* Checks, if the squares between the position and the destination of a move
|
|
* are
|
|
* free.
|
|
*
|
|
* @param move The move to check
|
|
* @return {@true} if the path is free
|
|
*/
|
|
protected boolean isFreePath(Move move) {
|
|
for (
|
|
int i = move.getPos().x + move.getxSign(), j
|
|
= move.getPos().y + move.getySign();
|
|
i != move.getDest().x
|
|
|| j != move.getDest().y;
|
|
i += move.getxSign(), j += move.getySign()
|
|
)
|
|
if (board.getBoardArr()[i][j] != null)
|
|
return false;
|
|
return checkDestination(move);
|
|
}
|
|
|
|
/**
|
|
* Checks if the destination of a move is empty or a piece from the opposing
|
|
* team
|
|
*
|
|
* @param move The move to check
|
|
* @return {@code false} if the move's destination is from the same team
|
|
*/
|
|
protected final boolean checkDestination(Move move) {
|
|
return board.getDest(move) == null
|
|
|| board.getDest(move).getColor() != getColor();
|
|
}
|
|
|
|
@Override
|
|
public Object clone() {
|
|
Piece piece = null;
|
|
try {
|
|
piece = (Piece) super.clone();
|
|
} catch (CloneNotSupportedException ex) {
|
|
ex.printStackTrace();
|
|
}
|
|
return piece;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return String.format("%s[color=%s]", getClass().getSimpleName(), color);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(color);
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (this == obj)
|
|
return true;
|
|
if (obj == null)
|
|
return false;
|
|
if (getClass() != obj.getClass())
|
|
return false;
|
|
Piece other = (Piece) obj;
|
|
return color == other.color;
|
|
}
|
|
|
|
/**
|
|
* @return the standard value of this {@link Piece} that can be used for
|
|
* board
|
|
* evaluation
|
|
*/
|
|
public abstract int getValue();
|
|
|
|
/**
|
|
* @return The first character of this {@link Piece} in algebraic notation
|
|
* and
|
|
* lower case
|
|
*/
|
|
public char firstChar() {
|
|
return Character.toLowerCase(getClass().getSimpleName().charAt(0));
|
|
}
|
|
|
|
/**
|
|
* @param firstChar the first character of a piece's name
|
|
* @return the class of the piece associated with that character or
|
|
* {@code null}
|
|
* if no piece is associated with the given character
|
|
*/
|
|
public static Class<? extends Piece> fromFirstChar(char firstChar) {
|
|
switch (Character.toLowerCase(firstChar)) {
|
|
case 'k':
|
|
return King.class;
|
|
case 'q':
|
|
return Queen.class;
|
|
case 'r':
|
|
return Rook.class;
|
|
case 'n':
|
|
return Knight.class;
|
|
case 'b':
|
|
return Bishop.class;
|
|
case 'p':
|
|
return Pawn.class;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return the {@link Color} of this {@link Piece}
|
|
*/
|
|
public Color getColor() { return color; }
|
|
|
|
/**
|
|
* Project: <strong>Chess</strong><br>
|
|
* File: <strong>Piece.java</strong><br>
|
|
* Created: <strong>01.07.2019</strong><br>
|
|
*
|
|
* @author Kai S. K. Engelbart
|
|
* @since Chess v0.1-alpha
|
|
*/
|
|
public enum Color {
|
|
|
|
/**
|
|
* Represents the color of the white pieces on a board.
|
|
*/
|
|
WHITE,
|
|
|
|
/**
|
|
* Represents the color of the black pieces on a board.
|
|
*/
|
|
BLACK;
|
|
|
|
/**
|
|
* @param c the first character of a color's name
|
|
* @return {@code WHITE} if the character is {@code w} or {@code W},
|
|
* else
|
|
* {@code BLACK}
|
|
*/
|
|
public static Color fromFirstChar(char c) {
|
|
return Character.toLowerCase(c) == 'w' ? WHITE : BLACK;
|
|
}
|
|
|
|
/**
|
|
* @return the first character (lower case) of this color
|
|
*/
|
|
public char firstChar() {
|
|
return this == WHITE ? 'w' : 'b';
|
|
}
|
|
|
|
/**
|
|
* @return the opposite of this color
|
|
*/
|
|
public Color opposite() {
|
|
return this == WHITE ? BLACK : WHITE;
|
|
}
|
|
}
|
|
}
|