lots of things
This commit is contained in:
7
app/src/main/java/chess/io/Command.java
Normal file
7
app/src/main/java/chess/io/Command.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package chess.io;
|
||||||
|
|
||||||
|
import chess.model.Game;
|
||||||
|
|
||||||
|
public abstract class Command {
|
||||||
|
public abstract CommandResult execute(Game game, OutputSystem outputSystem);
|
||||||
|
}
|
||||||
37
app/src/main/java/chess/io/CommandExecutor.java
Normal file
37
app/src/main/java/chess/io/CommandExecutor.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package chess.io;
|
||||||
|
|
||||||
|
import chess.model.Game;
|
||||||
|
|
||||||
|
public class CommandExecutor {
|
||||||
|
|
||||||
|
private final Game game;
|
||||||
|
private final OutputSystem outputSystem;
|
||||||
|
|
||||||
|
public CommandExecutor(Game game, OutputSystem outputSystem) {
|
||||||
|
this.game = game;
|
||||||
|
this.outputSystem = outputSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandResult executeCommand(Command command) {
|
||||||
|
CommandResult result = command.execute(this.game, this.outputSystem);
|
||||||
|
if (result == CommandResult.Moved)
|
||||||
|
alternatePlayers();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void alternatePlayers() {
|
||||||
|
this.game.switchPlayerTurn();
|
||||||
|
this.outputSystem.playerTurn(this.game.getPlayerTurn());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Game getGame() {
|
||||||
|
return game;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputSystem getOutputSystem() {
|
||||||
|
return outputSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
5
app/src/main/java/chess/io/CommandResult.java
Normal file
5
app/src/main/java/chess/io/CommandResult.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package chess.io;
|
||||||
|
|
||||||
|
public enum CommandResult {
|
||||||
|
Moved, NotMoved, NotAllowed;
|
||||||
|
}
|
||||||
8
app/src/main/java/chess/io/OutputSystem.java
Normal file
8
app/src/main/java/chess/io/OutputSystem.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package chess.io;
|
||||||
|
|
||||||
|
public abstract class OutputSystem implements OutputSystemInterface {
|
||||||
|
|
||||||
|
public OutputSystem() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
18
app/src/main/java/chess/io/OutputSystemInterface.java
Normal file
18
app/src/main/java/chess/io/OutputSystemInterface.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package chess.io;
|
||||||
|
|
||||||
|
import chess.model.Color;
|
||||||
|
|
||||||
|
public interface OutputSystemInterface {
|
||||||
|
|
||||||
|
void playerTurn(Color color);
|
||||||
|
|
||||||
|
void winnerIs(Color color);
|
||||||
|
|
||||||
|
void kingIsInCheck();
|
||||||
|
|
||||||
|
void kingIsInMat();
|
||||||
|
|
||||||
|
void patSituation();
|
||||||
|
|
||||||
|
void hasSurrendered(Color color);
|
||||||
|
}
|
||||||
15
app/src/main/java/chess/io/commands/CastlingCommand.java
Normal file
15
app/src/main/java/chess/io/commands/CastlingCommand.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package chess.io.commands;
|
||||||
|
|
||||||
|
import chess.io.Command;
|
||||||
|
import chess.io.CommandResult;
|
||||||
|
import chess.io.OutputSystem;
|
||||||
|
import chess.model.Game;
|
||||||
|
|
||||||
|
public class CastlingCommand extends Command{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||||
|
return CommandResult.NotAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package chess.io.commands;
|
||||||
|
|
||||||
|
import chess.io.Command;
|
||||||
|
import chess.io.CommandResult;
|
||||||
|
import chess.io.OutputSystem;
|
||||||
|
import chess.model.Game;
|
||||||
|
|
||||||
|
public class GrandCastlingCommand extends Command{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||||
|
return CommandResult.NotAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
63
app/src/main/java/chess/io/commands/MoveCommand.java
Normal file
63
app/src/main/java/chess/io/commands/MoveCommand.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package chess.io.commands;
|
||||||
|
|
||||||
|
import chess.io.Command;
|
||||||
|
import chess.io.CommandResult;
|
||||||
|
import chess.io.OutputSystem;
|
||||||
|
import chess.model.ChessBoard;
|
||||||
|
import chess.model.Color;
|
||||||
|
import chess.model.Game;
|
||||||
|
import chess.model.Move;
|
||||||
|
import chess.model.Piece;
|
||||||
|
import chess.model.visitor.PiecePathChecker;
|
||||||
|
|
||||||
|
public class MoveCommand extends Command {
|
||||||
|
private final Move move;
|
||||||
|
|
||||||
|
public MoveCommand(Move move) {
|
||||||
|
this.move = move;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||||
|
final ChessBoard board = game.getBoard();
|
||||||
|
|
||||||
|
Piece piece = board.pieceAt(move.getStart());
|
||||||
|
if (piece == null)
|
||||||
|
return CommandResult.NotAllowed;
|
||||||
|
|
||||||
|
if (piece.getColor() != game.getPlayerTurn())
|
||||||
|
return CommandResult.NotAllowed;
|
||||||
|
|
||||||
|
boolean valid = new PiecePathChecker(board, move).isValid();
|
||||||
|
if (!valid)
|
||||||
|
return CommandResult.NotAllowed;
|
||||||
|
|
||||||
|
board.applyMove(move);
|
||||||
|
|
||||||
|
if (board.isKingInCheck(game.getPlayerTurn())) {
|
||||||
|
board.undoLastMove();
|
||||||
|
return CommandResult.NotAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkGameStatus(game, outputSystem);
|
||||||
|
|
||||||
|
return CommandResult.Moved;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkGameStatus(Game game, OutputSystem outputSystem) {
|
||||||
|
final ChessBoard board = game.getBoard();
|
||||||
|
|
||||||
|
final Color enemy = Color.getEnemy(game.getPlayerTurn());
|
||||||
|
|
||||||
|
if (board.isKingInCheck(enemy)) {
|
||||||
|
if (board.hasAllowedMoves(enemy)) {
|
||||||
|
outputSystem.kingIsInCheck();
|
||||||
|
} else {
|
||||||
|
outputSystem.kingIsInMat();
|
||||||
|
outputSystem.winnerIs(game.getPlayerTurn());
|
||||||
|
}
|
||||||
|
} else if(!board.hasAllowedMoves(enemy)) {
|
||||||
|
outputSystem.patSituation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
app/src/main/java/chess/io/commands/NewGameCommand.java
Normal file
54
app/src/main/java/chess/io/commands/NewGameCommand.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package chess.io.commands;
|
||||||
|
|
||||||
|
import chess.io.Command;
|
||||||
|
import chess.io.CommandResult;
|
||||||
|
import chess.io.OutputSystem;
|
||||||
|
import chess.model.ChessBoard;
|
||||||
|
import chess.model.Color;
|
||||||
|
import chess.model.Coordinate;
|
||||||
|
import chess.model.Game;
|
||||||
|
import chess.model.pieces.Bishop;
|
||||||
|
import chess.model.pieces.King;
|
||||||
|
import chess.model.pieces.Knight;
|
||||||
|
import chess.model.pieces.Pawn;
|
||||||
|
import chess.model.pieces.Queen;
|
||||||
|
import chess.model.pieces.Rook;
|
||||||
|
|
||||||
|
public class NewGameCommand extends Command {
|
||||||
|
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||||
|
ChessBoard board = game.getBoard();
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
board.pieceComes(new Pawn(Color.Black), new Coordinate(i, 0));
|
||||||
|
board.pieceComes(new Pawn(Color.White), new Coordinate(i, Coordinate.VALUE_MAX - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
board.pieceComes(new Rook(Color.Black), new Coordinate(0, 1));
|
||||||
|
board.pieceComes(new Rook(Color.Black), new Coordinate(Coordinate.VALUE_MAX - 1, 1));
|
||||||
|
|
||||||
|
board.pieceComes(new Rook(Color.White), new Coordinate(0, Coordinate.VALUE_MAX - 2));
|
||||||
|
board.pieceComes(new Rook(Color.White), new Coordinate(Coordinate.VALUE_MAX - 1, Coordinate.VALUE_MAX - 2));
|
||||||
|
|
||||||
|
board.pieceComes(new Knight(Color.Black), new Coordinate(1, 1));
|
||||||
|
board.pieceComes(new Knight(Color.Black), new Coordinate(Coordinate.VALUE_MAX - 2, 1));
|
||||||
|
|
||||||
|
board.pieceComes(new Knight(Color.White), new Coordinate(1, Coordinate.VALUE_MAX - 2));
|
||||||
|
board.pieceComes(new Knight(Color.White), new Coordinate(Coordinate.VALUE_MAX - 2, Coordinate.VALUE_MAX - 2));
|
||||||
|
|
||||||
|
board.pieceComes(new Bishop(Color.Black), new Coordinate(2, 1));
|
||||||
|
board.pieceComes(new Bishop(Color.Black), new Coordinate(Coordinate.VALUE_MAX - 3, 1));
|
||||||
|
|
||||||
|
board.pieceComes(new Bishop(Color.White), new Coordinate(2, Coordinate.VALUE_MAX - 2));
|
||||||
|
board.pieceComes(new Bishop(Color.White), new Coordinate(Coordinate.VALUE_MAX - 3, Coordinate.VALUE_MAX - 2));
|
||||||
|
|
||||||
|
board.pieceComes(new Queen(Color.Black), new Coordinate(4, 1));
|
||||||
|
board.pieceComes(new King(Color.Black), new Coordinate(3, 1));
|
||||||
|
|
||||||
|
board.pieceComes(new Queen(Color.White), new Coordinate(4, Coordinate.VALUE_MAX - 2));
|
||||||
|
board.pieceComes(new King(Color.White), new Coordinate(3, Coordinate.VALUE_MAX - 2));
|
||||||
|
|
||||||
|
game.resetPlayerTurn();
|
||||||
|
|
||||||
|
return CommandResult.NotMoved;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
app/src/main/java/chess/io/commands/SurrenderCommand.java
Normal file
24
app/src/main/java/chess/io/commands/SurrenderCommand.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package chess.io.commands;
|
||||||
|
|
||||||
|
import chess.io.Command;
|
||||||
|
import chess.io.CommandResult;
|
||||||
|
import chess.io.OutputSystem;
|
||||||
|
import chess.model.Color;
|
||||||
|
import chess.model.Game;
|
||||||
|
|
||||||
|
public class SurrenderCommand extends Command {
|
||||||
|
|
||||||
|
private final Color player;
|
||||||
|
|
||||||
|
public SurrenderCommand(Color player) {
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||||
|
outputSystem.hasSurrendered(player);
|
||||||
|
outputSystem.winnerIs(Color.getEnemy(player));
|
||||||
|
return CommandResult.NotMoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
package chess.model;
|
package chess.model;
|
||||||
|
|
||||||
import chess.model.pieces.Bishop;
|
import java.util.Stack;
|
||||||
import chess.model.pieces.King;
|
|
||||||
import chess.model.pieces.Knight;
|
|
||||||
import chess.model.pieces.Pawn;
|
|
||||||
import chess.model.pieces.Queen;
|
|
||||||
import chess.model.pieces.Rook;
|
|
||||||
import chess.model.visitor.KingIdentifier;
|
import chess.model.visitor.KingIdentifier;
|
||||||
import chess.model.visitor.PiecePathChecker;
|
import chess.model.visitor.PiecePathChecker;
|
||||||
|
|
||||||
@@ -28,6 +24,8 @@ public class ChessBoard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Cell[][] cells;
|
private final Cell[][] cells;
|
||||||
|
private final Stack<Move> moves;
|
||||||
|
private final Stack<Piece> ejectedPieces;
|
||||||
|
|
||||||
public ChessBoard() {
|
public ChessBoard() {
|
||||||
this.cells = new Cell[Coordinate.VALUE_MAX][Coordinate.VALUE_MAX];
|
this.cells = new Cell[Coordinate.VALUE_MAX][Coordinate.VALUE_MAX];
|
||||||
@@ -36,23 +34,43 @@ public class ChessBoard {
|
|||||||
this.cells[i][j] = new Cell();
|
this.cells[i][j] = new Cell();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initPieces();
|
this.moves = new Stack<>();
|
||||||
|
this.ejectedPieces = new Stack<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyMove(Move move) {
|
public void applyMove(Move move) {
|
||||||
assert (move.isValid());
|
assert (move.isValid());
|
||||||
Piece deadPiece = pieceAt(move.getFinish());
|
Piece deadPiece = pieceAt(move.getFinish());
|
||||||
if (deadPiece != null) {
|
if (deadPiece != null) {
|
||||||
deadPiece.eject();
|
deadPiece.eject(this.moves.size());
|
||||||
|
this.ejectedPieces.add(deadPiece);
|
||||||
}
|
}
|
||||||
Piece movingPiece = pieceAt(move.getStart());
|
Piece movingPiece = pieceAt(move.getStart());
|
||||||
pieceComes(movingPiece, move.getFinish());
|
pieceComes(movingPiece, move.getFinish());
|
||||||
pieceLeaves(move.getStart());
|
pieceLeaves(move.getStart());
|
||||||
movingPiece.move();
|
movingPiece.move();
|
||||||
|
this.moves.add(move);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void undoMove(Move move) {
|
public void undoLastMove() {
|
||||||
// for later
|
assert !this.moves.empty() : "Can't undo at the beginning!";
|
||||||
|
|
||||||
|
Move move = this.moves.pop();
|
||||||
|
|
||||||
|
Piece movingPiece = pieceAt(move.getFinish());
|
||||||
|
pieceComes(movingPiece, move.getStart());
|
||||||
|
pieceLeaves(move.getFinish());
|
||||||
|
movingPiece.unMove();
|
||||||
|
|
||||||
|
if (this.ejectedPieces.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Piece piece = this.ejectedPieces.lastElement();
|
||||||
|
if (piece.getEjectedMoveNumber() != this.moves.size())
|
||||||
|
return;
|
||||||
|
|
||||||
|
pieceComes(piece, move.getFinish());
|
||||||
|
piece.eject(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCellEmpty(Coordinate coordinate) {
|
public boolean isCellEmpty(Coordinate coordinate) {
|
||||||
@@ -77,11 +95,11 @@ public class ChessBoard {
|
|||||||
return this.cells[coordinate.getX()][coordinate.getY()];
|
return this.cells[coordinate.getX()][coordinate.getY()];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pieceComes(Piece piece, Coordinate coordinate) {
|
public void pieceComes(Piece piece, Coordinate coordinate) {
|
||||||
cellAt(coordinate).setPiece(piece);
|
cellAt(coordinate).setPiece(piece);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pieceLeaves(Coordinate coordinate) {
|
public void pieceLeaves(Coordinate coordinate) {
|
||||||
cellAt(coordinate).setPiece(null);
|
cellAt(coordinate).setPiece(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,49 +137,55 @@ public class ChessBoard {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasAllowedMoves(Color player) {
|
||||||
|
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
||||||
|
for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
|
||||||
|
Coordinate attackCoords = new Coordinate(i, j);
|
||||||
|
Piece attackPiece = pieceAt(attackCoords);
|
||||||
|
if (attackPiece == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (attackPiece.getColor() != player)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (getAllowedMoves(attackCoords) != null)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean[][] getAllowedMoves(Coordinate pieceCoords) {
|
public boolean[][] getAllowedMoves(Coordinate pieceCoords) {
|
||||||
Piece piece = pieceAt(pieceCoords);
|
Piece piece = pieceAt(pieceCoords);
|
||||||
if (piece == null)
|
if (piece == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
boolean[][] result = new boolean[Coordinate.VALUE_MAX][Coordinate.VALUE_MAX];
|
Color player = piece.getColor();
|
||||||
|
|
||||||
|
boolean[][] result = new boolean[Coordinate.VALUE_MAX][Coordinate.VALUE_MAX];
|
||||||
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
||||||
for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
|
for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
|
||||||
PiecePathChecker piecePathChecker = new PiecePathChecker(this, new Move(pieceCoords, new Coordinate(i, j)));
|
Move move = new Move(pieceCoords, new Coordinate(i, j));
|
||||||
result[i][j] = piecePathChecker.isValid();
|
PiecePathChecker piecePathChecker = new PiecePathChecker(this,
|
||||||
|
move);
|
||||||
|
if (!piecePathChecker.isValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
applyMove(move);
|
||||||
|
result[i][j] = !isKingInCheck(player);
|
||||||
|
undoLastMove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initPieces() {
|
// return null is no valid moves are possible
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int x = 0; x < 8; x++) {
|
||||||
pieceComes(new Pawn(Color.Black), new Coordinate(i, 0));
|
for (int y = 0; y < 8; y++) {
|
||||||
pieceComes(new Pawn(Color.White), new Coordinate(i, Coordinate.VALUE_MAX - 1));
|
if (result[x][y])
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pieceComes(new Rook(Color.Black), new Coordinate(0, 1));
|
return null;
|
||||||
pieceComes(new Rook(Color.Black), new Coordinate(Coordinate.VALUE_MAX - 1, 1));
|
|
||||||
|
|
||||||
pieceComes(new Rook(Color.White), new Coordinate(0, Coordinate.VALUE_MAX - 2));
|
|
||||||
pieceComes(new Rook(Color.White), new Coordinate(Coordinate.VALUE_MAX - 1, Coordinate.VALUE_MAX - 2));
|
|
||||||
|
|
||||||
pieceComes(new Knight(Color.Black), new Coordinate(1, 1));
|
|
||||||
pieceComes(new Knight(Color.Black), new Coordinate(Coordinate.VALUE_MAX - 2, 1));
|
|
||||||
|
|
||||||
pieceComes(new Knight(Color.White), new Coordinate(1, Coordinate.VALUE_MAX - 2));
|
|
||||||
pieceComes(new Knight(Color.White), new Coordinate(Coordinate.VALUE_MAX - 2, Coordinate.VALUE_MAX - 2));
|
|
||||||
|
|
||||||
pieceComes(new Bishop(Color.Black), new Coordinate(2, 1));
|
|
||||||
pieceComes(new Bishop(Color.Black), new Coordinate(Coordinate.VALUE_MAX - 3, 1));
|
|
||||||
|
|
||||||
pieceComes(new Bishop(Color.White), new Coordinate(2, Coordinate.VALUE_MAX - 2));
|
|
||||||
pieceComes(new Bishop(Color.White), new Coordinate(Coordinate.VALUE_MAX - 3, Coordinate.VALUE_MAX - 2));
|
|
||||||
|
|
||||||
pieceComes(new Queen(Color.Black), new Coordinate(4, 1));
|
|
||||||
pieceComes(new King(Color.Black), new Coordinate(3, 1));
|
|
||||||
|
|
||||||
pieceComes(new Queen(Color.White), new Coordinate(4, Coordinate.VALUE_MAX - 2));
|
|
||||||
pieceComes(new King(Color.White), new Coordinate(3, Coordinate.VALUE_MAX - 2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,9 @@ package chess.model;
|
|||||||
|
|
||||||
public enum Color {
|
public enum Color {
|
||||||
White,
|
White,
|
||||||
Black
|
Black;
|
||||||
|
|
||||||
|
public static Color getEnemy(Color color) {
|
||||||
|
return color == White ? Black : White;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
package chess.model;
|
package chess.model;
|
||||||
|
|
||||||
import chess.model.visitor.PiecePathChecker;
|
|
||||||
import common.Signal0;
|
|
||||||
import common.Signal1;
|
|
||||||
|
|
||||||
public class Game {
|
public class Game {
|
||||||
private final ChessBoard board;
|
private final ChessBoard board;
|
||||||
|
private Color playerTurn;
|
||||||
public final Signal0 OnRenderUpdate = new Signal0();
|
|
||||||
public final Signal1<Move> OnMoveRefused = new Signal1<>();
|
|
||||||
|
|
||||||
public Game(ChessBoard board) {
|
public Game(ChessBoard board) {
|
||||||
this.board = board;
|
this.board = board;
|
||||||
@@ -18,14 +12,28 @@ public class Game {
|
|||||||
return board;
|
return board;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tryMove(Move move) {
|
public Color getPlayerTurn() {
|
||||||
boolean valid = new PiecePathChecker(board, move).isValid();
|
return playerTurn;
|
||||||
if (!valid) {
|
}
|
||||||
this.OnMoveRefused.emit(move);
|
|
||||||
return;
|
public void resetPlayerTurn() {
|
||||||
}
|
this.playerTurn = Color.White;
|
||||||
this.board.applyMove(move);
|
}
|
||||||
this.OnRenderUpdate.emit();
|
|
||||||
|
public void switchPlayerTurn() {
|
||||||
|
playerTurn = Color.getEnemy(playerTurn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean[][] getAllowedMoves(Coordinate coordinate) {
|
||||||
|
Piece piece = this.board.pieceAt(coordinate);
|
||||||
|
|
||||||
|
if (piece == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (piece.getColor() != getPlayerTurn())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return this.board.getAllowedMoves(coordinate);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,17 @@ package chess.model;
|
|||||||
public abstract class Piece {
|
public abstract class Piece {
|
||||||
|
|
||||||
private final Color color;
|
private final Color color;
|
||||||
private boolean moved;
|
private int moved;
|
||||||
|
private int ejectedMoveNumber;
|
||||||
|
|
||||||
public Piece(Color color) {
|
public Piece(Color color) {
|
||||||
this.color = color;
|
this.color = color;
|
||||||
this.moved = false;
|
this.moved = 0;
|
||||||
|
this.ejectedMoveNumber = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void move() {
|
public void move() {
|
||||||
this.moved = true;
|
this.moved++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getColor() {
|
public Color getColor() {
|
||||||
@@ -19,11 +21,23 @@ public abstract class Piece {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasMoved() {
|
public boolean hasMoved() {
|
||||||
return moved;
|
return moved > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void eject() {
|
public void unMove() {
|
||||||
// for later
|
this.moved--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEjected() {
|
||||||
|
return this.ejectedMoveNumber != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEjectedMoveNumber() {
|
||||||
|
return ejectedMoveNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void eject(int moveNumber) {
|
||||||
|
this.ejectedMoveNumber = moveNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract <T> T accept(PieceVisitor<T> visitor);
|
public abstract <T> T accept(PieceVisitor<T> visitor);
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ import javax.swing.JFrame;
|
|||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import chess.io.Command;
|
||||||
|
import chess.io.CommandExecutor;
|
||||||
|
import chess.io.CommandResult;
|
||||||
|
import chess.io.OutputSystem;
|
||||||
|
import chess.io.commands.MoveCommand;
|
||||||
|
import chess.io.commands.NewGameCommand;
|
||||||
import chess.model.ChessBoard;
|
import chess.model.ChessBoard;
|
||||||
import chess.model.Coordinate;
|
import chess.model.Coordinate;
|
||||||
import chess.model.Game;
|
import chess.model.Game;
|
||||||
@@ -17,25 +23,66 @@ import chess.model.Move;
|
|||||||
public class Window extends JFrame {
|
public class Window extends JFrame {
|
||||||
|
|
||||||
private final JLabel cells[][];
|
private final JLabel cells[][];
|
||||||
private final Game game;
|
private final CommandExecutor commandExecutor;
|
||||||
private final ChessBoard board;
|
private final ChessBoard board;
|
||||||
|
|
||||||
private Coordinate lastClick = null;
|
private Coordinate lastClick = null;
|
||||||
|
|
||||||
public Window(Game game) {
|
public Window(Game game) {
|
||||||
this.cells = new JLabel[8][8];
|
this.cells = new JLabel[8][8];
|
||||||
this.game = game;
|
this.commandExecutor = new CommandExecutor(game, initSlots());
|
||||||
this.board = game.getBoard();
|
this.board = this.commandExecutor.getGame().getBoard();
|
||||||
initSlots();
|
|
||||||
build();
|
build();
|
||||||
setSize(800, 800);
|
setSize(800, 800);
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||||
|
sendCommand(new NewGameCommand());
|
||||||
|
updateBoard();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSlots() {
|
private OutputSystem initSlots() {
|
||||||
this.game.OnRenderUpdate.connect(this::updateBoard);
|
OutputSystem outputSystem = new OutputSystem() {
|
||||||
this.game.OnMoveRefused.connect(this::drawInvalid);
|
|
||||||
|
@Override
|
||||||
|
public void playerTurn(chess.model.Color color) {
|
||||||
|
System.out.println("Player turn " + color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void winnerIs(chess.model.Color color) {
|
||||||
|
System.out.println("Winner is " + color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void kingIsInCheck() {
|
||||||
|
System.out.println("Check");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void kingIsInMat() {
|
||||||
|
System.out.println("CheckMate");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void patSituation() {
|
||||||
|
System.out.println("Pat");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hasSurrendered(chess.model.Color color) {
|
||||||
|
System.out.println("Surrendered");
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
return outputSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CommandResult sendCommand(Command command) {
|
||||||
|
CommandResult result = this.commandExecutor.executeCommand(command);
|
||||||
|
if (result == CommandResult.Moved) {
|
||||||
|
updateBoard();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color getCellColor(int x, int y) {
|
private Color getCellColor(int x, int y) {
|
||||||
@@ -77,10 +124,10 @@ public class Window extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void previewMoves(int x, int y) {
|
private boolean previewMoves(int x, int y) {
|
||||||
boolean[][] allowedMoves = this.board.getAllowedMoves(new Coordinate(x, y));
|
boolean[][] allowedMoves = this.commandExecutor.getGame().getAllowedMoves(new Coordinate(x, y));
|
||||||
if (allowedMoves == null)
|
if (allowedMoves == null)
|
||||||
return;
|
return false;
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
for (int j = 0; j < 8; j++) {
|
for (int j = 0; j < 8; j++) {
|
||||||
JLabel cell = this.cells[i][j];
|
JLabel cell = this.cells[i][j];
|
||||||
@@ -88,6 +135,7 @@ public class Window extends JFrame {
|
|||||||
cell.setBackground(Color.CYAN);
|
cell.setBackground(Color.CYAN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawInvalid(Move move) {
|
private void drawInvalid(Move move) {
|
||||||
@@ -111,12 +159,17 @@ public class Window extends JFrame {
|
|||||||
if (this.lastClick == null) {
|
if (this.lastClick == null) {
|
||||||
if (this.board.isCellEmpty(new Coordinate(x, y)))
|
if (this.board.isCellEmpty(new Coordinate(x, y)))
|
||||||
return;
|
return;
|
||||||
|
if (!previewMoves(x, y))
|
||||||
|
return;
|
||||||
this.lastClick = new Coordinate(x, y);
|
this.lastClick = new Coordinate(x, y);
|
||||||
previewMoves(x, y);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.lastClick.equals(new Coordinate(x, y)))
|
if (!this.lastClick.equals(new Coordinate(x, y))) {
|
||||||
this.game.tryMove(new Move(lastClick, new Coordinate(x, y)));
|
Move move = new Move(lastClick, new Coordinate(x, y));
|
||||||
|
if (sendCommand(new MoveCommand(move)) == CommandResult.NotAllowed) {
|
||||||
|
drawInvalid(move);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.lastClick = null;
|
this.lastClick = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user