Added move generation
+ Methods for generating legal and pseudolegal moves in Piece + Implementations of move generation for every piece + Highlighting of available moves for the selected piece in BoardPanel - Split up the move method in Board to move and attemptMove
This commit is contained in:
parent
f710b2d6f7
commit
8158490431
@ -38,22 +38,21 @@ public class Board {
|
||||
initializeDefaultPositions();
|
||||
}
|
||||
|
||||
public boolean move(int xPos, int yPos, int xDest, int yDest) {
|
||||
return move(new Move(xPos, yPos, xDest, yDest));
|
||||
}
|
||||
|
||||
public boolean move(Move move) {
|
||||
/**
|
||||
* Moves a piece across the board if the move is legal.
|
||||
*
|
||||
* @param move The move to execute
|
||||
* @return {@code true}, if the attempted move was legal and thus executed
|
||||
*/
|
||||
public boolean attemptMove(Move move) {
|
||||
Piece piece = getPos(move);
|
||||
if (piece == null || !piece.isValidMove(move)) return false;
|
||||
else {
|
||||
// Move piece
|
||||
// Save destination piece for possible canceling of the move
|
||||
Piece capturePiece = getDest(move);
|
||||
setDest(move, getPos(move));
|
||||
setPos(move, null);
|
||||
|
||||
// Update the king's position if the moved piece is the king
|
||||
if (piece.getType() == Type.KING) kingPos.put(piece.getColor(), move.dest);
|
||||
/*
|
||||
* Move piece
|
||||
* Save destination piece for possible canceling of the move
|
||||
*/
|
||||
Piece capturePiece = move(move);
|
||||
|
||||
// Revert move if it caused a check for its team
|
||||
if (checkCheck(piece.getColor())) {
|
||||
@ -64,13 +63,30 @@ public class Board {
|
||||
// TODO: detecting checkmate
|
||||
// Check for check on the opposite team
|
||||
Color oppositeColor = piece.getColor() == Color.WHITE ? Color.BLACK : Color.WHITE;
|
||||
if (checkCheck(oppositeColor))
|
||||
notifyListeners(new GameEvent(this, GameEventType.CHECK, oppositeColor));
|
||||
if (checkCheck(oppositeColor)) notifyListeners(new GameEvent(this, GameEventType.CHECK, oppositeColor));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a piece across the board without checking if the move is legal.
|
||||
*
|
||||
* @param move The move to execute
|
||||
* @return The captures piece, or null if the move's destination was empty
|
||||
*/
|
||||
public Piece move(Move move) {
|
||||
Piece piece = getPos(move);
|
||||
Piece capturePiece = getDest(move);
|
||||
setDest(move, piece);
|
||||
setPos(move, null);
|
||||
|
||||
// Update the king's position if the moved piece is the king
|
||||
if (piece.getType() == Type.KING) kingPos.put(piece.getColor(), move.dest);
|
||||
|
||||
return capturePiece;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts a move.
|
||||
*
|
||||
@ -86,6 +102,25 @@ public class Board {
|
||||
if (getPos(move).getType() == Type.KING) kingPos.put(getPos(move).getColor(), move.pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generated every legal move for one color
|
||||
*
|
||||
* @param color The color to generate the moves for
|
||||
* @return A list of all legal moves
|
||||
*/
|
||||
public List<Move> getMoves(Color color) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (int j = 0; j < 8; j++)
|
||||
if (boardArr[i][j] != null && boardArr[i][j].getColor() == color)
|
||||
moves.addAll(boardArr[i][j].getMoves(new Position(i, j)));
|
||||
return moves;
|
||||
}
|
||||
|
||||
public List<Move> getMoves(Position pos) {
|
||||
return get(pos).getMoves(pos);
|
||||
}
|
||||
|
||||
public boolean checkCheck(Color color) {
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (int j = 0; j < 8; j++)
|
||||
|
@ -3,11 +3,12 @@ package dev.kske.chess;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
@ -32,12 +33,16 @@ public class BoardPanel extends JPanel implements GameEventListener {
|
||||
private int tileSize;
|
||||
private Board board;
|
||||
|
||||
private List<Move> displayMoves;
|
||||
|
||||
public BoardPanel(Board board) {
|
||||
this();
|
||||
setBoard(board);
|
||||
}
|
||||
|
||||
public BoardPanel() {
|
||||
displayMoves = new ArrayList<>();
|
||||
|
||||
/*
|
||||
* Add a component listener for adjusting the tile size on resizing.
|
||||
* The size of the board is assumed to be 8x8, as well as the both the board and
|
||||
@ -57,16 +62,26 @@ public class BoardPanel extends JPanel implements GameEventListener {
|
||||
// Add a mouse adapter for testing piece movement
|
||||
addMouseListener(new MouseAdapter() {
|
||||
|
||||
private Point src;
|
||||
private Position pos;
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent evt) {
|
||||
if (src == null) src = evt.getPoint();
|
||||
else {
|
||||
Point dest = evt.getPoint();
|
||||
board.move(src.x / tileSize, src.y / tileSize, dest.x / tileSize, dest.y / tileSize);
|
||||
if (pos == null) {
|
||||
pos = new Position(evt.getPoint().x / tileSize, evt.getPoint().y / tileSize);
|
||||
|
||||
if (board.get(pos) != null) {
|
||||
displayMoves.clear();
|
||||
displayMoves.addAll(board.getMoves(pos));
|
||||
repaint();
|
||||
src = null;
|
||||
}
|
||||
} else {
|
||||
Position dest = new Position(evt.getPoint().x / tileSize, evt.getPoint().y / tileSize);
|
||||
|
||||
if (board.attemptMove(new Move(pos, dest))) {
|
||||
displayMoves.clear();
|
||||
repaint();
|
||||
}
|
||||
pos = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -89,6 +104,17 @@ public class BoardPanel extends JPanel implements GameEventListener {
|
||||
for (int j = 0; j < 8; j++)
|
||||
if (board.getBoardArr()[i][j] != null) g.drawImage(TextureUtil
|
||||
.getPieceTexture(board.getBoardArr()[i][j]), i * tileSize, j * tileSize, this);
|
||||
|
||||
// Draw possible moves if a piece was selected
|
||||
if (!displayMoves.isEmpty()) {
|
||||
g.setColor(Color.green);
|
||||
int radius = tileSize / 4;
|
||||
for (Move move : displayMoves)
|
||||
g.fillOval(move.dest.x * tileSize + tileSize / 2 - radius / 2,
|
||||
move.dest.y * tileSize + tileSize / 2 - radius / 2,
|
||||
radius,
|
||||
radius);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,4 +29,9 @@ public class Move {
|
||||
public boolean isVertical() { return xDist == 0; }
|
||||
|
||||
public boolean isDiagonal() { return xDist == yDist; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s -> %s", pos, dest);
|
||||
}
|
||||
}
|
||||
|
@ -14,4 +14,9 @@ public class Position {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%d, %d]", x, y);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package dev.kske.chess.piece;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dev.kske.chess.Board;
|
||||
import dev.kske.chess.Move;
|
||||
import dev.kske.chess.Position;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
@ -28,6 +32,48 @@ public class Bishop extends Piece {
|
||||
return checkDestination(move);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Move> getPseudolegalMoves(Position pos) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
|
||||
// Diagonal moves to the lower right
|
||||
for (int i = pos.x + 1, j = pos.y + 1; i < 8 && j < 8; i++, j++) {
|
||||
Move move = new Move(pos, new Position(i, j));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Diagonal moves to the lower left
|
||||
for (int i = pos.x - 1, j = pos.y + 1; i >= 0 && j < 8; i--, j++) {
|
||||
Move move = new Move(pos, new Position(i, j));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Diagonal moves to the upper right
|
||||
for (int i = pos.x + 1, j = pos.y - 1; i < 8 && j >= 0; i++, j--) {
|
||||
Move move = new Move(pos, new Position(i, j));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Diagonal moves to the upper left
|
||||
for (int i = pos.x - 1, j = pos.y - 1; i >= 0 && j >= 0; i--, j--) {
|
||||
Move move = new Move(pos, new Position(i, j));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() { return Type.BISHOP; }
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package dev.kske.chess.piece;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dev.kske.chess.Board;
|
||||
import dev.kske.chess.Move;
|
||||
import dev.kske.chess.Position;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
@ -20,6 +24,21 @@ public class King extends Piece {
|
||||
return move.xDist <= 1 && move.yDist <= 1 && isFreePath(move);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Move> getPseudolegalMoves(Position pos) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
for (int i = Math.max(0, pos.x - 1); i < Math.min(8, pos.x + 2); i++)
|
||||
for (int j = Math.max(0, pos.y - 1); j < Math.min(8, pos.y + 2); j++)
|
||||
if (i != pos.x || j != pos.y) {
|
||||
Move move = new Move(pos, new Position(i, j));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
}
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() { return Type.KING; }
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package dev.kske.chess.piece;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dev.kske.chess.Board;
|
||||
import dev.kske.chess.Move;
|
||||
import dev.kske.chess.Position;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
@ -20,6 +24,27 @@ public class Knight extends Piece {
|
||||
return Math.abs(move.xDist - move.yDist) == 1 && move.xDist != 0 && move.yDist != 0 && isFreePath(move);
|
||||
}
|
||||
|
||||
private void checkAndInsertMove(List<Move> moves, Position pos, int offsetX, int offsetY) {
|
||||
if (pos.x + offsetX >= 0 && pos.x + offsetX < 8 && pos.y + offsetY >= 0 && pos.y + offsetY < 8) {
|
||||
Move move = new Move(pos, new Position(pos.x + offsetX, pos.y + offsetY));
|
||||
if (checkDestination(move)) moves.add(move);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Move> getPseudolegalMoves(Position pos) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
checkAndInsertMove(moves, pos, -2, 1);
|
||||
checkAndInsertMove(moves, pos, -1, 2);
|
||||
checkAndInsertMove(moves, pos, 1, 2);
|
||||
checkAndInsertMove(moves, pos, 2, 1);
|
||||
checkAndInsertMove(moves, pos, -2, -1);
|
||||
checkAndInsertMove(moves, pos, -1, -2);
|
||||
checkAndInsertMove(moves, pos, 1, -2);
|
||||
checkAndInsertMove(moves, pos, 2, -1);
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() { return Type.KNIGHT; }
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package dev.kske.chess.piece;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dev.kske.chess.Board;
|
||||
import dev.kske.chess.Move;
|
||||
import dev.kske.chess.Position;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
@ -37,6 +41,38 @@ public class Pawn extends Piece {
|
||||
else return board.getDest(move) != null && board.getDest(move).getColor() != getColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Move> getPseudolegalMoves(Position pos) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
|
||||
int sign = getColor() == Color.WHITE ? -1 : 1;
|
||||
|
||||
// Strafe left
|
||||
if (pos.x > 0) {
|
||||
Move move = new Move(pos, new Position(pos.x - 1, pos.y + sign));
|
||||
if (isFreePath(move)) moves.add(move);
|
||||
}
|
||||
|
||||
// Strafe right
|
||||
if (pos.x < 7) {
|
||||
Move move = new Move(pos, new Position(pos.x + 1, pos.y + sign));
|
||||
if (isFreePath(move)) moves.add(move);
|
||||
}
|
||||
|
||||
// Step forward
|
||||
if (sign == 1 && pos.y < 7 || sign == -1 && pos.y > 0) {
|
||||
Move move = new Move(pos, new Position(pos.x, pos.y + sign));
|
||||
if (isFreePath(move)) moves.add(move);
|
||||
}
|
||||
|
||||
// Double step forward
|
||||
if (sign == 1 && pos.y == 1 || sign == -1 && pos.y == 6) {
|
||||
Move move = new Move(pos, new Position(pos.x, pos.y + 2 * sign));
|
||||
if (isFreePath(move)) moves.add(move);
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() { return Type.PAWN; }
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package dev.kske.chess.piece;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import dev.kske.chess.Board;
|
||||
import dev.kske.chess.Move;
|
||||
import dev.kske.chess.Position;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
@ -19,6 +23,20 @@ public abstract class Piece {
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
public List<Move> getMoves(Position pos) {
|
||||
List<Move> moves = getPseudolegalMoves(pos);
|
||||
for (Iterator<Move> iterator = moves.iterator(); iterator.hasNext();) {
|
||||
Move move = iterator.next();
|
||||
Piece capturePiece = board.move(move);
|
||||
if (board.checkCheck(getColor()))
|
||||
iterator.remove();
|
||||
board.revert(move, capturePiece);
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
protected abstract List<Move> getPseudolegalMoves(Position pos);
|
||||
|
||||
public abstract boolean isValidMove(Move move);
|
||||
|
||||
protected boolean isFreePath(Move move) {
|
||||
@ -47,5 +65,9 @@ public abstract class Piece {
|
||||
|
||||
public static enum Color {
|
||||
WHITE, BLACK;
|
||||
|
||||
public Color opposite() {
|
||||
return this == WHITE ? BLACK : WHITE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package dev.kske.chess.piece;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dev.kske.chess.Board;
|
||||
import dev.kske.chess.Move;
|
||||
import dev.kske.chess.Position;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
@ -36,6 +40,84 @@ public class Queen extends Piece {
|
||||
return checkDestination(move);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Move> getPseudolegalMoves(Position pos) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
|
||||
// Horizontal moves to the right
|
||||
for (int i = pos.x + 1; i < 8; i++) {
|
||||
Move move = new Move(pos, new Position(i, pos.y));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Horizontal moves to the left
|
||||
for (int i = pos.x - 1; i >= 0; i--) {
|
||||
Move move = new Move(pos, new Position(i, pos.y));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Vertical moves to the top
|
||||
for (int i = pos.y - 1; i >= 0; i--) {
|
||||
Move move = new Move(pos, new Position(pos.x, i));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Vertical moves to the bottom
|
||||
for (int i = pos.y + 1; i < 8; i++) {
|
||||
Move move = new Move(pos, new Position(pos.x, i));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Diagonal moves to the lower right
|
||||
for (int i = pos.x + 1, j = pos.y + 1; i < 8 && j < 8; i++, j++) {
|
||||
Move move = new Move(pos, new Position(i, j));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Diagonal moves to the lower left
|
||||
for (int i = pos.x - 1, j = pos.y + 1; i >= 0 && j < 8; i--, j++) {
|
||||
Move move = new Move(pos, new Position(i, j));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Diagonal moves to the upper right
|
||||
for (int i = pos.x + 1, j = pos.y - 1; i < 8 && j >= 0; i++, j--) {
|
||||
Move move = new Move(pos, new Position(i, j));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Diagonal moves to the upper left
|
||||
for (int i = pos.x - 1, j = pos.y - 1; i >= 0 && j >= 0; i--, j--) {
|
||||
Move move = new Move(pos, new Position(i, j));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() { return Type.QUEEN; }
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package dev.kske.chess.piece;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dev.kske.chess.Board;
|
||||
import dev.kske.chess.Move;
|
||||
import dev.kske.chess.Position;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
@ -32,6 +36,48 @@ public class Rook extends Piece {
|
||||
return checkDestination(move);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Move> getPseudolegalMoves(Position pos) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
|
||||
// Horizontal moves to the right
|
||||
for (int i = pos.x + 1; i < 8; i++) {
|
||||
Move move = new Move(pos, new Position(i, pos.y));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Horizontal moves to the left
|
||||
for (int i = pos.x - 1; i >= 0; i--) {
|
||||
Move move = new Move(pos, new Position(i, pos.y));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Vertical moves to the top
|
||||
for (int i = pos.y - 1; i >= 0; i--) {
|
||||
Move move = new Move(pos, new Position(pos.x, i));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Vertical moves to the bottom
|
||||
for (int i = pos.y + 1; i < 8; i++) {
|
||||
Move move = new Move(pos, new Position(pos.x, i));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) {
|
||||
moves.add(move);
|
||||
if (board.getDest(move) != null) break;
|
||||
} else break;
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() { return Type.ROOK; }
|
||||
}
|
||||
|
Reference in New Issue
Block a user