diff --git a/src/dev/kske/chess/board/Bishop.java b/src/dev/kske/chess/board/Bishop.java
index 4b2d8b0..9412a30 100644
--- a/src/dev/kske/chess/board/Bishop.java
+++ b/src/dev/kske/chess/board/Bishop.java
@@ -65,5 +65,5 @@ public class Bishop extends Piece {
}
@Override
- public Type getType() { return Type.BISHOP; }
+ public int getValue() { return 30; }
}
diff --git a/src/dev/kske/chess/board/Board.java b/src/dev/kske/chess/board/Board.java
index 7304f64..d6c440f 100644
--- a/src/dev/kske/chess/board/Board.java
+++ b/src/dev/kske/chess/board/Board.java
@@ -10,7 +10,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import dev.kske.chess.board.Piece.Color;
-import dev.kske.chess.board.Piece.Type;
/**
* Project: Chess
@@ -87,7 +86,7 @@ public class Board {
move.execute(this);
// Update the king's position if the moved piece is the king
- if (piece.getType() == Type.KING) kingPos.put(piece.getColor(), move.getDest());
+ if (piece instanceof King) kingPos.put(piece.getColor(), move.getDest());
// Update log
log.add(move, piece, capturePiece);
@@ -118,29 +117,30 @@ public class Board {
dest = Position.fromLAN(m.group("toSquare"));
if (m.group("fromSquare") != null) pos = Position.fromLAN(m.group("fromSquare"));
else {
- Type type = Type.fromFirstChar(m.group("pieceType").charAt(0));
- char file;
- int rank;
+ Class extends Piece> pieceClass = Piece.fromFirstChar(m.group("pieceType").charAt(0));
+ char file;
+ int rank;
if (m.group("fromFile") != null) {
file = m.group("fromFile").charAt(0);
- rank = get(type, file);
+ rank = get(pieceClass, file);
pos = Position.fromLAN(String.format("%c%d", file, rank));
} else if (m.group("fromRank") != null) {
rank = Integer.parseInt(m.group("fromRank").substring(0, 1));
- file = get(type, rank);
+ file = get(pieceClass, rank);
pos = Position.fromLAN(String.format("%c%d", file, rank));
- } else pos = get(type, dest);
+ } else pos = get(pieceClass, dest);
}
move = new Move(pos, dest);
break;
case "pawnCapture":
dest = Position.fromLAN(m.group("toSquare"));
char file = m.group("fromFile").charAt(0);
- int rank = m.group("fromRank") == null ? get(Type.PAWN, file) : Integer.parseInt(m.group("fromRank"));
+ int rank = m.group("fromRank") == null ? get(Pawn.class, file) : Integer.parseInt(m.group("fromRank"));
pos = Position.fromLAN(String.format("%c%d", file, rank));
if (m.group("promotedTo") != null) {
}
+ move = new Move(pos, dest);
break;
case "pawnPush":
dest = Position.fromLAN(m.group("toSquare"));
@@ -151,6 +151,7 @@ public class Board {
if (boardArr[dest.x][dest.y + step] != null) pos = new Position(dest.x, dest.y + step);
// Double step forward
else pos = new Position(dest.x, dest.y + 2 * step);
+ move = new Move(pos, dest);
break;
case "castling":
pos = new Position(4, log.getActiveColor() == Color.WHITE ? 7 : 0);
@@ -175,7 +176,7 @@ public class Board {
move.revert(this, moveNode.capturedPiece);
// Update the king's position if the moved piece is the king
- if (getPos(move).getType() == Type.KING) kingPos.put(getPos(move).getColor(), move.getPos());
+ if (getPos(move) instanceof King) kingPos.put(getPos(move).getColor(), move.getPos());
// Update log
log.removeLast();
@@ -322,30 +323,30 @@ public class Board {
/**
* Searches for a {@link Piece} inside a file (A - H).
*
- * @param type The {@link Type} of the piece to search for
- * @param file The file in which to search for the piece
+ * @param pieceClass The class of the piece to search for
+ * @param file The file in which to search for the piece
* @return The rank (1 - 8) of the first piece with the specified type and
* current color in the file, or {@code -1} if there isn't any
*/
- public int get(Type type, char file) {
+ public int get(Class extends Piece> pieceClass, char file) {
int x = file - 97;
for (int i = 0; i < 8; i++)
- if (boardArr[x][i] != null && boardArr[x][i].getType() == type && boardArr[x][i].getColor() == log.getActiveColor()) return 8 - i;
+ if (boardArr[x][i] != null && boardArr[x][i].getClass() == pieceClass && boardArr[x][i].getColor() == log.getActiveColor()) return 8 - i;
return -1;
}
/**
* Searches for a {@link Piece} inside a rank (1 - 8).
*
- * @param type The {@link Type} of the piece to search for
- * @param rank The rank in which to search for the piece
+ * @param pieceClass The class of the piece to search for
+ * @param rank The rank in which to search for the piece
* @return The file (A - H) of the first piece with the specified type and
* current color in the file, or {@code -} if there isn't any
*/
- public char get(Type type, int rank) {
+ public char get(Class extends Piece> pieceClass, int rank) {
int y = rank - 1;
for (int i = 0; i < 8; i++)
- if (boardArr[i][y] != null && boardArr[i][y].getType() == type && boardArr[i][y].getColor() == log.getActiveColor())
+ if (boardArr[i][y] != null && boardArr[i][y].getClass() == pieceClass && boardArr[i][y].getColor() == log.getActiveColor())
return (char) (i + 97);
return '-';
}
@@ -353,14 +354,14 @@ public class Board {
/**
* Searches for a {@link Piece} that can move to a {@link Position}.
*
- * @param type The {@link Type} of the piece to search for
- * @param dest The destination that the piece is required to reach
+ * @param pieceClass The class of the piece to search for
+ * @param dest The destination that the piece is required to reach
* @return The position of a piece that can move to the specified destination
*/
- public Position get(Type type, Position dest) {
+ public Position get(Class extends Piece> pieceClass, Position dest) {
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
- if (boardArr[i][j] != null && boardArr[i][j].getType() == type && boardArr[i][j].getColor() == log.getActiveColor()) {
+ if (boardArr[i][j] != null && boardArr[i][j].getClass() == pieceClass && boardArr[i][j].getColor() == log.getActiveColor()) {
Position pos = new Position(i, j);
if (boardArr[i][j].isValidMove(new Move(pos, dest))) return pos;
}
diff --git a/src/dev/kske/chess/board/FENString.java b/src/dev/kske/chess/board/FENString.java
index 0dbb3e5..8f27140 100644
--- a/src/dev/kske/chess/board/FENString.java
+++ b/src/dev/kske/chess/board/FENString.java
@@ -164,7 +164,7 @@ public class FENString {
}
// Write piece character
- char p = piece.getType().firstChar();
+ char p = piece.firstChar();
sb.append(piece.getColor() == Color.WHITE ? Character.toUpperCase(p) : p);
}
}
diff --git a/src/dev/kske/chess/board/King.java b/src/dev/kske/chess/board/King.java
index cde5a98..6807bb3 100644
--- a/src/dev/kske/chess/board/King.java
+++ b/src/dev/kske/chess/board/King.java
@@ -63,10 +63,10 @@ public class King extends Piece {
private boolean canCastle(Position kingPos, Position freeDest, Position rookPos, Position jumpPos) {
Piece rook = board.get(rookPos);
- return rook != null && rook.getType() == Type.ROOK && isFreePath(new Move(kingPos, freeDest))
- && !board.isAttacked(kingPos, getColor().opposite()) && !board.isAttacked(jumpPos, getColor().opposite());
+ return rook != null && rook instanceof Rook && isFreePath(new Move(kingPos, freeDest)) && !board.isAttacked(kingPos, getColor().opposite())
+ && !board.isAttacked(jumpPos, getColor().opposite());
}
@Override
- public Type getType() { return Type.KING; }
-}
+ public int getValue() { return 0; }
+}
\ No newline at end of file
diff --git a/src/dev/kske/chess/board/Knight.java b/src/dev/kske/chess/board/Knight.java
index cbaf67a..9e54fd8 100644
--- a/src/dev/kske/chess/board/Knight.java
+++ b/src/dev/kske/chess/board/Knight.java
@@ -45,5 +45,8 @@ public class Knight extends Piece {
}
@Override
- public Type getType() { return Type.KNIGHT; }
+ public int getValue() { return 35; }
+
+ @Override
+ public char firstChar() { return 'n'; }
}
diff --git a/src/dev/kske/chess/board/Log.java b/src/dev/kske/chess/board/Log.java
index a54b3bb..9d60002 100644
--- a/src/dev/kske/chess/board/Log.java
+++ b/src/dev/kske/chess/board/Log.java
@@ -5,7 +5,6 @@ import java.util.Iterator;
import java.util.Objects;
import dev.kske.chess.board.Piece.Color;
-import dev.kske.chess.board.Piece.Type;
/**
* Project: Chess
@@ -78,14 +77,14 @@ public class Log implements Iterable {
* @param capturedPiece The piece captured with the move
*/
public void add(Move move, Piece piece, Piece capturedPiece) {
- enPassant = piece.getType() == Type.PAWN && move.getyDist() == 2 ? new Position(move.getPos().x, move.getPos().y + move.getySign()) : null;
+ enPassant = piece instanceof Pawn && move.getyDist() == 2 ? new Position(move.getPos().x, move.getPos().y + move.getySign()) : null;
if (activeColor == Color.BLACK) ++fullmoveNumber;
- if (piece.getType() == Type.PAWN || capturedPiece != null) halfmoveClock = 0;
+ if (piece instanceof Pawn || capturedPiece != null) halfmoveClock = 0;
else++halfmoveClock;
activeColor = activeColor.opposite();
// Disable castling rights if a king or a rook has been moved
- if (piece.getType() == Type.KING || piece.getType() == Type.ROOK) disableCastlingRights(piece, move.getPos());
+ if (piece instanceof King || piece instanceof Rook) disableCastlingRights(piece, move.getPos());
final MoveNode leaf = new MoveNode(move, capturedPiece, castlingRights.clone(), enPassant, activeColor, fullmoveNumber, halfmoveClock);
@@ -170,11 +169,11 @@ public class Log implements Iterable {
private void disableCastlingRights(Piece piece, Position initialPosition) {
// Kingside
- if (piece.getType() == Type.KING || piece.getType() == Type.ROOK && initialPosition.x == 7)
+ if (piece instanceof King || piece instanceof Rook && initialPosition.x == 7)
castlingRights[piece.getColor() == Color.WHITE ? MoveNode.WHITE_KINGSIDE : MoveNode.BLACK_KINGSIDE] = false;
// Queenside
- if (piece.getType() == Type.KING || piece.getType() == Type.ROOK && initialPosition.x == 0)
+ if (piece instanceof King || piece instanceof Rook && initialPosition.x == 0)
castlingRights[piece.getColor() == Color.WHITE ? MoveNode.WHITE_QUEENSIDE : MoveNode.BLACK_QUEENSIDE] = false;
}
diff --git a/src/dev/kske/chess/board/Pawn.java b/src/dev/kske/chess/board/Pawn.java
index 3f7ddf9..177abba 100644
--- a/src/dev/kske/chess/board/Pawn.java
+++ b/src/dev/kske/chess/board/Pawn.java
@@ -82,5 +82,5 @@ public class Pawn extends Piece {
}
@Override
- public Type getType() { return Type.PAWN; }
+ public int getValue() { return 10; }
}
diff --git a/src/dev/kske/chess/board/Piece.java b/src/dev/kske/chess/board/Piece.java
index 5fc1fd6..848dca5 100644
--- a/src/dev/kske/chess/board/Piece.java
+++ b/src/dev/kske/chess/board/Piece.java
@@ -57,9 +57,7 @@ public abstract class Piece implements Cloneable {
* @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();
- }
+ protected final boolean checkDestination(Move move) { return board.getDest(move) == null || board.getDest(move).getColor() != getColor(); }
@Override
public Object clone() {
@@ -72,14 +70,11 @@ public abstract class Piece implements Cloneable {
return piece;
}
- public abstract Type getType();
-
- public Color getColor() { return color; }
+ @Override
+ public String toString() { return getClass().getSimpleName(); }
@Override
- public int hashCode() {
- return Objects.hash(color);
- }
+ public int hashCode() { return Objects.hash(color); }
@Override
public boolean equals(Object obj) {
@@ -90,52 +85,50 @@ public abstract class Piece implements Cloneable {
return color == other.color;
}
- public static enum Type {
+ /**
+ * @return the standard value of this {@link Piece} that can be used for board
+ * evaluation
+ */
+ public abstract int getValue();
- KING, QUEEN, ROOK, KNIGHT, BISHOP, PAWN;
+ /**
+ * @return The first character of this {@link Piece} in algebraic notation and
+ * lower case
+ */
+ public char firstChar() { return Character.toLowerCase(toString().charAt(0)); }
- /**
- * @return The first character of this {@link Type} in algebraic notation and
- * lower case
- */
- public char firstChar() {
- return this == KNIGHT ? 'n' : Character.toLowerCase(this.toString().charAt(0));
- }
-
- public static Type fromFirstChar(char firstChar) {
- switch (Character.toLowerCase(firstChar)) {
- case 'k':
- return KING;
- case 'q':
- return QUEEN;
- case 'r':
- return ROOK;
- case 'n':
- return KNIGHT;
- case 'b':
- return BISHOP;
- case 'p':
- return PAWN;
- default:
- return null;
- }
+ 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; }
+
public static enum Color {
WHITE, BLACK;
- public static Color fromFirstChar(char c) {
- return Character.toLowerCase(c) == 'w' ? WHITE : BLACK;
- }
+ public static Color fromFirstChar(char c) { return Character.toLowerCase(c) == 'w' ? WHITE : BLACK; }
- public char firstChar() {
- return this == WHITE ? 'w' : 'b';
- }
+ public char firstChar() { return this == WHITE ? 'w' : 'b'; }
- public Color opposite() {
- return this == WHITE ? BLACK : WHITE;
- }
+ public Color opposite() { return this == WHITE ? BLACK : WHITE; }
}
}
diff --git a/src/dev/kske/chess/board/Queen.java b/src/dev/kske/chess/board/Queen.java
index 3932b95..b2482ce 100644
--- a/src/dev/kske/chess/board/Queen.java
+++ b/src/dev/kske/chess/board/Queen.java
@@ -101,5 +101,5 @@ public class Queen extends Piece {
}
@Override
- public Type getType() { return Type.QUEEN; }
+ public int getValue() { return 90; }
}
diff --git a/src/dev/kske/chess/board/Rook.java b/src/dev/kske/chess/board/Rook.java
index 590e49e..b2efd5c 100644
--- a/src/dev/kske/chess/board/Rook.java
+++ b/src/dev/kske/chess/board/Rook.java
@@ -65,5 +65,5 @@ public class Rook extends Piece {
}
@Override
- public Type getType() { return Type.ROOK; }
+ public int getValue() { return 50; }
}
diff --git a/src/dev/kske/chess/game/ai/MoveProcessor.java b/src/dev/kske/chess/game/ai/MoveProcessor.java
index 2c73ddd..112bc30 100644
--- a/src/dev/kske/chess/game/ai/MoveProcessor.java
+++ b/src/dev/kske/chess/game/ai/MoveProcessor.java
@@ -5,10 +5,16 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
+import dev.kske.chess.board.Bishop;
import dev.kske.chess.board.Board;
+import dev.kske.chess.board.King;
+import dev.kske.chess.board.Knight;
import dev.kske.chess.board.Move;
+import dev.kske.chess.board.Pawn;
+import dev.kske.chess.board.Piece;
import dev.kske.chess.board.Piece.Color;
-import dev.kske.chess.board.Piece.Type;
+import dev.kske.chess.board.Queen;
+import dev.kske.chess.board.Rook;
/**
* Project: Chess
@@ -28,35 +34,35 @@ public class MoveProcessor implements Callable {
private Move bestMove;
- private static final Map positionScores;
+ private static final Map, int[][]> positionScores;
static {
positionScores = new HashMap<>();
- positionScores.put(Type.KING,
+ positionScores.put(King.class,
new int[][] { new int[] { -3, -4, -4, -5, -5, -4, -4, -3 }, new int[] { -3, -4, -4, -5, -4, -4, -4, -3 },
new int[] { -3, -4, -4, -5, -4, -4, -4, -3 }, new int[] { -3, -4, -4, -5, -4, -4, -4, -3 },
new int[] { -2, -3, -3, -2, -2, -2, -2, -1 }, new int[] { -1, -2, -2, -2, -2, -2, -2, -1 },
new int[] { 2, 2, 0, 0, 0, 0, 2, 2 }, new int[] { 2, 3, 1, 0, 0, 1, 3, 2 } });
- positionScores.put(Type.QUEEN,
+ positionScores.put(Queen.class,
new int[][] { new int[] { -2, -1, -1, -1, -1, -1, -1, -2 }, new int[] { -1, 0, 0, 0, 0, 0, 0, -1 },
new int[] { -1, 0, 1, 1, 1, 1, 0, -1 }, new int[] { -1, 0, 1, 1, 1, 1, 0, -1 }, new int[] { 0, 0, 1, 1, 1, 1, 0, -1 },
new int[] { -1, 1, 1, 1, 1, 1, 0, -1 }, new int[] { -1, 0, 1, 0, 0, 0, 0, -1 },
new int[] { -2, -1, -1, -1, -1, -1, -1, -2 } });
- positionScores.put(Type.ROOK,
+ positionScores.put(Rook.class,
new int[][] { new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }, new int[] { 1, 1, 1, 1, 1, 1, 1, 1 }, new int[] { -1, 0, 0, 0, 0, 0, 0, -1 },
new int[] { -1, 0, 0, 0, 0, 0, 0, -1 }, new int[] { -1, 0, 0, 0, 0, 0, 0, -1 }, new int[] { -1, 0, 0, 0, 0, 0, 0, -1 },
new int[] { -1, 0, 0, 0, 0, 0, 0, -1 }, new int[] { 0, 0, 0, 1, 1, 0, 0, 0 } });
- positionScores.put(Type.KNIGHT,
+ positionScores.put(Knight.class,
new int[][] { new int[] { -5, -4, -3, -3, -3, -3, -4, -5 }, new int[] { -4, -2, 0, 0, 0, 0, -2, -4 },
new int[] { -3, 0, 1, 2, 2, 1, 0, -3 }, new int[] { -3, 1, 2, 2, 2, 2, 1, -3 }, new int[] { -3, 0, 2, 2, 2, 2, 0, -1 },
new int[] { -3, 1, 1, 2, 2, 1, 1, -3 }, new int[] { -4, -2, 0, 1, 1, 0, -2, -4 },
new int[] { -5, -4, -3, -3, -3, -3, -4, -5 } });
- positionScores.put(Type.BISHOP,
+ positionScores.put(Bishop.class,
new int[][] { new int[] { -2, -1, -1, -1, -1, -1, -1, 2 }, new int[] { -1, 0, 0, 0, 0, 0, 0, -1 },
new int[] { -1, 0, 1, 1, 1, 1, 0, -1 }, new int[] { -1, 1, 1, 1, 1, 1, 1, -1 }, new int[] { -1, 0, 1, 1, 1, 1, 0, -1 },
new int[] { -1, 1, 1, 1, 1, 1, 1, -1 }, new int[] { -1, 1, 0, 0, 0, 0, 1, -1 },
new int[] { -2, -1, -1, -1, -1, -1, -1, -2 } });
- positionScores.put(Type.PAWN,
+ positionScores.put(Pawn.class,
new int[][] { new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }, new int[] { 5, 5, 5, 5, 5, 5, 5, 5 }, new int[] { 1, 1, 2, 3, 3, 2, 1, 1 },
new int[] { 0, 0, 1, 3, 3, 1, 0, 0 }, new int[] { 0, 0, 0, 2, 2, 0, 0, 0 }, new int[] { 0, 0, -1, 0, 0, -1, 0, 0 },
new int[] { 0, 1, 1, -2, -2, 1, 1, 0 }, new int[] { 0, 0, 0, 0, 0, 0, 0, 0 } });
@@ -108,25 +114,9 @@ public class MoveProcessor implements Callable {
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
if (board.getBoardArr()[i][j] != null && board.getBoardArr()[i][j].getColor() == color) {
- switch (board.getBoardArr()[i][j].getType()) {
- case QUEEN:
- score += 90;
- break;
- case ROOK:
- score += 50;
- break;
- case KNIGHT:
- score += 30;
- break;
- case BISHOP:
- score += 30;
- break;
- case PAWN:
- score += 10;
- break;
- }
- if (positionScores.containsKey(board.getBoardArr()[i][j].getType()))
- score += positionScores.get(board.getBoardArr()[i][j].getType())[i][color == Color.WHITE ? j : 7 - j];
+ score += board.getBoardArr()[i][j].getValue();
+ if (positionScores.containsKey(board.getBoardArr()[i][j].getClass()))
+ score += positionScores.get(board.getBoardArr()[i][j].getClass())[i][color == Color.WHITE ? j : 7 - j];
}
return score;
}
diff --git a/src/dev/kske/chess/io/TextureUtil.java b/src/dev/kske/chess/io/TextureUtil.java
index 25ac288..79d251b 100644
--- a/src/dev/kske/chess/io/TextureUtil.java
+++ b/src/dev/kske/chess/io/TextureUtil.java
@@ -37,7 +37,7 @@ public class TextureUtil {
* @return The fitting texture
*/
public static Image getPieceTexture(Piece piece) {
- String key = piece.getType().toString().toLowerCase() + "_" + piece.getColor().toString().toLowerCase();
+ String key = piece.toString().toLowerCase() + "_" + piece.getColor().toString().toLowerCase();
return scaledTextures.get(key);
}