change project structure
This commit is contained in:
21
app/src/main/java/chess/controller/Command.java
Normal file
21
app/src/main/java/chess/controller/Command.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package chess.controller;
|
||||
|
||||
import chess.model.Game;
|
||||
|
||||
public abstract class Command {
|
||||
|
||||
public enum CommandResult {
|
||||
/** The command was successfull. Should update display and switch player turn. */
|
||||
Moved,
|
||||
/** The command was successfull. Should not update anything */
|
||||
NotMoved,
|
||||
/** The command was successfull. Should only update display */
|
||||
ActionNeeded,
|
||||
/** The command was not successfull */
|
||||
NotAllowed;
|
||||
}
|
||||
|
||||
public abstract CommandResult execute(Game game, OutputSystem outputSystem);
|
||||
|
||||
public void postExec(Game game, OutputSystem outputSystem) {}
|
||||
}
|
||||
91
app/src/main/java/chess/controller/CommandExecutor.java
Normal file
91
app/src/main/java/chess/controller/CommandExecutor.java
Normal file
@@ -0,0 +1,91 @@
|
||||
package chess.controller;
|
||||
|
||||
import chess.controller.Command.CommandResult;
|
||||
import chess.model.Game;
|
||||
import chess.model.Game.GameStatus;
|
||||
|
||||
public class CommandExecutor {
|
||||
|
||||
private Game game;
|
||||
private OutputSystem outputSystem;
|
||||
|
||||
public CommandExecutor() {
|
||||
this.game = null;
|
||||
this.outputSystem = null;
|
||||
}
|
||||
|
||||
public CommandResult executeCommand(Command command) {
|
||||
assert this.game != null : "No input game specified !";
|
||||
assert this.outputSystem != null : "No output system specified !";
|
||||
|
||||
CommandResult result = command.execute(this.game, this.outputSystem);
|
||||
|
||||
// non player commands are not supposed to return move result
|
||||
assert result != CommandResult.Moved || command instanceof PlayerCommand;
|
||||
|
||||
processResult(command, result);
|
||||
command.postExec(game, outputSystem);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void processResult(Command command, CommandResult result) {
|
||||
switch (result) {
|
||||
case NotAllowed:
|
||||
case NotMoved:
|
||||
return;
|
||||
|
||||
case ActionNeeded:
|
||||
this.outputSystem.updateDisplay();
|
||||
return;
|
||||
|
||||
case Moved:
|
||||
if (checkGameStatus())
|
||||
return;
|
||||
switchPlayerTurn();
|
||||
this.outputSystem.updateDisplay();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void switchPlayerTurn() {
|
||||
this.game.switchPlayerTurn();
|
||||
this.outputSystem.playerTurn(this.game.getPlayerTurn());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return True if the game is over
|
||||
*/
|
||||
private boolean checkGameStatus() {
|
||||
GameStatus gameStatus = this.game.checkGameStatus();
|
||||
|
||||
switch (gameStatus) {
|
||||
case Check:
|
||||
this.outputSystem.kingIsInCheck();
|
||||
return false;
|
||||
|
||||
case CheckMate:
|
||||
this.outputSystem.kingIsInMat();
|
||||
this.outputSystem.winnerIs(this.game.getPlayerTurn());
|
||||
return true;
|
||||
|
||||
case OnGoing:
|
||||
return false;
|
||||
|
||||
case Pat:
|
||||
this.outputSystem.patSituation();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setOutputSystem(OutputSystem outputSystem) {
|
||||
this.outputSystem = outputSystem;
|
||||
}
|
||||
|
||||
public void setGame(Game game) {
|
||||
this.game = game;
|
||||
}
|
||||
|
||||
}
|
||||
25
app/src/main/java/chess/controller/OutputSystem.java
Normal file
25
app/src/main/java/chess/controller/OutputSystem.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package chess.controller;
|
||||
|
||||
import chess.model.Color;
|
||||
import chess.model.Coordinate;
|
||||
|
||||
public interface OutputSystem {
|
||||
|
||||
void playerTurn(Color color);
|
||||
|
||||
void winnerIs(Color color);
|
||||
|
||||
void kingIsInCheck();
|
||||
|
||||
void kingIsInMat();
|
||||
|
||||
void patSituation();
|
||||
|
||||
void hasSurrendered(Color color);
|
||||
|
||||
void gameStarted();
|
||||
|
||||
void promotePawn(Coordinate pieceCoords);
|
||||
|
||||
void updateDisplay();
|
||||
}
|
||||
7
app/src/main/java/chess/controller/PlayerCommand.java
Normal file
7
app/src/main/java/chess/controller/PlayerCommand.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package chess.controller;
|
||||
|
||||
import chess.model.Game;
|
||||
|
||||
public abstract class PlayerCommand extends Command{
|
||||
public abstract void undo(Game game, OutputSystem outputSystem);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package chess.controller.commands;
|
||||
|
||||
import chess.controller.OutputSystem;
|
||||
import chess.controller.PlayerCommand;
|
||||
import chess.model.Game;
|
||||
|
||||
public class CastlingCommand extends PlayerCommand {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||
// we must promote the pending pawn before
|
||||
if (game.pawnShouldBePromoted())
|
||||
return CommandResult.NotAllowed;
|
||||
|
||||
return CommandResult.NotAllowed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo(Game game, OutputSystem outputSystem) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'undo'");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package chess.controller.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import chess.controller.Command;
|
||||
import chess.controller.OutputSystem;
|
||||
import chess.model.ChessBoard;
|
||||
import chess.model.Coordinate;
|
||||
import chess.model.Game;
|
||||
import chess.model.Piece;
|
||||
|
||||
public class GetAllowedMovesCommand extends Command {
|
||||
|
||||
private final Coordinate start;
|
||||
private List<Coordinate> destinations;
|
||||
|
||||
public GetAllowedMovesCommand(Coordinate start) {
|
||||
this.start = start;
|
||||
this.destinations = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||
final ChessBoard board = game.getBoard();
|
||||
Piece piece = board.pieceAt(start);
|
||||
|
||||
if (piece == null)
|
||||
return CommandResult.NotAllowed;
|
||||
|
||||
if (piece.getColor() != game.getPlayerTurn())
|
||||
return CommandResult.NotAllowed;
|
||||
|
||||
this.destinations = board.getAllowedMoves(start);
|
||||
return CommandResult.NotMoved;
|
||||
}
|
||||
|
||||
public List<Coordinate> getDestinations() {
|
||||
return destinations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package chess.controller.commands;
|
||||
|
||||
import chess.controller.Command;
|
||||
import chess.controller.OutputSystem;
|
||||
import chess.model.Coordinate;
|
||||
import chess.model.Game;
|
||||
import chess.model.Piece;
|
||||
|
||||
public class GetPieceAtCommand extends Command{
|
||||
|
||||
private final Coordinate pieceCoords;
|
||||
private Piece piece;
|
||||
|
||||
public GetPieceAtCommand(Coordinate pieceCoords) {
|
||||
this.pieceCoords = pieceCoords;
|
||||
this.piece = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||
if (!pieceCoords.isValid())
|
||||
return CommandResult.NotAllowed;
|
||||
|
||||
this.piece = game.getBoard().pieceAt(pieceCoords);
|
||||
|
||||
return CommandResult.NotMoved;
|
||||
}
|
||||
|
||||
public Piece getPiece() {
|
||||
return piece;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package chess.controller.commands;
|
||||
|
||||
import chess.controller.OutputSystem;
|
||||
import chess.controller.PlayerCommand;
|
||||
import chess.model.Game;
|
||||
|
||||
public class GrandCastlingCommand extends PlayerCommand {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||
// we must promote the pending pawn before
|
||||
if (game.pawnShouldBePromoted())
|
||||
return CommandResult.NotAllowed;
|
||||
|
||||
return CommandResult.NotAllowed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo(Game game, OutputSystem outputSystem) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'undo'");
|
||||
}
|
||||
|
||||
}
|
||||
80
app/src/main/java/chess/controller/commands/MoveCommand.java
Normal file
80
app/src/main/java/chess/controller/commands/MoveCommand.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package chess.controller.commands;
|
||||
|
||||
import chess.controller.OutputSystem;
|
||||
import chess.controller.PlayerCommand;
|
||||
import chess.model.ChessBoard;
|
||||
import chess.model.Coordinate;
|
||||
import chess.model.Game;
|
||||
import chess.model.Move;
|
||||
import chess.model.Piece;
|
||||
import chess.model.visitor.PiecePathChecker;
|
||||
|
||||
public class MoveCommand extends PlayerCommand {
|
||||
|
||||
private final Move move;
|
||||
private Piece deadPiece;
|
||||
|
||||
public MoveCommand(Move move) {
|
||||
this.move = move;
|
||||
this.deadPiece = null;
|
||||
}
|
||||
|
||||
public Move getMove() {
|
||||
return move;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||
final ChessBoard board = game.getBoard();
|
||||
|
||||
// we must promote the pending pawn before
|
||||
if (game.pawnShouldBePromoted())
|
||||
return CommandResult.NotAllowed;
|
||||
|
||||
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;
|
||||
|
||||
this.deadPiece = board.pieceAt(move.getFinish());
|
||||
board.applyMove(move);
|
||||
|
||||
if (board.isKingInCheck(game.getPlayerTurn())) {
|
||||
board.undoLastMove();
|
||||
return CommandResult.NotAllowed;
|
||||
}
|
||||
|
||||
if (game.pawnShouldBePromoted())
|
||||
return CommandResult.ActionNeeded;
|
||||
|
||||
return CommandResult.Moved;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo(Game game, OutputSystem outputSystem) {
|
||||
final ChessBoard board = game.getBoard();
|
||||
|
||||
board.undoMove(move, deadPiece);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postExec(Game game, OutputSystem outputSystem) {
|
||||
tryPromote(game, outputSystem);
|
||||
}
|
||||
|
||||
private void tryPromote(Game game, OutputSystem outputSystem) {
|
||||
Coordinate pawnPos = game.pawnPromotePosition();
|
||||
|
||||
if (pawnPos == null)
|
||||
return;
|
||||
|
||||
outputSystem.promotePawn(pawnPos);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package chess.controller.commands;
|
||||
|
||||
import chess.controller.Command;
|
||||
import chess.controller.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) {
|
||||
final ChessBoard board = game.getBoard();
|
||||
|
||||
board.clearBoard();
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
board.pieceComes(new Pawn(Color.Black), new Coordinate(i, 1));
|
||||
board.pieceComes(new Pawn(Color.White), new Coordinate(i, Coordinate.VALUE_MAX - 2));
|
||||
}
|
||||
|
||||
board.pieceComes(new Rook(Color.Black), new Coordinate(0, 0));
|
||||
board.pieceComes(new Rook(Color.Black), new Coordinate(Coordinate.VALUE_MAX - 1, 0));
|
||||
|
||||
board.pieceComes(new Rook(Color.White), new Coordinate(0, Coordinate.VALUE_MAX - 1));
|
||||
board.pieceComes(new Rook(Color.White), new Coordinate(Coordinate.VALUE_MAX - 1, Coordinate.VALUE_MAX - 1));
|
||||
|
||||
board.pieceComes(new Knight(Color.Black), new Coordinate(1, 0));
|
||||
board.pieceComes(new Knight(Color.Black), new Coordinate(Coordinate.VALUE_MAX - 2, 0));
|
||||
|
||||
board.pieceComes(new Knight(Color.White), new Coordinate(1, Coordinate.VALUE_MAX - 1));
|
||||
board.pieceComes(new Knight(Color.White), new Coordinate(Coordinate.VALUE_MAX - 2, Coordinate.VALUE_MAX - 1));
|
||||
|
||||
board.pieceComes(new Bishop(Color.Black), new Coordinate(2, 0));
|
||||
board.pieceComes(new Bishop(Color.Black), new Coordinate(Coordinate.VALUE_MAX - 3, 0));
|
||||
|
||||
board.pieceComes(new Bishop(Color.White), new Coordinate(2, Coordinate.VALUE_MAX - 1));
|
||||
board.pieceComes(new Bishop(Color.White), new Coordinate(Coordinate.VALUE_MAX - 3, Coordinate.VALUE_MAX - 1));
|
||||
|
||||
board.pieceComes(new Queen(Color.Black), new Coordinate(3, 0));
|
||||
board.pieceComes(new King(Color.Black), new Coordinate(4, 0));
|
||||
|
||||
board.pieceComes(new Queen(Color.White), new Coordinate(3, Coordinate.VALUE_MAX - 1));
|
||||
board.pieceComes(new King(Color.White), new Coordinate(4, Coordinate.VALUE_MAX - 1));
|
||||
|
||||
game.resetPlayerTurn();
|
||||
|
||||
outputSystem.gameStarted();
|
||||
outputSystem.playerTurn(game.getPlayerTurn());
|
||||
|
||||
return CommandResult.NotMoved;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package chess.controller.commands;
|
||||
|
||||
import chess.controller.OutputSystem;
|
||||
import chess.controller.PlayerCommand;
|
||||
import chess.model.ChessBoard;
|
||||
import chess.model.Color;
|
||||
import chess.model.Coordinate;
|
||||
import chess.model.Game;
|
||||
import chess.model.Piece;
|
||||
import chess.model.pieces.Bishop;
|
||||
import chess.model.pieces.Knight;
|
||||
import chess.model.pieces.Pawn;
|
||||
import chess.model.pieces.Queen;
|
||||
import chess.model.pieces.Rook;
|
||||
|
||||
public class PromoteCommand extends PlayerCommand {
|
||||
|
||||
public enum PromoteType {
|
||||
Queen,
|
||||
Rook,
|
||||
Bishop,
|
||||
Knight
|
||||
}
|
||||
|
||||
private final PromoteType promoteType;
|
||||
private Coordinate pieceCoords;
|
||||
|
||||
public PromoteCommand(PromoteType promoteType) {
|
||||
this.promoteType = promoteType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||
final ChessBoard board = game.getBoard();
|
||||
|
||||
this.pieceCoords = game.pawnPromotePosition();
|
||||
|
||||
if (this.pieceCoords == null)
|
||||
return CommandResult.NotAllowed;
|
||||
|
||||
Piece pawn = board.pieceAt(this.pieceCoords);
|
||||
if (pawn == null || !(pawn instanceof Pawn))
|
||||
return CommandResult.NotAllowed;
|
||||
|
||||
int destY = this.pieceCoords.getY();
|
||||
|
||||
int enemyLine = pawn.getColor() == Color.White ? 0 : 7;
|
||||
|
||||
if (destY != enemyLine)
|
||||
return CommandResult.NotAllowed;
|
||||
|
||||
board.pieceComes(createPiece(this.promoteType, pawn.getColor()), this.pieceCoords);
|
||||
|
||||
return CommandResult.Moved;
|
||||
}
|
||||
|
||||
private Piece createPiece(PromoteType promoteType, Color color) {
|
||||
switch (promoteType) {
|
||||
case Queen:
|
||||
return new Queen(color);
|
||||
|
||||
case Bishop:
|
||||
return new Bishop(color);
|
||||
|
||||
case Knight:
|
||||
return new Knight(color);
|
||||
|
||||
case Rook:
|
||||
return new Rook(color);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo(Game game, OutputSystem outputSystem) {
|
||||
final ChessBoard board = game.getBoard();
|
||||
|
||||
Piece promoted = board.pieceAt(this.pieceCoords);
|
||||
|
||||
assert promoted != null;
|
||||
|
||||
Color player = promoted.getColor();
|
||||
board.pieceComes(new Pawn(player), this.pieceCoords);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package chess.controller.commands;
|
||||
|
||||
import chess.controller.Command;
|
||||
import chess.controller.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;
|
||||
}
|
||||
|
||||
}
|
||||
15
app/src/main/java/chess/controller/commands/UndoCommand.java
Normal file
15
app/src/main/java/chess/controller/commands/UndoCommand.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package chess.controller.commands;
|
||||
|
||||
import chess.controller.Command;
|
||||
import chess.controller.OutputSystem;
|
||||
import chess.model.Game;
|
||||
|
||||
public class UndoCommand extends Command{
|
||||
|
||||
@Override
|
||||
public CommandResult execute(Game game, OutputSystem outputSystem) {
|
||||
//TODO
|
||||
return CommandResult.Moved;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user