Added castling, fixed some minor bugs
This commit is contained in:
parent
199d2f06c6
commit
58340ca6ac
@ -50,7 +50,7 @@ public class Board implements Cloneable {
|
||||
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, -2 } });
|
||||
new int[] { -1, 1, 0, 0, 0, 0, 1, -1 }, new int[] { -2, -1, -1, -1, -1, -1, -1, -2 } });
|
||||
positionScores.put(Type.PAWN,
|
||||
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 },
|
||||
@ -75,6 +75,9 @@ public class Board implements Cloneable {
|
||||
Piece piece = getPos(move);
|
||||
if (piece == null || !piece.isValidMove(move)) return false;
|
||||
else {
|
||||
// Set type after validation
|
||||
if (move.type == Move.Type.UNKNOWN) move.type = Move.Type.NORMAL;
|
||||
|
||||
// Move piece
|
||||
move(move);
|
||||
|
||||
@ -104,13 +107,34 @@ public class Board implements Cloneable {
|
||||
// TODO: Select promotion
|
||||
setDest(move, new Queen(piece.getColor(), this));
|
||||
break;
|
||||
case CASTLING:
|
||||
// Move the king
|
||||
setDest(move, piece);
|
||||
setPos(move, null);
|
||||
|
||||
// Move the rook
|
||||
Move rookMove = move.dest.x == 6 ? new Move(7, move.pos.y, 5, move.pos.y) // Kingside
|
||||
: new Move(0, move.pos.y, 3, move.pos.y); // Queenside
|
||||
|
||||
// Move the rook
|
||||
setDest(rookMove, getPos(rookMove));
|
||||
setPos(rookMove, null);
|
||||
|
||||
getDest(rookMove).incMoveCounter();
|
||||
break;
|
||||
case UNKNOWN:
|
||||
System.err.printf("Unknown move %s found!%n", move);
|
||||
System.err.printf("Move of unknown type %s found!%n", move);
|
||||
case NORMAL:
|
||||
setDest(move, piece);
|
||||
setPos(move, null);
|
||||
break;
|
||||
default:
|
||||
System.err.printf("Move %s of unimplemented type found!%n", move);
|
||||
}
|
||||
|
||||
// Increment move counter
|
||||
getDest(move).incMoveCounter();
|
||||
|
||||
// Update the king's position if the moved piece is the king
|
||||
if (piece.getType() == Type.KING) kingPos.put(piece.getColor(), move.dest);
|
||||
|
||||
@ -127,19 +151,38 @@ public class Board implements Cloneable {
|
||||
Piece capturedPiece = loggedMove.capturedPiece;
|
||||
|
||||
switch (move.type) {
|
||||
case CASTLING:
|
||||
case EN_PASSANT:
|
||||
case PAWN_PROMOTION:
|
||||
setPos(move, new Pawn(getDest(move).getColor(), this));
|
||||
setDest(move, capturedPiece);
|
||||
break;
|
||||
case CASTLING:
|
||||
// Move the king
|
||||
setPos(move, getDest(move));
|
||||
setDest(move, null);
|
||||
|
||||
// Move the rook
|
||||
Move rookMove = move.dest.x == 6 ? new Move(5, move.pos.y, 7, move.pos.y) // Kingside
|
||||
: new Move(3, move.pos.y, 0, move.pos.y); // Queenside
|
||||
|
||||
// Move the rook
|
||||
setDest(rookMove, getPos(rookMove));
|
||||
setPos(rookMove, null);
|
||||
|
||||
getDest(rookMove).decMoveCounter();
|
||||
break;
|
||||
case UNKNOWN:
|
||||
System.err.printf("Unknown move %s found!%n", move);
|
||||
System.err.printf("Move of unknown type %s found!%n", move);
|
||||
case NORMAL:
|
||||
setPos(move, getDest(move));
|
||||
setDest(move, capturedPiece);
|
||||
break;
|
||||
default:
|
||||
System.err.printf("Move %s of unimplemented type found!%n", move);
|
||||
}
|
||||
|
||||
// Decrement move counter
|
||||
getPos(move).decMoveCounter();
|
||||
|
||||
// Update the king's position if the moved piece is the king
|
||||
if (getPos(move).getType() == Type.KING) kingPos.put(getPos(move).getColor(), move.pos);
|
||||
|
||||
|
@ -17,7 +17,26 @@ public class King extends Piece {
|
||||
|
||||
@Override
|
||||
public boolean isValidMove(Move move) {
|
||||
return move.xDist <= 1 && move.yDist <= 1 && isFreePath(move);
|
||||
// Castling
|
||||
if (getMoveCounter() == 0 && move.xDist == 2 && move.yDist == 0) {
|
||||
|
||||
// Kingside
|
||||
if (board.getBoardArr()[7][move.pos.y] != null && board.getBoardArr()[7][move.pos.y].getType() == Type.ROOK
|
||||
&& isFreePath(new Move(new Position(5, move.pos.y), new Position(7, move.pos.y)))) {
|
||||
move.type = Move.Type.CASTLING;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Queenside
|
||||
if (board.getBoardArr()[0][move.pos.y] != null && board.getBoardArr()[0][move.pos.y].getType() == Type.ROOK
|
||||
&& isFreePath(new Move(new Position(1, move.pos.y), new Position(4, move.pos.y)))) {
|
||||
move.type = Move.Type.CASTLING;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return move.xDist <= 1 && move.yDist <= 1 && checkDestination(move);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -29,9 +48,33 @@ public class King extends Piece {
|
||||
Move move = new Move(pos, new Position(i, j));
|
||||
if (board.getDest(move) == null || board.getDest(move).getColor() != getColor()) moves.add(move);
|
||||
}
|
||||
|
||||
// Castling
|
||||
// TODO: Check attacked squares in between
|
||||
// TODO: Castling out of check?
|
||||
if (getMoveCounter() == 0) {
|
||||
|
||||
// Kingside
|
||||
if (board.getBoardArr()[7][pos.y] != null && board.getBoardArr()[7][pos.y].getType() == Type.ROOK
|
||||
&& isFreePath(new Move(new Position(5, pos.y), new Position(7, pos.y))))
|
||||
moves.add(new Move(pos, new Position(6, pos.y), Move.Type.CASTLING));
|
||||
|
||||
// Queenside
|
||||
if (board.getBoardArr()[0][pos.y] != null && board.getBoardArr()[0][pos.y].getType() == Type.ROOK
|
||||
&& isFreePath(new Move(new Position(1, pos.y), new Position(4, pos.y))))
|
||||
moves.add(new Move(pos, new Position(2, pos.y), Move.Type.CASTLING));
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isFreePath(Move move) {
|
||||
for (int i = move.pos.x, j = move.pos.y; i != move.dest.x || j != move.dest.y; i += move.xSign, j += move.ySign)
|
||||
if (board.getBoardArr()[i][j] != null) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() { return Type.KING; }
|
||||
}
|
||||
|
@ -11,8 +11,9 @@ import java.util.List;
|
||||
*/
|
||||
public abstract class Piece implements Cloneable {
|
||||
|
||||
protected Color color;
|
||||
protected Board board;
|
||||
private final Color color;
|
||||
protected Board board;
|
||||
private int moveCounter;
|
||||
|
||||
public Piece(Color color, Board board) {
|
||||
this.color = color;
|
||||
@ -22,10 +23,9 @@ public abstract class Piece implements Cloneable {
|
||||
public List<Move> getMoves(Position pos) {
|
||||
List<Move> moves = getPseudolegalMoves(pos);
|
||||
for (Iterator<Move> iterator = moves.iterator(); iterator.hasNext();) {
|
||||
Move move = iterator.next();
|
||||
Move move = iterator.next();
|
||||
board.move(move);
|
||||
if (board.checkCheck(getColor()))
|
||||
iterator.remove();
|
||||
if (board.checkCheck(getColor())) iterator.remove();
|
||||
board.revert();
|
||||
}
|
||||
return moves;
|
||||
@ -66,6 +66,16 @@ public abstract class Piece implements Cloneable {
|
||||
|
||||
public Color getColor() { return color; }
|
||||
|
||||
public int getMoveCounter() { return moveCounter; }
|
||||
|
||||
public void incMoveCounter() {
|
||||
++moveCounter;
|
||||
}
|
||||
|
||||
public void decMoveCounter() {
|
||||
--moveCounter;
|
||||
}
|
||||
|
||||
public static enum Type {
|
||||
KING, QUEEN, ROOK, KNIGHT, BISHOP, PAWN
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import dev.kske.chess.board.Board;
|
||||
import dev.kske.chess.board.Move;
|
||||
import dev.kske.chess.board.Move.Type;
|
||||
import dev.kske.chess.board.Piece.Color;
|
||||
import dev.kske.chess.board.Position;
|
||||
import dev.kske.chess.ui.OverlayComponent;
|
||||
@ -49,7 +50,7 @@ public class NaturalPlayer extends Player {
|
||||
|
||||
overlayComponent.clearDots();
|
||||
moveRequested = false;
|
||||
game.onMove(NaturalPlayer.this, new Move(pos, dest));
|
||||
game.onMove(NaturalPlayer.this, new Move(pos, dest, Type.UNKNOWN));
|
||||
pos = null;
|
||||
}
|
||||
}
|
||||
|
@ -79,5 +79,7 @@ public class GameModeDialog extends JDialog {
|
||||
dispose();
|
||||
});
|
||||
getContentPane().add(btnAI2);
|
||||
|
||||
setLocationRelativeTo(null);
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ public class MainWindow {
|
||||
btnRestart.addActionListener((evt) -> System.err.println("Resetting not implemented!"));
|
||||
toolPanel.add(btnRestart);
|
||||
mframe.pack();
|
||||
mframe.setLocationRelativeTo(null);
|
||||
|
||||
// Display dialog for game mode selection
|
||||
new GameModeDialog(boardPane).setVisible(true);
|
||||
|
Reference in New Issue
Block a user