diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index e5d3d02102..19a9bca79d 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -1,10 +1,13 @@
# Contributors
-Display | Name | Github Profile | Homepage
----|:---:|:---:|:---:
-![](https://avatars0.githubusercontent.com/u/22460123?s=100) | Jeffry Lum | [Github](https://github.com/j-lum/) | [Homepage](https://se.kasugano.moe)
-![](https://avatars0.githubusercontent.com/u/1673303?s=100) | Damith C. Rajapakse | [Github](https://github.com/damithc/) | [Homepage](https://www.comp.nus.edu.sg/~damithch/)
-![]() | Ou Ningxiang | [Github](https://github.com/onx001/) | [Homepage](https://github.com/onx001)
+Name | Github Profile
+---|:---:
+Antriksh Dhand | [Github](https://github.com/antrikshdhand/)
+Ou Ningxiang | [Github](https://github.com/onx001/)
+Oh Ken Wei | [Github](https://github.com/ken-ruster/)
+Tong Zheng Hong | [Github](https://://github.com/TongZhengHong/)
+Tricia Boo Koh | [Github](https://://github.com/TriciaBK/)
# I would like to join this list. How can I help the project
-For more information, please refer to our [contributor's guide](https://oss-generic.github.io/process/).
+
+For more information, please refer to our [contributor's guide](README.md#contributing).
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 703e1ea854..7c16118b83 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -118,10 +118,9 @@ How the minimax algorithm works:
5. The `getBestMove` method returns the best move for the CPU to make.
### Move types
-The Move class and its subclasses are responsible for handling the different types of moves in chess.
-The Move class is an abstract class that is extended by the following subclasses: StandardMove, PawnOpening, CastleMove, EnPassantMove and PromotionMove.
-The Move class is also extended by the following classes: CastleSide, Direction, MoveDirection, MoveType and PromotionPiece.
-Below is a class diagram representing the Move class.
+The Move class and its subclasses are responsible for handling the different types of moves in chess. The Move class is a parent class of several move types: CastleMove, EnPassantMove and PromoteMove. The MoveFactory class is responsible for generating the correct move type.
+
+Below is a class diagram representing the parent Move class.
![](images/MoveClass.png)
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index 85ad5d2389..737b7993cc 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -70,9 +70,9 @@ However, if you prefer to **start a fresh game** or if **no previous game is fou
Choose your starting color to start new game! [b/w/exit]
```
-Next, you can choose the difficulty of the AI you will be pitched against! The current supported difficulty levels range from 1 to 4. Please enter the number corresponding to your preferred difficulty level.
+Next, you can choose the difficulty of the AI you will be pitched against! The current supported difficulty levels range from 1 to 3. Please enter the number corresponding to your preferred difficulty level.
```
-Choose your difficulty level! [1/2/3/4/exit]
+Choose your difficulty level! [1/2/3/exit]
```
Inputs that are not compliant with the expect input (indicated in `[]`) will be rejected and users will be prompted to re-input.
@@ -94,7 +94,7 @@ Additionally, every time a move is executed, ChessMaster provides a comprehensiv
-
+
move d2 d4
_________________________________________________________________
@@ -162,9 +162,7 @@ _________________________________________________________________
The game will automatically end and a victor be declared when one side has been checkmated, or if both players are stuck in a stalemate situation where neither player can avoid moving into a checked position.
-Checkmate is the point in the game where the attacking player has the opponent's king in a situation where it can't escape being captured on the next move.
-
-The king is "trapped" and has no safe squares to move to, and no other pieces can help.
+Checkmate is the point in the game where the attacking player has the opponent's king in a situation where it can't escape being captured on the next move. The king is "trapped" and has no safe squares to move to, and no other pieces can help.
Otherwise, you may use the `exit` command if you wish to end the game midway and quit the program or `restart` command to start a new game.
@@ -180,7 +178,7 @@ Examples:
- `move a2 a4`
- `move b3 g6`
-ChessMaster also automatically checks if the move was valid and legal before it is executed. If the move is valid, an output as shown above in the [Gameplay](#gameplay) section will be output. Else, the following error
+ChessMaster automatically checks if the move is valid and legal before it is executed. If the move is valid, an output as shown above in the [Gameplay](#gameplay) section will be output. Else, the following error
message will be shown:
`Oops, that move isn't valid!`
@@ -291,26 +289,29 @@ Objective:
_________________________________________________________________
```
-#### Further details of special rules
+#### 1. Castling
-1. Castling
+For the move to be valid:
+- It's the king's first move.
+- It's the rook's first move.
+- There are no pieces between the king and the rook.
+- The king is not in check and the king will not be in check after castling
- For the move to be valid:
- - It's the king's first move.
- - It's the rook's first move.
- - There are no pieces between the king and the rook.
- - The king is not in check and the king will not be in check after castling
-
- To perform castling on either sides:
- - Move your king two squares to the right/left (towards the rook).
- - The rook will jump over the king and land on the square next to the king.
+To perform castling on either sides:
+- Move your king two squares to the right/left (towards the rook).
+- The rook will jump over the king and land on the square next to the king.
- Example of castling availability: `moves e1`
+Examples and expected output:
- Expected Output:
+
+
+ Castling availability: moves e1 |
+ Execute castle move: moves e1 c1 |
+
+
+
-
- (a) (b) (c) (d) (e) (f) (g) (h)
+ (a) (b) (c) (d) (e) (f) (g) (h)
_________________________________
(8) | R | | | | K | | | R | (8)
_________________________________
@@ -328,26 +329,23 @@ _________________________________________________________________
_________________________________
(1) | r | |[.]|[.]|{k}| b | n | r | (1)
_________________________________
- (a) (b) (c) (d) (e) (f) (g) (h)
-
- _________________________________________________________________
+ (a) (b) (c) (d) (e) (f) (g) (h)
- Available coordinates for King at e1:
- e2 d1 d2 c1
- _________________________________________________________________
-
+_________________________________________________________________
- Example: `move e1 c1`
+Available coordinates for King at e1:
+e2 d1 d2 c1
+_________________________________________________________________
- Expected Output:
+ |
+
-
- _________________________________________________________________
+_________________________________________________________________
- You moved King from e1 to c1
- _________________________________________________________________
+You moved King from e1 to c1
+_________________________________________________________________
- (a) (b) (c) (d) (e) (f) (g) (h)
+ (a) (b) (c) (d) (e) (f) (g) (h)
_________________________________
(8) | R | | | | K | | | R | (8)
_________________________________
@@ -365,75 +363,82 @@ _________________________________________________________________
_________________________________
(1) | | |(k)| r |( )| b | n | r | (1)
_________________________________
- (a) (b) (c) (d) (e) (f) (g) (h)
-
+ (a) (b) (c) (d) (e) (f) (g) (h)
-2. En Passant:
-
- This move only happens when your opponent moves their pawn two squares forward from its starting position and lands next to your pawn.
- To capture en passant, you must do it on your very next move.
- - Move your pawn diagonally forward to the square that your opponent's pawn would have occupied if it had moved only one square forward.
+ |
+
+
- Sample previous board:
+#### 2. En Passant:
-
- _________________________________________________________________
+This move only happens when your opponent moves their pawn two squares forward from its starting position and lands next to your pawn.
+To capture en passant, you must do it on your very next move.
+- Move your pawn diagonally forward to the square that your opponent's pawn would have occupied if it had moved only one square forward.
- ChessMaster moved Pawn from e7 to e5
- _________________________________________________________________
+
+
+ Sample board before en passant |
+ Executing en passant move: move d5 e6 |
+
+
+
- (a) (b) (c) (d) (e) (f) (g) (h)
- _________________________________
- (8) | R | | B | Q | K | B | | R | (8)
- _________________________________
- (7) | P | P | P | P |( )| P | P | P | (7)
- _________________________________
- (6) | | | N | | | | | | (6)
- _________________________________
- (5) | | | | p |(P)| | | | (5)
- _________________________________
- (4) | | | | | | | | | (4)
- _________________________________
- (3) | | | | | | | | | (3)
- _________________________________
- (2) | p | p | | | p | p | p | p | (2)
- _________________________________
- (1) | r | n | b | q | k | b | n | r | (1)
- _________________________________
- (a) (b) (c) (d) (e) (f) (g) (h)
-
+_________________________________________________________________
- Example: `move d5 e6`
+ChessMaster moved Pawn from e7 to e5
+_________________________________________________________________
- Expected output:
+ (a) (b) (c) (d) (e) (f) (g) (h)
+ _________________________________
+ (8) | R | | B | Q | K | B | | R | (8)
+ _________________________________
+ (7) | P | P | P | P |( )| P | P | P | (7)
+ _________________________________
+ (6) | | | N | | | | | | (6)
+ _________________________________
+ (5) | | | | p |(P)| | | | (5)
+ _________________________________
+ (4) | | | | | | | | | (4)
+ _________________________________
+ (3) | | | | | | | | | (3)
+ _________________________________
+ (2) | p | p | | | p | p | p | p | (2)
+ _________________________________
+ (1) | r | n | b | q | k | b | n | r | (1)
+ _________________________________
+ (a) (b) (c) (d) (e) (f) (g) (h)
-
- (a) (b) (c) (d) (e) (f) (g) (h)
- _________________________________
- (8) | R | | B | Q | K | B | | R | (8)
- _________________________________
- (7) | P | P | P | P | | P | P | P | (7)
- _________________________________
- (6) | | | N | |(p)| | | | (6)
- _________________________________
- (5) | | | |( )| | | | | (5)
- _________________________________
- (4) | | | | | | | | | (4)
- _________________________________
- (3) | | | | | | | | | (3)
- _________________________________
- (2) | p | p | | | p | p | p | p | (2)
- _________________________________
- (1) | r | n | b | q | k | b | n | r | (1)
- _________________________________
- (a) (b) (c) (d) (e) (f) (g) (h)
+
|
+
+
+_________________________________________________________________
+
+You moved Pawn from d5 to e6
+_________________________________________________________________
- _________________________________________________________________
+ (a) (b) (c) (d) (e) (f) (g) (h)
+ _________________________________
+ (8) | R | | B | Q | K | B | | R | (8)
+ _________________________________
+ (7) | P | P | P | P | | P | P | P | (7)
+ _________________________________
+ (6) | | | N | |(p)| | | | (6)
+ _________________________________
+ (5) | | | |( )| | | | | (5)
+ _________________________________
+ (4) | | | | | | | | | (4)
+ _________________________________
+ (3) | | | | | | | | | (3)
+ _________________________________
+ (2) | p | p | | | p | p | p | p | (2)
+ _________________________________
+ (1) | r | n | b | q | k | b | n | r | (1)
+ _________________________________
+ (a) (b) (c) (d) (e) (f) (g) (h)
- Available coordinates for Pawn at d5:
- e6 c6 d6
- _________________________________________________________________
-
+ |
+
+
### Show commands: `help`
@@ -528,8 +533,8 @@ _________________________________________________________________
### Step back in history: `stepback`
-Displays the board state as it was a certain number of moves ago. Note that this command does not reverse any moves
-in the current game.
+Displays the board state as it was a certain number of moves ago. **Note that this command does not reverse any moves
+in the current game.**
Format: `stepback [number of moves to step back]`
@@ -565,7 +570,6 @@ Use `show` to see the current board.
_________________________________________________________________
```
-
### List pieces in play: `captured`
Lists each player's pieces grouped by whether they have been captured or not.
@@ -632,6 +636,21 @@ Every time a turn ends, ChessMaster will save the current state of the game. Whe
user will be prompted to choose whether to load the saved game or begin a new one. ChessMaster only supports a single
saved game, and starting a new one will delete the existing save file.
+### Editing the storage file
+Tasks data are saved automatically in a text (.txt) file `/data/ChessMaster.txt`. Users are welcome to update data directly by editing this data file to achieve a desired game state.
+
+The format of the saved game in the storage file is as follows:
+
+```json
+[CURRENT_PLAYER_COLOR] // Either BLACK or WHITE
+[GAME_DIFFICULTY] // Integer from 1 - 3
+[NEXT_TURN_COLOR] // Either BLACK or WHITE
+[HUMAN_MOVE_HISTORY] // delimited by ','
+[CPU_MOVE_HISTORY] // delimited by ','
+[CHESS_BOARD_PIECE] // Next 8 lines of 8 characters each
+[hasMoved_FLAGS] // Next 8 lines of 8 characters each
+```
+
## FAQ
> **Q**: How do I transfer my data to another computer?
diff --git a/docs/diagrams/MoveSequence.puml b/docs/diagrams/MoveSequence.puml
index ec7ed18939..c296663ffc 100644
--- a/docs/diagrams/MoveSequence.puml
+++ b/docs/diagrams/MoveSequence.puml
@@ -23,7 +23,9 @@ g -> cb : move :Move
deactivate g
activate cb
cb -> cb : isValidMove()
+activate cb
cb --> cb : :boolean
+deactivate cb
alt Move is valid
create mf
cb -> mf : createMove()
diff --git a/docs/images/MoveSequence.png b/docs/images/MoveSequence.png
index 67481e64b4..9d2fc1522c 100644
Binary files a/docs/images/MoveSequence.png and b/docs/images/MoveSequence.png differ
diff --git a/docs/team/antrikshdhand.md b/docs/team/antrikshdhand.md
index 4c49307f4b..738d1a170e 100644
--- a/docs/team/antrikshdhand.md
+++ b/docs/team/antrikshdhand.md
@@ -1,17 +1,39 @@
-# Project Portfolio Page [DRAFT]
+# Project Portfolio Page
+
+By Antriksh Dhand (@antrikshdhand)
## Overview
+I primarily focused on enhancing the gameplay experience and ensuring the robustness of the codebase. I implemented new key commands, refactored existing code for an improved object-oriented design, and explored end-to-end testing strategies.
+
## Contributions
### Code contributed
+Check out my contributions on the [TP Dashboard](https://nus-cs2113-ay2324s1.github.io/tp-dashboard/?search=antrikshdhhttps://nus-cs2113-ay2324s1.github.io/tp-dashboard/?search=antrikshdhand&breakdown=truehttps://nus-cs2113-ay2324s1.github.io/tp-dashboard/?search=antrikshdhand&breakdown=truehttps://nus-cs2113-ay2324s1.github.io/tp-dashboard/?search=antrikshdhand&breakdown=trueand&breakdown=true).
+
### Enhancements implemented
-### Contributions to the UG
+#### `captured`, `history`, and `stepback` Commands
+
+I implemented the `captured`, `history`, and `stepback` commands, allowing the player access to commands they would generally expect to see in a modern chess game. The `stepback` command posed a unique challenge, requiring a deep dive into move reversal mechanisms. This effort involved significant code refactoring to promote cleaner, more object-oriented structures.
+
+#### Object-Oriented Design Refactoring
+
+To enhance code maintainability and extensibility, I introduced sub-classes such as `CastleMove` and `EnPassantMove`. Additionally, the implementation of the `MoveFactory` class, adopting the Factory method pattern, has streamlined the creation of Move objects. This in turn fed into making the reversal of moves much more cleaner to implement and more robust overall. I also encouraged and administered the use of SLAP in our codebase.
+
+### Contributions to the User Guide (UG)
+
+While not introducing new major sections, I diligently maintained the UG by documenting my new commands and ensuring that information stays relevant and up to date.
+
+### Contributions to the Developer Guide (DG)
+
+#### End-to-End Testing Section
+
+I made substantial progress in establishing end-to-end testing for the CLI. Despite not achieving full completion, I laid the groundwork and documented the process in the DG, providing a valuable resource for future testing efforts. You can see a stub of this code in the DG.
-### Contributions to the DG
+### General Contributions
-### Contributions to team-based tasks
+Regularly contributed to team discussions, providing insights and assistance where needed.
-### Review/mentoring contributions
\ No newline at end of file
+Actively participated in code reviews and offered constructive feedback to enhance overall code quality.
\ No newline at end of file
diff --git a/docs/team/ken-ruster.md b/docs/team/ken-ruster.md
index 264998f16d..0c74f5ec61 100644
--- a/docs/team/ken-ruster.md
+++ b/docs/team/ken-ruster.md
@@ -7,41 +7,51 @@ and its simplicity means that even low-end machines should be able to run it.
### Code contributions: [RepoSense Link](https://nus-cs2113-ay2324s1.github.io/tp-dashboard/?search=ken-ruster&breakdown=false&sort=groupTitle%20dsc&sortWithin=title&since=2023-09-22&timeframe=commit&mergegroup=&groupSelect=groupByRepos)
Given below are my contributions to the project:
-- **New Feature**: Move class
- - A class representing a move to be made.
- - Includes the coordinates from and to of the move, as well as the piece involved to check for validity later.
-- **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.
- - How it works:
- - Move history is stored in the .txt file
- - When the game is loaded, the moves are executed in the exact order they were stored in.
- - The board it was executed on then is passed into the Game to be run after being checked against the saved board state.
- - By doing this, we are able to ensure the History, Stepback and Captured commands are able to work normally after a saved game is loaded.
-- **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, including:
- - `parsePromote`
- - `ShowMovesCommand`
- - `executeSavedMoves`, `loadHumanMoves()` and `loadCPUMoves()` in `Storage`
- - `executeMoveArray` in `ChessBoard`
-- **Documentation**:
- - Developer Guide:
- - Added documentation for the `Parser` and `Command` subclasses
- - User Guide:
- - Added documentation for the Features section
- - Updated the Command Summary
- - Added and wrote the FAQ section
+### **New Feature**: Move class
+- A class representing a move to be made.
+- Includes the coordinates from and to of the move, as well as the piece involved to check for validity later.
+### **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 of the saved file.
+ It required implementing a `PromoteMove` class as well to store possible promotions.
+- How it works:
+ - Move history is stored in the .txt file
+ - When the game is loaded, the file reads the moves of the human and CPU, and merges them to form a single array.
+ - Each of the moves in the array are parsed and executed in the exact order they were stored in.
+ - The board it was executed on then is passed into the Game to be run after being checked against the saved board state.
+ - By doing this, we are able to ensure the History, Stepback and Captured commands are able to work normally after a saved game is loaded.
+### **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.
+- How it works:
+ - Game checks for pieces able to promoted at the end of each move
+ - User is prompted to promote a piece, and the input is parsed to return a new piece
+ - The pawn to be promoted is replaced with the new piece
+### **Project Management**:
+- Set up GitHub organisation and repo
+- Managed repo branch security settings
+- Maintained issue tracker
+- Managed bug testing and checkStyle adherence for releases `1.0` and `2.0`
+### **Enhancements to existing features**:
+- Added additional tests for existing features, including:
+ - `parsePromote`
+ - `ShowMovesCommand`
+ - `executeSavedMoves`, `loadHumanMoves()` and `loadCPUMoves()` in `Storage`
+ - `executeMoveArray` in `ChessBoard`
+### **Documentation**:
+- Developer Guide:
+ - Added documentation for the `Parser` and `Command` subclasses
+ - Added sequence diagram for move parsing
+ - Added class diagram describing `Parser` and `Command`
+- User Guide:
+ - Added documentation for the Features section
+ - Updated the Command Summary
+ - Added and wrote the FAQ section
diff --git a/docs/team/onx001.md b/docs/team/onx001.md
index 18010f1f23..0183e53ec5 100644
--- a/docs/team/onx001.md
+++ b/docs/team/onx001.md
@@ -18,9 +18,21 @@ The move validity of the chesspieces is determined by the `isValidMove()` method
I implemented this alongside various non-standard chess moves, such as castling and en passant in a manner that minimised code coupling and enabled other developers to have a more bug-free experience.
+### Reposense
+
+My code contributions can be found on the [TP Dashboard](https://github.com/AY2324S1-CS2113-T18-1/tp/commit/fa0fa79e972d3c962461120070ca65f00bfff965).
+
### Project Management
I solved bugs and issues that arose from the integration of the Minimax algorithm and the move validity of the chesspieces. I also managed the bug testing and checkstyle adherence, and delivered key features in a timely manner which allowed for other developers to have a longer runway for implementing their features.
### Documentation
-I documented the `Minimax` class and algorithm with a sequence diagram, as well as the `Move` class and the various types of moves available. I also added documentation in the user guide for castling and en passant, as well as the difficulty of the game. In addition, I polished and edited the user guide to make it more comprehensive about the various features ChessMaster has to offer.
+
+#### Developer's Guide
+I documented the `Minimax` class and algorithm with a sequence diagram, as well as the `Move` class and the various types of moves available. I also added a sequence diagram and a class diagram of the `Move` class.
+
+### User's Guide
+I added documentation in the user guide for castling and en passant, as well as the difficulty of the game. In addition, I polished and edited the user guide to make it more comprehensive about the various features ChessMaster has to offer.
+
+### Team-based tasks
+I added several issues and reviewed several PRs, and helped to manage the project board. An example can be found [in this pull request](https://github.com/AY2324S1-CS2113-T18-1/tp/pull/182) and [in this issue](https://github.com/AY2324S1-CS2113-T18-1/tp/issues/185). I also submitted various bugs for other teams such as [here](https://github.com/AY2324S1-CS2113-F11-1/tp/issues/58).
\ No newline at end of file
diff --git a/src/main/java/chessmaster/ChessMaster.java b/src/main/java/chessmaster/ChessMaster.java
index ecd863b2db..cdacf1b7f3 100644
--- a/src/main/java/chessmaster/ChessMaster.java
+++ b/src/main/java/chessmaster/ChessMaster.java
@@ -37,7 +37,7 @@ private ChessMaster() {
try {
playerColor = storage.loadPlayerColor();
difficulty = storage.loadDifficulty();
- currentTurnColor = storage.loadCurrentColor();
+
//@@author ken_ruster
ChessTile[][] existingBoardState = storage.loadBoard();
ChessBoard existingBoard = new ChessBoard(playerColor, existingBoardState);
@@ -47,6 +47,8 @@ private ChessMaster() {
storage.executeSavedMoves(playerColor, existingBoard, board, human, cpu);
board.setDifficulty(difficulty);
+ currentTurnColor = getCurrentTurnColor(human, cpu, playerColor);
+
if (shouldStartNewGame() && !exit) {
loadNewGame();
}
@@ -56,6 +58,21 @@ private ChessMaster() {
}
}
+ private Color getCurrentTurnColor(Human human, CPU cpu, Color playerColor) throws ChessMasterException {
+ int noHumanMoves = human.getMovesLength();
+ int noCPUMoves = cpu.getMovesLength();
+
+ if (noHumanMoves == noCPUMoves) {
+ return playerColor;
+ } else if (noHumanMoves > noCPUMoves && playerColor.isWhite()
+ || noHumanMoves < noCPUMoves && playerColor.isBlack()) {
+ return playerColor.getOppositeColour();
+ }
+
+ throw new ChessMasterException(
+ "Moves in save file are invalid! Please start a new game or correct the error");
+ }
+
private boolean shouldStartNewGame() {
ui.promptContinuePrevGame(false);
String input = ui.getUserInput(false);
diff --git a/src/main/java/chessmaster/game/Game.java b/src/main/java/chessmaster/game/Game.java
index 24dee0042e..37c96fdc7f 100644
--- a/src/main/java/chessmaster/game/Game.java
+++ b/src/main/java/chessmaster/game/Game.java
@@ -32,7 +32,6 @@ public class Game {
private Command command;
private boolean hasEnded;
- private boolean exit = false;
public Game(Color playerColour, Color currentTurnColor, ChessBoard board,
Storage storage, TextUI ui, int difficulty, Human human, CPU cpu) {
diff --git a/src/main/java/chessmaster/storage/Storage.java b/src/main/java/chessmaster/storage/Storage.java
index 94a68bb02a..48445a855a 100644
--- a/src/main/java/chessmaster/storage/Storage.java
+++ b/src/main/java/chessmaster/storage/Storage.java
@@ -11,7 +11,7 @@
import chessmaster.pieces.ChessPiece;
import chessmaster.user.CPU;
import chessmaster.user.Human;
-
+import chessmaster.user.Player;
import java.io.File;
import java.io.FileNotFoundException;
@@ -167,7 +167,7 @@ public ChessTile[][] loadBoard() throws ChessMasterException {
int rowIndex = 0;
ChessTile[][] boardTiles = new ChessTile[ChessBoard.SIZE][ChessBoard.SIZE];
while (rowIndex < ChessBoard.SIZE && fileScanner.hasNext()) {
- String chessRowLine = fileScanner.nextLine();
+ String chessRowLine = fileScanner.nextLine().trim();
if (chessRowLine.length() != ChessBoard.SIZE) {
fileScanner.close();
throw new LoadBoardException();
@@ -195,7 +195,7 @@ public ChessTile[][] loadBoard() throws ChessMasterException {
rowIndex = 0;
while (rowIndex < ChessBoard.SIZE && fileScanner.hasNext()) {
- String chessRowLine = fileScanner.nextLine();
+ String chessRowLine = fileScanner.nextLine().trim();
if (chessRowLine.length() != ChessBoard.SIZE) {
fileScanner.close();
throw new LoadBoardException();
@@ -231,12 +231,33 @@ public ChessBoard executeSavedMoves(Color playerColor,
ChessBoard board,
Human human,
CPU cpu) throws ChessMasterException {
- ArrayList moveStringList = new ArrayList();
+ ArrayList moveStringList = new ArrayList();
ArrayList humanMoves = loadHumanMoves();
ArrayList cpuMoves = loadCPUMoves();
+ if (cpuMoves.size() > humanMoves.size() && playerColor.isWhite()
+ || cpuMoves.size() < humanMoves.size() && playerColor.isBlack()) {
+ throw new ChessMasterException(
+ "Moves in save file are invalid! Please start a new game or correct the error");
+ }
+
// Merge move string arrays into a singular array
- if (playerColor.isWhite()) {
+ boolean isPlayerTurn = playerColor.isWhite();
+ int noOfMoves = humanMoves.size() + cpuMoves.size();
+
+ for (int i = 0; i < noOfMoves; i ++) {
+ int turnIndex = i / 2;
+ if (isPlayerTurn && humanMoves.size() >= turnIndex + 1) {
+ moveStringList.add(humanMoves.get(turnIndex));
+ } else if (cpuMoves.size() >= turnIndex + 1) {
+ moveStringList.add(cpuMoves.get(turnIndex));
+ }
+
+ isPlayerTurn = !isPlayerTurn;
+ }
+
+ /*
+ if (playerColor.isWhite() && humanMoves.size() == cpuMoves.size()) {
for (String move : humanMoves) {
moveStringList.add(move);
}
@@ -244,7 +265,23 @@ public ChessBoard executeSavedMoves(Color playerColor,
for (int i = 0; i < cpuMoves.size(); i ++) {
moveStringList.add(2 * i + 1, cpuMoves.get(i));
}
- } else if (playerColor.isBlack()) {
+ } else if (playerColor.isBlack() && humanMoves.size() == cpuMoves.size()) {
+ for (String move : cpuMoves) {
+ moveStringList.add(move);
+ }
+
+ for (int i = 0; i < humanMoves.size(); i ++) {
+ moveStringList.add(2 * i + 1, humanMoves.get(i));
+ }
+ } else if (playerColor.isWhite() && humanMoves.size() > cpuMoves.size()) {
+ for (String move : humanMoves) {
+ moveStringList.add(move);
+ }
+
+ for (int i = 0; i < cpuMoves.size(); i ++) {
+ moveStringList.add(2 * i + 1, cpuMoves.get(i));
+ }
+ } else if (playerColor.isBlack() && humanMoves.size() > cpuMoves.size()) {
for (String move : cpuMoves) {
moveStringList.add(move);
}
@@ -255,6 +292,7 @@ public ChessBoard executeSavedMoves(Color playerColor,
} else {
throw new LoadBoardException();
}
+ */
//Execute move string Array
board.executeMoveArray(moveStringList, human, cpu);
@@ -287,7 +325,7 @@ public ChessBoard executeSavedMoves(Color playerColor,
//@@author onx001
- private boolean isPieceValid (ChessPiece initialPiece) {
+ private boolean isPieceValid(ChessPiece initialPiece) {
if (initialPiece.isBlackKing()) {
if (blackKingPresent) {
return false;
@@ -339,8 +377,8 @@ public Color loadPlayerColor() throws ChessMasterException {
}
if (fileScanner.hasNext()) {
- String colorLine = fileScanner.nextLine();
- Color playerColor = Parser.parsePlayerColor(colorLine);
+ String colorLine = fileScanner.nextLine().trim();
+ Color playerColor = Parser.parsePlayerColor(colorLine.toUpperCase());
fileScanner.close();
return playerColor;
@@ -373,7 +411,7 @@ public int loadDifficulty() throws ChessMasterException {
if (fileScanner.hasNext()) {
try {
- String difficultyLine = fileScanner.nextLine();
+ String difficultyLine = fileScanner.nextLine().trim();
int difficulty = Parser.parseDifficulty(difficultyLine);
fileScanner.close();
@@ -390,6 +428,7 @@ public int loadDifficulty() throws ChessMasterException {
throw new LoadBoardException();
}
+
//@@author TriciaBK
/**
* Loads the current turn player's
@@ -414,8 +453,8 @@ public Color loadCurrentColor() throws ChessMasterException {
}
if (fileScanner.hasNext()) {
- String currentColorString = fileScanner.nextLine();
- Color color = Parser.parsePlayerColor(currentColorString);
+ String currentColorString = fileScanner.nextLine().trim();
+ Color color = Parser.parsePlayerColor(currentColorString.toUpperCase());
fileScanner.close();
return color;
}
@@ -424,6 +463,7 @@ public Color loadCurrentColor() throws ChessMasterException {
throw new LoadBoardException();
}
+
public String getFilePath() {
return this.filePathString;
}
@@ -455,11 +495,12 @@ public ArrayList loadHumanMoves() throws ChessMasterException {
ArrayList out = new ArrayList();
if (fileScanner.hasNext()) {
- String[] movesArray = fileScanner.nextLine().split(", ");
+ String movesString = fileScanner.nextLine().trim();
+ String[] movesArray = movesString.split(Player.MOVE_DELIMITER);
Arrays.stream(movesArray)
.sequential()
.filter(x -> !x.equals(""))
- .forEach(x -> out.add(x));
+ .forEach(x -> out.add(x.trim()));
}
fileScanner.close();
@@ -492,11 +533,12 @@ public ArrayList loadCPUMoves() throws ChessMasterException {
ArrayList out = new ArrayList();
if (fileScanner.hasNext()) {
- String[] movesArray = fileScanner.nextLine().split(", ");
+ String movesString = fileScanner.nextLine().trim();
+ String[] movesArray = movesString.split(Player.MOVE_DELIMITER);
Arrays.stream(movesArray)
.sequential()
.filter(x -> !x.equals(""))
- .forEach(x -> out.add(x));
+ .forEach(x -> out.add(x.trim()));
}
fileScanner.close();
diff --git a/src/main/java/chessmaster/ui/UiMessages.java b/src/main/java/chessmaster/ui/UiMessages.java
index 97bbbbfa98..dc4d553bfa 100644
--- a/src/main/java/chessmaster/ui/UiMessages.java
+++ b/src/main/java/chessmaster/ui/UiMessages.java
@@ -17,7 +17,8 @@ public class UiMessages {
"Invalid input! Please enter either 'y' for yes or 'n' for no: ";
public static final String CONTINUE_PREV_GAME_MESSAGE = "Great! Continuing previous game as %s at difficulty %d";
- public static final String CHOOSE_PLAYER_COLOR_MESSAGE = "Choose your starting color to start new game! [b/w/exit]";
+ public static final String CHOOSE_PLAYER_COLOR_MESSAGE =
+ "Choose your starting color to start new game! [b/w/exit] ";
public static final String CHOOSE_PLAYER_COLOR_ERROR_MESSAGE =
"Invalid input! Please enter either 'b' for Black or 'w' for White: ";
public static final String START_NEW_GAME_MESSAGE = "Great! Starting new game as %s";
diff --git a/src/main/java/chessmaster/user/Player.java b/src/main/java/chessmaster/user/Player.java
index 8b46fba337..3e8689b0db 100644
--- a/src/main/java/chessmaster/user/Player.java
+++ b/src/main/java/chessmaster/user/Player.java
@@ -10,7 +10,7 @@
public abstract class Player {
- private static final String MOVE_DELIMITER = ", ";
+ public static final String MOVE_DELIMITER = ",";
protected ArrayList moves;
protected ArrayList pieces;
|