From 4dd5747241e4f5eb09e9560ee790b794bc60d04a Mon Sep 17 00:00:00 2001 From: ken_ruster Date: Fri, 10 Nov 2023 02:03:27 +0800 Subject: [PATCH 1/6] Update class diagrams --- docs/diagrams/ParserCommandDiagram.puml | 2 ++ docs/diagrams/StorageClass.puml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/diagrams/ParserCommandDiagram.puml b/docs/diagrams/ParserCommandDiagram.puml index bb74467858..573b9fde3d 100644 --- a/docs/diagrams/ParserCommandDiagram.puml +++ b/docs/diagrams/ParserCommandDiagram.puml @@ -1,5 +1,7 @@ @startuml 'https://plantuml.com/class-diagram +hide circle +skinparam classAttributeIconSize 0 package command{ abstract class Command { +execute() diff --git a/docs/diagrams/StorageClass.puml b/docs/diagrams/StorageClass.puml index 533aa4ec73..a3153ecba6 100644 --- a/docs/diagrams/StorageClass.puml +++ b/docs/diagrams/StorageClass.puml @@ -1,4 +1,6 @@ @startuml +hide circle +skinparam classAttributeIconSize 0 class Storage { - filePathString: String From a0110a6252d6bdc0f5120771409bcd359890806f Mon Sep 17 00:00:00 2001 From: ken_ruster Date: Fri, 10 Nov 2023 02:31:59 +0800 Subject: [PATCH 2/6] Update sequence diagrams --- docs/diagrams/ChessMasterSequence.puml | 10 +++---- docs/diagrams/GameSequence.puml | 14 ++++----- docs/diagrams/MiniMaxSequence.puml | 4 +-- docs/diagrams/ParseCommandSequence.puml | 40 ++++++++++++------------- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/docs/diagrams/ChessMasterSequence.puml b/docs/diagrams/ChessMasterSequence.puml index 62e9eb2c5c..36ae899363 100644 --- a/docs/diagrams/ChessMasterSequence.puml +++ b/docs/diagrams/ChessMasterSequence.puml @@ -15,7 +15,7 @@ activate storage storage --> chessMaster : prevBoard:ChessBoard deactivate storage -alt [. Previous board exists] +alt Previous board exists chessMaster -> ui : shouldStartNewGame() activate ui @@ -23,9 +23,9 @@ alt [. Previous board exists] ui --> chessMaster : :boolean deactivate ui - opt [startNewGame] + opt startNewGame - chessMaster -> ui : chooseColor + chessMaster -> ui : chooseColor() activate ui user -> ui : "black/white" ui --> chessMaster : playerColor:Color @@ -33,9 +33,9 @@ alt [. Previous board exists] end -else [. No previous board] +else No previous board - chessMaster -> ui : chooseColor + chessMaster -> ui : chooseColor() activate ui user -> ui : "black/white" ui --> chessMaster : playerColor:Color diff --git a/docs/diagrams/GameSequence.puml b/docs/diagrams/GameSequence.puml index c905436dcc..1853041112 100644 --- a/docs/diagrams/GameSequence.puml +++ b/docs/diagrams/GameSequence.puml @@ -10,22 +10,22 @@ participant ":Storage" as storage #PaleTurquoise activate game #AliceBlue -loop [hasGameEnded] +loop hasGameEnded - game -> ui : getUserCommand() + game -> ui : getUserInput() activate ui - user -> ui : "a2 a3" - ui --> game : :String + user -> ui : input + ui --> game : userInputString :String deactivate ui - game -> parser : parseCommand("a2 a3") + game -> parser : parseCommand(userInputString) activate parser parser --> game : :Command deactivate parser - opt [isMoveCommand] + opt isMoveCommand - game -> parser : parseMove("a2 a3") + game -> parser : parseMove(input) activate parser parser --> game : humanMove:Move deactivate parser diff --git a/docs/diagrams/MiniMaxSequence.puml b/docs/diagrams/MiniMaxSequence.puml index 9c806179ef..365bc30629 100644 --- a/docs/diagrams/MiniMaxSequence.puml +++ b/docs/diagrams/MiniMaxSequence.puml @@ -14,7 +14,7 @@ user -> MM : getBestMove() MM -> MM : mostPoints() -loop ["depth < maxDepth"] +loop "depth < maxDepth" MM -> CB : getBoard() deactivate MM @@ -49,7 +49,7 @@ loop ["depth < maxDepth"] deactivate CB CB -> MM : Continue loop deactivate CB - loop ["depth < maxDepth"] + loop "depth < maxDepth" activate MM MM -> MM : Recursively call mostPoints() while incrementing depth MM --> MM : bestTuple diff --git a/docs/diagrams/ParseCommandSequence.puml b/docs/diagrams/ParseCommandSequence.puml index c1f096d359..80080ff983 100644 --- a/docs/diagrams/ParseCommandSequence.puml +++ b/docs/diagrams/ParseCommandSequence.puml @@ -5,43 +5,43 @@ participant ":Game" as Game participant ":Parser" as Parser participant ":Command" as Command participant ":CommandResult" as CommandResult -participant "coord:Coordinate" as Coordinate -participant "board:ChessBoard" as ChessBoard -participant "promoteFrom: ChessPiece" as ChessPiece +participant "coord :Coordinate" as Coordinate +participant "board :ChessBoard" as ChessBoard +participant "promoteFrom :ChessPiece" as ChessPiece -Game -> Parser: parseCommand +Game -> Parser: parseCommand() activate Parser create Command Parser -> Command ++ -Command --> Parser --: Command -Game <-- Parser --: Command +Command --> Parser --: :Command +Game <-- Parser --: :Command Game -> Command ++: execute alt MoveCommand - Command -> Parser ++: parseMove - Parser --> Command --: Move + Command -> Parser ++: parseMove() + Parser --> Command --: :Move else ShowMoveCommand create Coordinate - Command -> Coordinate ++: parseAlgebraicCoor - Coordinate --> Command --: coord - Command -> ChessBoard ++: showAvailableCoordinates + Command -> Coordinate ++: parseAlgebraicCoor() + Coordinate --> Command --: coord :Coordinate + Command -> ChessBoard ++: showAvailableCoordinates() ChessBoard -- - Command -> ChessBoard ++: getAvailableCoordinatesString - ChessBoard --> Command --: String + Command -> ChessBoard ++: getAvailableCoordinatesString() + ChessBoard --> Command --: :String destroy Coordinate end Command -> CommandResult** activate CommandResult CommandResult --> Command-- -Game <-- Command --: CommandResult +Game <-- Command --: :CommandResult opt canPromote -Game -> Parser ++: parsePromote -Parser -> ChessPiece ++: getColour -ChessPiece --> Parser --: Color -Parser -> ChessPiece ++: getPosition -ChessPiece --> Parser --: Coordinate -Game <-- Parser --: ChessPiece +Game -> Parser ++: parsePromote() +Parser -> ChessPiece ++: getColour() +ChessPiece --> Parser --: :Color +Parser -> ChessPiece ++: getPosition() +ChessPiece --> Parser --: :Coordinate +Game <-- Parser --: :ChessPiece end From 17a7572d64a965fbfee41ba299d31a8e3de49868 Mon Sep 17 00:00:00 2001 From: ken_ruster Date: Fri, 10 Nov 2023 02:49:23 +0800 Subject: [PATCH 3/6] Update architecture diagram --- docs/diagrams/OverallArchitecture.puml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/diagrams/OverallArchitecture.puml b/docs/diagrams/OverallArchitecture.puml index a07d2cb3d4..64ed9643a6 100644 --- a/docs/diagrams/OverallArchitecture.puml +++ b/docs/diagrams/OverallArchitecture.puml @@ -21,4 +21,8 @@ game -u-> ui storage .up.> board +game .right.> parser +storage .> parser +board .> parser + @enduml \ No newline at end of file From 665087e5dda0297197b3264b639e213df849ccc1 Mon Sep 17 00:00:00 2001 From: ken_ruster Date: Fri, 10 Nov 2023 12:11:59 +0800 Subject: [PATCH 4/6] Add PPP for ken-ruster --- docs/team/ken-ruster.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 docs/team/ken-ruster.md diff --git a/docs/team/ken-ruster.md b/docs/team/ken-ruster.md new file mode 100644 index 0000000000..73bb5d5b37 --- /dev/null +++ b/docs/team/ken-ruster.md @@ -0,0 +1,33 @@ +# Project: ChessMaster v2.1 + +ChessMaster is a desktop application targeted at chess beginners +for them to be able to learn chess on the go. Users interact with it using the CLI, +and its simplicity means that even low-end machines should be able to run it. + +Given below are my contributions to the project: +- **New Feature**: Checking for the validity of the save file. + - Justification: To make sure that the move history and current board state match. Prevents the user from making + illegal moves via changing the save file. + - Highlights: The implementation required a revision to the structure used to save the file. + It required implementing a `PromoteMove` class as well to store possible promotions. +- **New feature**: Displaying valid moves for a piece + - Justification: New players may not be able to tell how certain pieces move. + This feature assists them in learning how the game works in an accessible manner. + - Highlights: Doing this posed a challenge on how best to display the different possibilities for moves + , eg capturable pieces, current position of the piece and empty tiles it could move to. + Some difficulty arose while learning to go formatting for text highlighting which works + for both Windows and Mac. +- **New feature**: Handling promotion + - Justification: Promotion is an essential mechanic of Chess. + - Highlights: Handling promotion required extensive modification of several classes relating to game function. +- **Project Management**: + - Managed bug testing and checkStyle adherence for releases `1.0` and `2.0` +- **Enhancements to existing features**: + - Added additional tests for existing features +- **Documentation**: + - Developer Guide: + - Added documentation for the `Parser` and `Command` subclasses + - User Guide: + - Added documentation for the Features section + - Updated the Command Summary + - Added the FAQ section From 94b21a262e71ee594096b29cb0392939651a0e02 Mon Sep 17 00:00:00 2001 From: ken_ruster Date: Fri, 10 Nov 2023 12:51:35 +0800 Subject: [PATCH 5/6] Update JavaDoc documentation --- .../java/chessmaster/game/ChessBoard.java | 17 +++++++++- src/main/java/chessmaster/game/Game.java | 32 +++++++++++++++++++ .../java/chessmaster/game/PromoteMove.java | 2 +- src/main/java/chessmaster/parser/Parser.java | 9 ++++++ .../java/chessmaster/pieces/ChessPiece.java | 7 ++++ .../java/chessmaster/storage/Storage.java | 29 +++++++++++++++-- 6 files changed, 92 insertions(+), 4 deletions(-) diff --git a/src/main/java/chessmaster/game/ChessBoard.java b/src/main/java/chessmaster/game/ChessBoard.java index 57a2ea458e..7c7e424874 100644 --- a/src/main/java/chessmaster/game/ChessBoard.java +++ b/src/main/java/chessmaster/game/ChessBoard.java @@ -420,7 +420,12 @@ public ChessBoard clone() { } - + /** + * Converts a String representing a board into a new ChessBoard. + * + * @param board String representing the board + * @return ChessBoard generated from input string + */ public ChessBoard toBoard(String board) { ChessTile[][] boardTiles = new ChessTile[SIZE][SIZE]; int row = 0; @@ -444,6 +449,16 @@ public ChessBoard toBoard(String board) { } //@@author ken-ruster + + /** + * Takes in an array of multiple moves, and executes them in order. Also updates the move history + * stored in the human and CPU objects. + * + * @param moves ArrayList of moves to be executed + * @param human Object representing the human player + * @param cpu Object representing the CPU player + * @throws ChessMasterException + */ public void executeMoveArray(ArrayList moves, Human human, CPU cpu) throws ChessMasterException { boolean isPlayersTurn = playerColor.isWhite(); diff --git a/src/main/java/chessmaster/game/Game.java b/src/main/java/chessmaster/game/Game.java index 07f2ec52d3..da8097f95c 100644 --- a/src/main/java/chessmaster/game/Game.java +++ b/src/main/java/chessmaster/game/Game.java @@ -107,6 +107,14 @@ public boolean run() { return hasEnded || RestartCommand.isRestart(command); } + /** + * Represents main part of gameplay loop for the human user. Responsible for + * taking in the user's input and discerning the user's intention based on the input. + * Also executes and handles all commands except `MoveCommand`. + * + * @return Command corresponding to the user's input + * @throws ChessMasterException + */ private Command getAndExecuteUserCommand() throws ChessMasterException { String userInputString = ui.getUserInput(true); this.command = Parser.parseCommand(userInputString); @@ -116,6 +124,15 @@ private Command getAndExecuteUserCommand() throws ChessMasterException { return this.command; } + /** + * Handles the user input in the case that a move was made by the player. + * Extracts the move from the current command, and reflects the move on the chessboard. + * When the move is done, it also handles any possible promotions which can be made. + * Returns the move which has been made to be printed in the run() function. + * + * @return Move which has been executed + * @throws ChessMasterException + */ private Move handleHumanMove() throws ChessMasterException { Move humanMove = ((MoveCommand) this.command).getMove(); board.executeMoveWithCheck(humanMove); @@ -132,6 +149,14 @@ private Move handleHumanMove() throws ChessMasterException { return humanMove; } + /** + * Obtains and executes the CPU's move in response to the current board state. + * Also prints a message informing the player of the CPU thinking as it may take some time + * to compute the most optimal move in higher difficulty levels. + * + * @return The move that the CPU made + * @throws ChessMasterException + */ private Move handleCPUMove() throws ChessMasterException { ui.printCPUThinkingMessage(); @@ -145,6 +170,13 @@ private Move handleCPUMove() throws ChessMasterException { return cpuMove; } + /** + * Checks whether the current state of the board qualifies as the game having ended. + * If the game has ended, prints a message signalling the end of the game, and resets the saved board. + * + * @return Whether the game has ended + * @throws ChessMasterException + */ private boolean checkEndState() throws ChessMasterException { boolean end = board.isEndGame(); if (end) { diff --git a/src/main/java/chessmaster/game/PromoteMove.java b/src/main/java/chessmaster/game/PromoteMove.java index 22a8843bbb..5a50b8300f 100644 --- a/src/main/java/chessmaster/game/PromoteMove.java +++ b/src/main/java/chessmaster/game/PromoteMove.java @@ -13,7 +13,7 @@ public PromoteMove (Coordinate coord, ChessPiece piece) { * Converts the move to a format to be saved in the .txt file. * Only called after the piece has been promoted to * - * @return + * @return String representing the move */ @Override public String toFileString() { diff --git a/src/main/java/chessmaster/parser/Parser.java b/src/main/java/chessmaster/parser/Parser.java index 54ed760a15..dc578d39eb 100644 --- a/src/main/java/chessmaster/parser/Parser.java +++ b/src/main/java/chessmaster/parser/Parser.java @@ -140,6 +140,15 @@ public static ChessPiece parseChessPiece(String pieceString, int row, int col) { } //@@author + /** + * Parses the user's input to return the appropriate Command. + * Returns an InvalidCommand if the input does not match any of the expected patterns. + * Used to discern the program's appropriate response to the user's input. + * + * @param in User's input, stored as a String + * @return A command corresponding to user input, or InvalidCommand if the input is not recognised + */ + public static Command parseCommand(String in) { String[] splitInputStrings = in.split("\\s+", 2); String commandString = splitInputStrings[0]; diff --git a/src/main/java/chessmaster/pieces/ChessPiece.java b/src/main/java/chessmaster/pieces/ChessPiece.java index 68fb7d0743..fc779f980c 100644 --- a/src/main/java/chessmaster/pieces/ChessPiece.java +++ b/src/main/java/chessmaster/pieces/ChessPiece.java @@ -148,6 +148,13 @@ public void setEnPassant() { } //@@author ken-ruster + /** + * Convert all the possible moves of the piece into a String. + * Returns a message saying that there are no moves available if there are no legal moves the piece can make. + * + * @param board Board the piece is located on + * @return A String containing the coordinates the piece is able to move to + */ public String[] getAvailableCoordinatesString(ChessBoard board) { StringBuilder out = new StringBuilder(); Coordinate[] legalCoordinates = getLegalCoordinates(board); diff --git a/src/main/java/chessmaster/storage/Storage.java b/src/main/java/chessmaster/storage/Storage.java index e855f5aa8b..e903907eb0 100644 --- a/src/main/java/chessmaster/storage/Storage.java +++ b/src/main/java/chessmaster/storage/Storage.java @@ -21,7 +21,8 @@ import java.util.Scanner; public class Storage { - + //@@author ken_ruster + private static final String LOAD_BOARD_MISMATCH_STRING = "Board state does not match state dictated by move history!"; //@@author TriciaBK private String filePathString; private File storageFile; @@ -210,6 +211,16 @@ public ChessTile[][] loadBoard() throws ChessMasterException { return boardTiles; } + /** + * Executes moves saved in the txt file so that it can be checked against the save board state. + * Also stores the saved move history of both the human and CPU. + * + * @param playerColor The color which the player is playing as + * @param otherBoard A temporary board to be compared with the board saved in the .txt file + * @param human Object representing information about the human player + * @param cpu Object representing information about the computer-controlled player + * @throws ChessMasterException + */ public void executeSavedMoves(Color playerColor, ChessBoard otherBoard, Human human, @@ -246,7 +257,7 @@ public void executeSavedMoves(Color playerColor, // Check obtained board with loaded board state if (!board.equals(otherBoard)) { - throw new LoadBoardException("Board state does not match state dictated by move history!"); + throw new LoadBoardException(LOAD_BOARD_MISMATCH_STRING); } } @@ -393,6 +404,13 @@ public String getFilePath() { return this.filePathString; } + /** + * Loads the history of moves made by the human player in the saved game. + * Parses the moves into Move objects, and returns a null array if no moves were found. + * + * @return ArrayList containing the move history of the human player + * @throws ChessMasterException + */ public ArrayList loadHumanMoves() throws ChessMasterException { createChessMasterFile(); @@ -423,6 +441,13 @@ public ArrayList loadHumanMoves() throws ChessMasterException { return out; } + /** + * Loads the history of moves made by the CPU player in the saved game. + * Parses the moves into Move objects, and returns a null array if no moves were found. + * + * @return ArrayList containing the move history of the CPU player + * @throws ChessMasterException + */ public ArrayList loadCPUMoves() throws ChessMasterException { createChessMasterFile(); From c246dabcb7bf26fae361c48ae49314c98112d318 Mon Sep 17 00:00:00 2001 From: ken_ruster Date: Fri, 10 Nov 2023 12:57:54 +0800 Subject: [PATCH 6/6] Fix checkStyle errors --- src/main/java/chessmaster/storage/Storage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/chessmaster/storage/Storage.java b/src/main/java/chessmaster/storage/Storage.java index e903907eb0..d50a5c238c 100644 --- a/src/main/java/chessmaster/storage/Storage.java +++ b/src/main/java/chessmaster/storage/Storage.java @@ -22,7 +22,8 @@ public class Storage { //@@author ken_ruster - private static final String LOAD_BOARD_MISMATCH_STRING = "Board state does not match state dictated by move history!"; + private static final String LOAD_BOARD_MISMATCH_STRING = + "Board state does not match state dictated by move history!"; //@@author TriciaBK private String filePathString; private File storageFile;