initial commit

This commit is contained in:
Stanisław Jarocki 2023-06-10 06:55:34 +02:00
commit fc76c43754
25 changed files with 1718 additions and 0 deletions

29
.gitignore vendored Normal file
View File

@ -0,0 +1,29 @@
### IntelliJ IDEA ###
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

6
.idea/misc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_19" default="true" project-jdk-name="openjdk-19" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/chessEngine.iml" filepath="$PROJECT_DIR$/chessEngine.iml" />
</modules>
</component>
</project>

124
.idea/uiDesigner.xml Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

125
.idea/workspace.xml Normal file
View File

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="594d24b9-cb67-479c-bd03-0c89ab1bafab" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Board/Board.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Board/Board.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Game.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Game.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Piece/King.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Piece/King.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Piece/Rook.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Piece/Rook.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Test.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Test.java" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ExternalProjectsManager">
<system id="GRADLE">
<state>
<task path="com.jarocki.stanislaw.chess.Main">
<activation />
</task>
<task path="">
<activation />
</task>
<projects_view />
</state>
</system>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Enum" />
<option value="Class" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProblemsViewState">
<option name="selectedTabId" value="CurrentFile" />
</component>
<component name="ProjectId" id="2QYS6gFlqUJ1sff56xJOBTXQndq" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
<ConfirmationsSetting value="1" id="Add" />
</component>
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;/home/stanlee77/code/chessEngine/src/com/jarocki/stanislaw/chess/Piece&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;reference.settings.project.maven.runner&quot;
}
}</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Piece" />
</key>
<key name="MoveClassesOrPackagesDialog.RECENTS_KEY">
<recent name="com.jarocki.stanislaw.chess" />
</key>
</component>
<component name="RunManager">
<configuration name="Run Main" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="com.jarocki.stanislaw.chess.Main" />
<module name="chessEngine" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="594d24b9-cb67-479c-bd03-0c89ab1bafab" name="Changes" comment="" />
<created>1685528867910</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1685528867910</updated>
</task>
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
<breakpoints>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/com/jarocki/stanislaw/chess/Player/Player.java</url>
<line>6</line>
<option name="timeStamp" value="10" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
<pin-to-top-manager>
<pinned-members>
<PinnedItemInfo parentTag="com.jarocki.stanislaw.chess.Board.Board" memberName="hasWhiteKingMoved" />
<PinnedItemInfo parentTag="com.jarocki.stanislaw.chess.Board.Board" memberName="fields" />
</pinned-members>
</pin-to-top-manager>
</component>
<component name="com.intellij.coverage.CoverageDataManagerImpl">
<SUITE FILE_PATH="coverage/chessEngine$Run_Main.ic" NAME="Run Main Coverage Results" MODIFIED="1687198501398" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="idea" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" />
</component>
</project>

11
chessEngine.iml Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,333 @@
package com.jarocki.stanislaw.chess.Board;
import com.jarocki.stanislaw.chess.Coordinate.Column;
import com.jarocki.stanislaw.chess.Coordinate.Row;
import com.jarocki.stanislaw.chess.Piece.*;
import com.jarocki.stanislaw.chess.Piece.Color;
import java.awt.*;
public class Board {
private final Basic[][] fields;
private boolean hasWhiteKingMoved;
private boolean hasBlackKingMoved;
private Pawn lastMovedPawn;
public Board() {
fields = new Basic[8][8];
this.hasWhiteKingMoved = false;
this.hasBlackKingMoved = false;
this.setUpPieces();
}
public void setUpPieces() {
for (int col = 0; col < 8; col++) {
fields[Row.TWO.getNum()][col] = new Pawn(Color.WHITE, Row.TWO, Column.values()[col]);
fields[Row.SEVEN.getNum()][col] = new Pawn(Color.BLACK, Row.SEVEN, Column.values()[col]);
}
fields[Row.ONE.getNum()][Column.A.getNum()] = new Rook(Color.WHITE, Row.ONE, Column.A);
fields[Row.ONE.getNum()][Column.H.getNum()] = new Rook(Color.WHITE, Row.ONE, Column.H);
fields[Row.EIGHT.getNum()][Column.A.getNum()] = new Rook(Color.BLACK, Row.EIGHT, Column.A);
fields[Row.EIGHT.getNum()][Column.H.getNum()] = new Rook(Color.BLACK, Row.EIGHT, Column.H);
fields[Row.ONE.getNum()][Column.E.getNum()] = new King(Color.WHITE, Row.ONE, Column.E);
fields[Row.EIGHT.getNum()][Column.E.getNum()] = new King(Color.BLACK, Row.EIGHT, Column.E);
fields[Row.ONE.getNum()][Column.D.getNum()] = new Queen(Color.WHITE, Row.ONE, Column.D);
fields[Row.EIGHT.getNum()][Column.D.getNum()] = new Queen(Color.BLACK, Row.EIGHT, Column.D);
fields[Row.ONE.getNum()][Column.B.getNum()] = new Knight(Color.WHITE, Row.ONE, Column.B);
fields[Row.ONE.getNum()][Column.G.getNum()] = new Knight(Color.WHITE, Row.ONE, Column.G);
fields[Row.EIGHT.getNum()][Column.B.getNum()] = new Knight(Color.BLACK, Row.EIGHT, Column.B);
fields[Row.EIGHT.getNum()][Column.G.getNum()] = new Knight(Color.BLACK, Row.EIGHT, Column.G);
fields[Row.ONE.getNum()][Column.C.ordinal()] = new Bishop(Color.WHITE, Row.ONE, Column.C);
fields[Row.ONE.getNum()][Column.F.ordinal()] = new Bishop(Color.WHITE, Row.ONE, Column.F);
fields[Row.EIGHT.getNum()][Column.C.ordinal()] = new Bishop(Color.BLACK, Row.EIGHT, Column.C);
fields[Row.EIGHT.getNum()][Column.F.ordinal()] = new Bishop(Color.BLACK, Row.EIGHT, Column.F);
}
public void movePiece(Column currentColumn, Row currentRow, Column targetColumn, Row targetRow) {
int currRow = currentRow.ordinal();
int currCol = currentColumn.ordinal();
int targRow = targetRow.ordinal();
int targCol = targetColumn.ordinal();
Basic piece = fields[currRow][currCol];
fields[currRow][currCol] = null;
fields[targRow][targCol] = piece;
}
public void printBoard() {
System.out.println();
System.out.print(" ");
for (Column column : Column.values()) {
System.out.print(" " + column.name() + " ");
}
System.out.println();
for (int row = 7; row >= 0; row--) {
System.out.print(Row.values()[row].ordinal() + 1 + " ");
for (int col = 0; col < 8; col++) {
Basic piece = fields[row][col];
boolean isLightPurple = (row + col) % 2 == 0;
boolean isLightBlue = (row + col) % 2 != 0;
if (isLightPurple) {
System.out.print("\u001B[48;5;53m");
} else if (isLightBlue) {
System.out.print("\u001B[48;5;17m");
}
if (piece != null) {
if (piece.getColor() == Color.WHITE) {
System.out.print(" \u001B[93m" + piece.getSymbol().getChar() + " \u001B[0m"); // light yellow - white
} else {
System.out.print(" \u001B[94m" + piece.getSymbol().getChar() + " \u001B[0m"); // black - light blue
}
} else {
System.out.print(" ");
}
}
System.out.println("\u001B[0m");
}
}
public void makeMove(int fromRow, int fromCol, int toRow, int toCol) {
Basic piece = fields[fromRow][fromCol];
fields[fromRow][fromCol] = null;
Row targetRow = Row.getRowByNum(String.valueOf(toRow+1));
Column targetCol = Column.getColByNum(String.valueOf(toCol+1));
piece.setRow(targetRow);
piece.setColumn(targetCol);
// handle pawn promotion to queen
if((toRow == 0 || toRow == 7) && piece.getSymbol().equals(Symbol.PAWN)){
piece.setSymbol(Symbol.QUEEN);
Queen queen = new Queen(piece.getColor(), piece.getRow(), piece.getColumn());
queen.setRow(targetRow);
queen.setColumn(targetCol);
fields[toRow][toCol] = queen;
return;
}
// remove en passant captured pawn from board
if (piece.getSymbol().equals(Symbol.PAWN)) {
Pawn pawn = new Pawn(piece.getColor(), piece.getRow(), piece.getColumn());
if (Math.abs(fromRow - toRow) == 1 && Math.abs(fromCol - toCol) == 1 && fields[toRow][toCol] == null) {
int capturedPawnRow = fromRow;
int capturedPawnCol = toCol;
removePiece(capturedPawnRow, capturedPawnCol);
}
}
// castling check
if (piece.getSymbol().equals(Symbol.KING)) {
King king = new King(piece.getColor(), piece.getRow(), piece.getColumn());
if (Math.abs(fromCol - toCol) == 2) {
// short castling
if (toCol > fromCol) {
// move closer rook
fields[toRow][toCol - 1] = fields[toRow][Column.H.getNum()];
fields[toRow][Column.H.getNum()] = null;
}
// long castling
else {
// move far rook
fields[toRow][toCol + 1] = fields[toRow][Column.A.getNum()];
fields[toRow][Column.A.getNum()] = null;
}
}
// update status of the king
if (piece.getColor() == Color.WHITE) {
this.hasWhiteKingMoved = true;
} else {
this.hasBlackKingMoved = true;
}
} else if (piece.getSymbol().equals(Symbol.PAWN)) {
if (Math.abs(fromRow - toRow) == 2) {
lastMovedPawn = new Pawn(piece.getColor(), piece.getRow(), piece.getColumn());
} else {
lastMovedPawn = null;
}
}
fields[toRow][toCol] = piece;
// en passant, castling
if (piece instanceof King) {
if (piece.getColor() == Color.WHITE) {
this.hasWhiteKingMoved = true;
} else {
this.hasBlackKingMoved = true;
}
} else if (piece instanceof Pawn) {
if (Math.abs(fromRow - toRow) == 2) {
lastMovedPawn = (Pawn) piece;
} else {
lastMovedPawn = null;
}
}
}
public boolean isMoveValid(int fromRow, int fromCol, int toRow, int toCol, Color currPlayerColor) {
// check if not trying to go from or to outside the board
if (fromRow < 0 || fromRow >= 8 || fromCol < 0 || fromCol >= 8 ||
toRow < 0 || toRow >= 8 || toCol < 0 || toCol >= 8) {
System.out.println("Coordinates out of the board! (Board)");
return false;
}
Basic piece = fields[fromRow][fromCol];
// check if there's a piece to pick and move
if (piece == null) {
System.out.println("There's no piece in this field. (Board)");
return false;
}
// make sure the piece belongs to the current player
if (piece.getColor() != currPlayerColor) {
System.out.println("Oh come on, It's not even your piece! (Board)");
return false;
}
// check if target field is not occupied by piece of the same color
if (fields[toRow][toCol] != null && fields[toRow][toCol].getColor() == currPlayerColor) {
System.out.println("There is your piece already! (Board)");
return false;
}
// check stuff specific for particular piece
if (!piece.isMoveValid(toRow, toCol, this)) {
System.out.println("Move invalid for a particular piece. (Board)");
return false;
}
// make sure the move doesnt lead to check
Board tempBoard = copy();
tempBoard.makeMove(fromRow, fromCol, toRow, toCol);
if (tempBoard.isKingInCheck(currPlayerColor)) {
System.out.println("The king is in check!");
return false;
}
return true;
}
public Board copy() {
Board copy = new Board();
// clean the board
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
copy.removePiece(row, col);
}
}
// copyt board state
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
Basic piece = fields[row][col];
if (piece != null) {
Color color = piece.getColor();
Row pieceRow = piece.getRow();
Column pieceCol = piece.getColumn();
copy.setPiece(row, col, piece.copy(color, pieceRow, pieceCol));
}
}
}
// copy other props
copy.hasWhiteKingMoved = this.hasWhiteKingMoved;
copy.hasBlackKingMoved = this.hasBlackKingMoved;
if (this.lastMovedPawn != null) {
int row = this.lastMovedPawn.getRow().getNum();
int col = this.lastMovedPawn.getRow().getNum();
Basic lastMovedPawnCopy = copy.getPiece(row, col);
if(lastMovedPawnCopy != null){
copy.lastMovedPawn = new Pawn(lastMovedPawnCopy.getColor(), lastMovedPawnCopy.getRow(), lastMovedPawnCopy.getColumn());
} else {
copy.lastMovedPawn = null;
}
}
return copy;
}
public void removePiece(int row, int col) {
fields[row][col] = null;
}
public Basic getPiece(int row, int column) {
if (row >= 0 && row < 8 && column >= 0 && column < 8) {
return fields[row][column];
} else {
return null;
}
}
public Pawn getLastMovedPawn() {
return lastMovedPawn;
}
public void setPiece(int row, int col, Basic piece) {
fields[row][col] = piece;
}
public boolean isKingInCheck(Color kingColor) {
int kingRow = -1;
int kingCol = -1;
// find king coordinates
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
Basic piece = fields[row][col];
if (piece != null && piece.getSymbol().equals(Symbol.KING) && piece.getColor() == kingColor) {
kingRow = row;
kingCol = col;
// System.out.println("[DEBUG] " + kingColor + " king is in " + Column.getColByNum(String.valueOf(kingCol + 1)) + String.valueOf(kingRow + 1));
break;
}
}
}
// check for each opponent piece if can take the king out
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
Basic piece = fields[row][col];
if (piece != null && piece.getColor() != kingColor) {
Basic particularPiece = piece;
if(piece.getSymbol().equals(Symbol.QUEEN)){
particularPiece = (Queen) new Queen(particularPiece.getColor(), particularPiece.getRow(), particularPiece.getColumn());
}
if(piece.getSymbol().equals(Symbol.KING)){
particularPiece = (King) new King(particularPiece.getColor(), particularPiece.getRow(), particularPiece.getColumn());
}
if(piece.getSymbol().equals(Symbol.KNIGHT)){
particularPiece = (Knight) new Knight(particularPiece.getColor(), particularPiece.getRow(), particularPiece.getColumn());
}
if(piece.getSymbol().equals(Symbol.BISHOP)){
particularPiece = (Bishop) new Bishop(particularPiece.getColor(), particularPiece.getRow(), particularPiece.getColumn());
}
if(piece.getSymbol().equals(Symbol.ROOK)){
particularPiece = (Rook) new Rook(particularPiece.getColor(), particularPiece.getRow(), particularPiece.getColumn());
}
if(piece.getSymbol().equals(Symbol.PAWN)){
particularPiece = (Pawn) new Pawn(particularPiece.getColor(), particularPiece.getRow(), particularPiece.getColumn());
}
if (particularPiece.isMoveValid(kingRow, kingCol, this)) {
return true;
}
}
}
}
return false;
}
}

View File

@ -0,0 +1,39 @@
package com.jarocki.stanislaw.chess.Coordinate;
public enum Column {
A,
B,
C,
D,
E,
F,
G,
H;
public int getNum() {
return this.ordinal();
}
public static Column getColByNum(String number) {
switch (number) {
case "1":
return Column.A;
case "2":
return Column.B;
case "3":
return Column.C;
case "4":
return Column.D;
case "5":
return Column.E;
case "6":
return Column.F;
case "7":
return Column.G;
case "8":
return Column.H;
default:
throw new IllegalArgumentException("Invalid column number: " + number);
}
}
}

View File

@ -0,0 +1,117 @@
//package com.jarocki.stanislaw.chess.Coordinate;
//
//import com.jarocki.stanislaw.chess.Player.Role;
//
//public class Coordinate {
// private String lastMoveFrom;
// private String lastMoveTo;
// private Column lastMoveFromCol;
// private Row lastMoveFromRow;
// private Column lastMoveToCol;
// private Row lastMoveToRow;
//
// public void setLastMove(String moveFrom, String moveTo) {
// if(moveFrom == null || moveTo == null) {
// System.out.println("Some moves are missing: moveFrom = " + moveFrom + " and moveTo = " + moveTo + " (setLastMove)");
// }
// setLastMoveFrom(moveFrom);
// setLastMoveTo(moveTo);
// }
//
// public void convertMoveToCoordinates() {
// String moveFrom = this.getLastMoveFrom();
// String moveTo = this.getLastMoveTo();
//
// if (moveFrom.length() != 2 || moveTo.length() != 2) {
// throw new RuntimeException("Incorrect move coordinates (convertMoveToCoordinates)");
// }
//
// Column moveFromCol = Column.valueOf(moveFrom.substring(0, 1));
// Row moveFromRow = Row.getRowByNumber(moveFrom.substring(1,2));
// Column moveToCol = Column.valueOf(moveTo.substring(0, 1));
// Row moveToRow = Row.getRowByNumber(moveTo.substring(1,2));
//
// setLastMoveFromCol(moveFromCol);
// setLastMoveFromRow(moveFromRow);
// setLastMoveToCol(moveToCol);
// setLastMoveToRow(moveToRow);
// }
//
// public String convertMoveToString() {
// Row rowFrom = this.getLastMoveFromRow();
// Row rowTo = this.getLastMoveToRow();
// Column colFrom = this.getLastMoveFromCol();
// Column colTo = this.getLastMoveToCol();
//
// return (
// colFrom.toString() +
// String.valueOf(rowFrom.getNum()) +
// colTo.toString() +
// String.valueOf(rowTo.getNum())
// );
// }
//
// public void displayMoveInfo() {
// String from = this.getLastMoveFrom();
// String to = this.getLastMoveTo();
// String playerName = this.getRole().formatName();
//
// if (from == null || to == null) {
// System.out.println("Player " + playerName + " hasn't moved yet");
// return;
// }
//
// System.out.println("Player " + playerName + " moved from " + from + " to " + to);
// }
// public Column getLastMoveFromCol() {
// return lastMoveFromCol;
// }
//
// public void setLastMoveFromCol(Column lastMoveFromCol) {
// this.lastMoveFromCol = lastMoveFromCol;
// }
//
// public Row getLastMoveFromRow() {
// return lastMoveFromRow;
// }
//
// public void setLastMoveFromRow(Row lastMoveFromRow) {
// this.lastMoveFromRow = lastMoveFromRow;
// }
//
// public Column getLastMoveToCol() {
// return lastMoveToCol;
// }
//
// public void setLastMoveToCol(Column lastMoveToCol) {
// this.lastMoveToCol = lastMoveToCol;
// }
//
// public Row getLastMoveToRow() {
// return lastMoveToRow;
// }
//
// public void setLastMoveToRow(Row lastMoveToRow) {
// this.lastMoveToRow = lastMoveToRow;
// }
//
// public Role getRole() {
// return role;
// }
//
// public String getLastMoveFrom() {
// return lastMoveFrom;
// }
//
// private void setLastMoveFrom(String lastMoveFrom) {
// this.lastMoveFrom = lastMoveFrom;
// }
//
// public String getLastMoveTo() {
// return lastMoveTo;
// }
//
// private void setLastMoveTo(String lastMoveTo) {
// this.lastMoveTo = lastMoveTo;
// }
//}

View File

@ -0,0 +1,39 @@
package com.jarocki.stanislaw.chess.Coordinate;
public enum Row {
ONE,
TWO,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT;
public static Row getRowByNum(String number) {
switch (number) {
case "1":
return Row.ONE;
case "2":
return Row.TWO;
case "3":
return Row.THREE;
case "4":
return Row.FOUR;
case "5":
return Row.FIVE;
case "6":
return Row.SIX;
case "7":
return Row.SEVEN;
case "8":
return Row.EIGHT;
default:
throw new IllegalArgumentException("Invalid row number: " + number);
}
}
public int getNum() {
return this.ordinal();
}
}

View File

@ -0,0 +1,112 @@
package com.jarocki.stanislaw.chess;
import com.jarocki.stanislaw.chess.Board.Board;
import com.jarocki.stanislaw.chess.Piece.Color;
import com.jarocki.stanislaw.chess.Player.Player;
import com.jarocki.stanislaw.chess.Player.Role;
import java.util.Scanner;
public class Game {
private Board board;
private boolean isGameOn;
private boolean isWhiteTurn = true;
public Game() {
board = new Board();
}
public void play() {
Scanner scanner = new Scanner(System.in);
this.setIsGameOn(true);
Board board = new Board();
Player currPlayer = new Player(Role.WHITE);
board.setUpPieces();
int iteration = 0; // tests only
// String[] testMoves = Test.getOnlyPawnsOpening();
// String[] testMoves = Test.getWrongPawnMoves();
// String[] testMoves = Test.takeQueenOut();
// String[] testMoves = Test.takeBishopOut();
// String[] testMoves = Test.takeKnightsOut();
// String[] testMoves = Test.takeRookOut();
// String[] testMoves = Test.takeKingOut();
// String[] testMoves = Test.getCastlingMoves();
String[] testMoves = Test.getPawnPromotion();
// String[] testMoves = Test.getOpeningMoves();
while(getIsGameOn()) {
board.printBoard();
Color playerColor = this.getIsWhiteTurn() ? Color.WHITE : Color.BLACK;
System.out.println("Enter " + playerColor.toString() + " next move: ");
Test.delay(300);
// tests
String input;
if(iteration >= testMoves.length) {
input = scanner.nextLine();
} else { // tests only
input = testMoves[iteration];
iteration = iteration + 1;
}
String[] moves = input.toUpperCase().split(" ");
if (moves.length != 2) {
System.out.println("Incorrect move format. Try \"e2 e4\". (Game)");
continue;
}
currPlayer.setLastMove(moves[0], moves[1]);
currPlayer.convertMoveToCoordinates();
int fromRow = currPlayer.getLastMoveFromRow().getNum();
int fromCol = currPlayer.getLastMoveFromCol().getNum();
int toRow = currPlayer.getLastMoveToRow().getNum();
int toCol = currPlayer.getLastMoveToCol().getNum();
Test.displayCurrentMove(currPlayer.getRole().formatName(), moves[0], moves[1]);
if (!board.isMoveValid(fromRow, fromCol, toRow, toCol, playerColor)) {
System.out.println("Moving " + currPlayer.getRole().formatName() + " from " + moves[0] + " to " + moves[1] + " is illegal. (Game)");
this.switchTurn();
currPlayer.switchRole();
continue;
}
board.makeMove(fromRow, fromCol, toRow, toCol);
currPlayer.displayMoveInfo();
this.switchTurn();
currPlayer.switchRole();
}
scanner.close();
}
public void stopGame() {
this.setIsGameOn(false);
}
private boolean getIsGameOn() {
return isGameOn;
}
private void setIsGameOn(boolean isGameOn) {
this.isGameOn = isGameOn;
}
public boolean getIsWhiteTurn() {
return isWhiteTurn;
}
public void switchTurn() {
isWhiteTurn = !isWhiteTurn;
}
}

View File

@ -0,0 +1,9 @@
package com.jarocki.stanislaw.chess;
public class Main {
public static void main(String[] args) {
Game game = new Game();
game.play();
}
}

View File

@ -0,0 +1,54 @@
package com.jarocki.stanislaw.chess.Piece;
import com.jarocki.stanislaw.chess.Board.Board;
import com.jarocki.stanislaw.chess.Coordinate.Column;
import com.jarocki.stanislaw.chess.Coordinate.Row;
public class Basic {
private final Color color;
private Column column;
private Row row;
private Symbol symbol;
public Basic (Color color, Row row, Column column) {
this.color = color;
this.column = column;
this.row = row;
}
public Color getColor() {
return color;
}
public Column getColumn() {
return column;
}
public void setColumn(Column column) {
this.column = column;
}
public Row getRow() {
return row;
}
public void setRow(Row row) {
this.row = row;
}
public Symbol getSymbol() {
return this.symbol;
}
public void setSymbol(Symbol symbol) {
this.symbol = symbol;
}
public boolean isMoveValid(int targetRow, int targetColumn, Board board) { return false; }
public Basic copy(Color color, Row row, Column column) {
Basic copy = new Basic(color, row, column);
copy.setSymbol(this.symbol);
return copy;
}
}

View File

@ -0,0 +1,54 @@
package com.jarocki.stanislaw.chess.Piece;
import com.jarocki.stanislaw.chess.Board.Board;
import com.jarocki.stanislaw.chess.Coordinate.Column;
import com.jarocki.stanislaw.chess.Coordinate.Row;
public class Bishop extends Basic {
public Bishop(Color color, Row row, Column col) {
super(color, row, col);
setSymbol(getSymbol().BISHOP);
}
@Override
public boolean isMoveValid(int toRow, int toCol, Board board) {
int row = this.getRow().getNum();
int col = this.getColumn().getNum();
if (toRow < 0 || toRow >= 8 || toCol < 0 || toCol >= 8) {
return false;
}
int dRow = toRow - row;
int dCol = toCol - col;
// check if moving on diagonal
if (Math.abs(dRow) != Math.abs(dCol)) {
return false;
}
// check if something between bishop and destination tile
int stepRow = dRow > 0 ? 1 : -1;
int stepCol = dCol > 0 ? 1 : -1;
int currentRow = row + stepRow;
int currentCol = col + stepCol;
while (currentRow != toRow || currentCol != toCol) {
if (board.getPiece(currentRow, currentCol) != null) {
return false;
}
currentRow += stepRow;
currentCol += stepCol;
}
// check destination clear/with opponent
Basic destinationPiece = board.getPiece(toRow, toCol);
return destinationPiece == null || destinationPiece.getColor() != this.getColor();
}
public Basic copy() {
return new Bishop(this.getColor(), this.getRow(), this.getColumn());
}
}

View File

@ -0,0 +1,10 @@
package com.jarocki.stanislaw.chess.Piece;
public enum Color {
WHITE,
BLACK;
public String toString() {
return this.name().substring(0,1) + this.name().substring(1).toLowerCase();
}
}

View File

@ -0,0 +1,91 @@
package com.jarocki.stanislaw.chess.Piece;
import com.jarocki.stanislaw.chess.Board.Board;
import com.jarocki.stanislaw.chess.Coordinate.Column;
import com.jarocki.stanislaw.chess.Coordinate.Row;
public class King extends Basic {
private boolean hasMoved;
public King(Color color, Row row, Column col) {
super(color, row, col);
this.setSymbol(Symbol.KING);
hasMoved = false;
}
public boolean hasMoved() {
return hasMoved;
}
public boolean isMoveValid(int toRow, int toCol, Board board) {
int row = this.getRow().getNum();
int col = this.getColumn().getNum();
// check if inside the board
if (toRow < 0 || toRow >= 8 || toCol < 0 || toCol >= 8) {
return false;
}
int dRow = Math.abs(toRow - row);
int dCol = Math.abs(toCol - col);
// king can move only by one tile unless its a castling
if ((dRow != 1 || dCol != 0) && (dRow != 0 || dCol != 1) && (dRow != 1 || dCol != 1)) {
// Check for castling
if (isCastlingMove(toRow, toCol, board)) {
return true;
}
return false;
}
// check if destination is empty or with opponent
Basic destinationPiece = board.getPiece(toRow, toCol);
return destinationPiece == null || destinationPiece.getColor() != this.getColor();
}
public Basic copy() {
King copy = new King(this.getColor(), this.getRow(), this.getColumn());
copy.hasMoved = hasMoved;
return copy;
}
private boolean isCastlingMove(int toRow, int toCol, Board board) {
int fromRow = this.getRow().getNum();
int fromCol = this.getColumn().getNum();
// check if king moved
if (hasMoved()) {
return false;
}
// check if pattern is right - long/short castling
if (toRow != fromRow || (toCol != 2 && toCol != 6)) {
return false;
}
// check if not making the check
if (board.isKingInCheck(this.getColor())) {
return false;
}
//
int rookCol = (toCol == 2) ? 0 : 7;
Rook rook = (Rook) board.getPiece(fromRow, rookCol);
if (!(rook instanceof Rook) || rook.getColor() != this.getColor()) {
return false;
}
// Check if the path between the king and rook is clear
int startCol = (toCol == 2) ? 1 : 5;
int endCol = (toCol == 2) ? 3 : 6;
int row = fromRow;
for (int col = startCol; col <= endCol; col++) {
Basic piece = board.getPiece(row, col);
if (piece != null) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,31 @@
package com.jarocki.stanislaw.chess.Piece;
import com.jarocki.stanislaw.chess.Board.Board;
import com.jarocki.stanislaw.chess.Coordinate.Column;
import com.jarocki.stanislaw.chess.Coordinate.Row;
public class Knight extends Basic {
public Knight(Color color, Row row, Column col) {
super(color, row, col);
setSymbol(Symbol.KNIGHT);
}
@Override
public boolean isMoveValid(int toRow, int toCol, Board board) {
int row = this.getRow().getNum();
int col = this.getColumn().getNum();
// make sure the destination coordinates are on the board
if (toRow < 0 || toRow >= 8 || toCol < 0 || toCol >= 8) {
return false;
}
int dRow = Math.abs(toRow - row);
int dCol = Math.abs(toCol - col);
// knight can move only in "L" path = to cols up one row vert and vice versa
return (dRow == 2 && dCol == 1) || (dRow == 1 && dCol == 2);
}
public Basic copy() {
return new Knight(this.getColor(), this.getRow(), this.getColumn());
}
}

View File

@ -0,0 +1,101 @@
package com.jarocki.stanislaw.chess.Piece;
import com.jarocki.stanislaw.chess.Board.Board;
import com.jarocki.stanislaw.chess.Coordinate.Column;
import com.jarocki.stanislaw.chess.Coordinate.Row;
public class Pawn extends Basic {
public Pawn(Color color, Row row, Column col) {
super(color, row, col);
this.setSymbol(Symbol.PAWN);
}
@Override
public boolean isMoveValid(int targetRow, int targetColumn, Board board) {
// check if inside board
if (targetRow < 0 || targetRow >= 8 || targetColumn < 0 || targetColumn >= 8) {
return false;
}
// destination tile empty/with opponent's pawn
if (board.getPiece(targetRow, targetColumn) == null) {
if (getColumn().getNum() == targetColumn) {
// moving forward by one row depending on the color
if (getColor() == Color.WHITE) {
if (targetRow - getRow().getNum() == 1) {
return true;
} else if (isStartingPosition(getRow(), getColor()) && targetRow - getRow().getNum() == 2) {
// check if can move two tiles
if (board.getPiece(getRow().getNum() + 1, targetColumn) == null) {
return true;
}
}
} else {
if (targetRow - getRow().getNum() == -1) {
return true;
} else if (isStartingPosition(getRow(), getColor()) && targetRow - getRow().getNum() == -2) {
// check if can move two tiles
if (board.getPiece(getRow().getNum() - 1, targetColumn) == null) {
return true;
}
}
}
}
// if en passant
return isValidCapture(targetRow, targetColumn, board);
} else {
// i know it's silly but works
return isValidCapture(targetRow, targetColumn, board);
}
}
private boolean isValidCapture(int targetRow, int targetColumn, Board board) {
// inside board
if (targetRow < 0 || targetRow >= 8 || targetColumn < 0 || targetColumn >= 8) {
return false;
}
Basic targetPiece = board.getPiece(targetRow, targetColumn);
if (targetPiece == null) {
// en passant check
if (targetColumn == getColumn().getNum() - 1 || targetColumn == getColumn().getNum() + 1) {
// check target tile
if (targetRow == getRow().getNum() + (getColor() == Color.WHITE ? 1 : -1)) {
Pawn lastMovedPawn = board.getLastMovedPawn();
if (lastMovedPawn != null && lastMovedPawn.getRow() == getRow() &&
lastMovedPawn.getColumn().getNum() == targetColumn) {
// correct en passant
return true;
}
}
}
return false;
}
int col = getColumn().getNum();
if (targetColumn == getColumn().getNum() - 1) {
// diagonal to top left
Color color = getColor();
if (getColor() == Color.WHITE && targetRow == getRow().getNum() + 1) {
return true;
} else if (getColor() == Color.BLACK && targetRow == getRow().getNum() - 1) {
return true;
}
} else if (targetColumn == getColumn().getNum() + 1) {
// one tile to top right
if (getColor() == Color.WHITE && targetRow == getRow().getNum() + 1) {
return true;
} else if (getColor() == Color.BLACK && targetRow == getRow().getNum() - 1) {
return true;
}
}
return false;
}
private boolean isStartingPosition(Row currentRow, Color color) {
// check if the pawn is in its starting position (white row - 2, black row - 7)
return (color == Color.WHITE && currentRow == Row.TWO)
|| (color == Color.BLACK && currentRow == Row.SEVEN);
}
}

View File

@ -0,0 +1,53 @@
package com.jarocki.stanislaw.chess.Piece;
import com.jarocki.stanislaw.chess.Board.Board;
import com.jarocki.stanislaw.chess.Coordinate.Column;
import com.jarocki.stanislaw.chess.Coordinate.Row;
public class Queen extends Basic {
public Queen(Color color, Row row, Column col) {
super(color, row, col);
setSymbol(Symbol.QUEEN);
}
@Override
public boolean isMoveValid(int toRow, int toCol, Board board) {
int row = this.getRow().getNum();
int col = this.getColumn().getNum();
//check if inside the board
if (toRow < 0 || toRow >= 8 || toCol < 0 || toCol >= 8) {
return false;
}
int dRow = toRow - row;
int dCol = toCol - col;
// queen moving vertical/horizontally/diagonally
if (dRow != 0 && dCol != 0 && Math.abs(dRow) != Math.abs(dCol)) {
return false;
}
// check if there's sth between her and the destination
int stepRow = dRow == 0 ? 0 : (dRow > 0 ? 1 : -1);
int stepCol = dCol == 0 ? 0 : (dCol > 0 ? 1 : -1);
int currentRow = row + stepRow;
int currentCol = col + stepCol;
while (currentRow != toRow || currentCol != toCol) {
if (board.getPiece(currentRow, currentCol) != null) {
return false;
}
currentRow += stepRow;
currentCol += stepCol;
}
// destination tile has to be empty or with opponent
Basic destinationPiece = board.getPiece(toRow, toCol);
return destinationPiece == null || destinationPiece.getColor() != this.getColor();
}
public Basic copy() {
return new Queen(this.getColor(), this.getRow(), this.getColumn());
}
}

View File

@ -0,0 +1,60 @@
package com.jarocki.stanislaw.chess.Piece;
import com.jarocki.stanislaw.chess.Board.Board;
import com.jarocki.stanislaw.chess.Coordinate.Column;
import com.jarocki.stanislaw.chess.Coordinate.Row;
public class Rook extends Basic {
private boolean hasMoved = false;
public Rook(Color color, Row row, Column col) {
super(color, row, col);
setSymbol(Symbol.ROOK);
}
@Override
public boolean isMoveValid(int toRow, int toCol, Board board) {
int row = this.getRow().getNum();
int col = this.getColumn().getNum();
if (toRow < 0 || toRow >= 8 || toCol < 0 || toCol >= 8) {
return false;
}
int dRow = toRow - row;
int dCol = toCol - col;
// rook can move only vertical/horizontal
if (dRow != 0 && dCol != 0) {
return false;
}
// check for objects on the path to destination
int stepRow = Integer.compare(dRow, 0);
int stepCol = Integer.compare(dCol, 0);
int currentRow = row + stepRow;
int currentCol = col + stepCol;
while (currentRow != toRow || currentCol != toCol) {
if (board.getPiece(currentRow, currentCol) != null) {
return false;
}
currentRow += stepRow;
currentCol += stepCol;
}
// check destination empty/with opponent
Basic destinationPiece = board.getPiece(toRow, toCol);
return destinationPiece == null || destinationPiece.getColor() != this.getColor();
}
public void setHasMoved() {
hasMoved = true;
}
public Basic copy() {
return new Rook(this.getColor(), this.getRow(), this.getColumn());
}
}

View File

@ -0,0 +1,26 @@
package com.jarocki.stanislaw.chess.Piece;
public enum Symbol {
KING("K"),
QUEEN("Q"),
ROOK("R"),
BISHOP("B"),
KNIGHT("N"),
PAWN("P");
// PAWN("");
// QUEEN(""),
// ROOK(""),
// BISHOP(""),
// KNIGHT(""),
private final String symbol;
Symbol(String symbol) {
this.symbol = symbol;
}
public String getChar() {
return symbol;
}
}

View File

@ -0,0 +1,128 @@
package com.jarocki.stanislaw.chess.Player;
import com.jarocki.stanislaw.chess.Coordinate.Column;
import com.jarocki.stanislaw.chess.Coordinate.Row;
import com.jarocki.stanislaw.chess.Piece.Color;
public class Player {
private Role role;
private String lastMoveFrom;
private String lastMoveTo;
private Column lastMoveFromCol;
private Row lastMoveFromRow;
private Column lastMoveToCol;
private Row lastMoveToRow;
public Player(Role role) {
this.role = role;
}
public void switchRole (){
this.role = getRole().equals(Role.WHITE) ? Role.BLACK : Role.WHITE;
}
public void setLastMove(String moveFrom, String moveTo) {
if(moveFrom == null || moveTo == null) {
System.out.println("Some moves are missing: moveFrom = " + moveFrom + " and moveTo = " + moveTo + " (setLastMove)");
}
setLastMoveFrom(moveFrom);
setLastMoveTo(moveTo);
}
public void convertMoveToCoordinates() {
String moveFrom = this.getLastMoveFrom();
String moveTo = this.getLastMoveTo();
if (moveFrom.length() != 2 || moveTo.length() != 2) {
throw new RuntimeException("Incorrect move coordinates (convertMoveToCoordinates)");
}
Column moveFromCol = Column.valueOf(moveFrom.substring(0, 1));
Row moveFromRow = Row.getRowByNum(moveFrom.substring(1,2));
Column moveToCol = Column.valueOf(moveTo.substring(0, 1));
Row moveToRow = Row.getRowByNum(moveTo.substring(1,2));
setLastMoveFromCol(moveFromCol);
setLastMoveFromRow(moveFromRow);
setLastMoveToCol(moveToCol);
setLastMoveToRow(moveToRow);
}
public String convertMoveToString() {
Row rowFrom = this.getLastMoveFromRow();
Row rowTo = this.getLastMoveToRow();
Column colFrom = this.getLastMoveFromCol();
Column colTo = this.getLastMoveToCol();
return (
colFrom.toString() +
String.valueOf(rowFrom.getNum()) +
colTo.toString() +
String.valueOf(rowTo.getNum())
);
}
public void displayMoveInfo() {
String from = this.getLastMoveFrom();
String to = this.getLastMoveTo();
String playerName = this.getRole().formatName();
if (from == null || to == null) {
System.out.println("Player " + playerName + " hasn't moved yet");
return;
}
System.out.println("Player " + playerName + " moved from " + from + " to " + to);
}
public Column getLastMoveFromCol() {
return lastMoveFromCol;
}
public void setLastMoveFromCol(Column lastMoveFromCol) {
this.lastMoveFromCol = lastMoveFromCol;
}
public Row getLastMoveFromRow() {
return lastMoveFromRow;
}
public void setLastMoveFromRow(Row lastMoveFromRow) {
this.lastMoveFromRow = lastMoveFromRow;
}
public Column getLastMoveToCol() {
return lastMoveToCol;
}
public void setLastMoveToCol(Column lastMoveToCol) {
this.lastMoveToCol = lastMoveToCol;
}
public Row getLastMoveToRow() {
return lastMoveToRow;
}
public void setLastMoveToRow(Row lastMoveToRow) {
this.lastMoveToRow = lastMoveToRow;
}
public Role getRole() {
return role;
}
public String getLastMoveFrom() {
return lastMoveFrom;
}
private void setLastMoveFrom(String lastMoveFrom) {
this.lastMoveFrom = lastMoveFrom;
}
public String getLastMoveTo() {
return lastMoveTo;
}
private void setLastMoveTo(String lastMoveTo) {
this.lastMoveTo = lastMoveTo;
}
}

View File

@ -0,0 +1,10 @@
package com.jarocki.stanislaw.chess.Player;
public enum Role {
BLACK,
WHITE;
public String formatName() {
return this.name().substring(0,1) + this.name().substring(1).toLowerCase();
}
}

View File

@ -0,0 +1,142 @@
package com.jarocki.stanislaw.chess;
public class Test {
static public String[] getOnlyPawnsOpening() {
return new String[]{
"e2 e4", "d7 d5",
"c2 c4", "e7 e5",
"e4 d5", "e5 e4",
"a2 a4", "a7 a6",
"h2 h3", "h7 h5",
"a4 a5", "c7 c5",
"d5 c6", "b7 b5",
"a5 b6",
};
}
static public String[] getWrongPawnMoves() {
return new String[]{
"e2 e4", "d7 d5",
"c2 c4", "e7 e5",
"e4 d5", "f4 f5",
"c4 c6", "g6 g5",
"b2 b1", "d5 d4",
};
}
static public String[] takeRookOut() {
return new String[]{
"h2 h4", "g7 g5",
"h4 g5", "b7 b5",
"h1 h7", "f7 f5",
"h7 d7", "a8 a5", // wrong move over opponents and self pieces
"h7 f7", "a7 a5",
"f7 f5", "h8 h7",
"f5 b5", "h7 h1",
"b5 f5", "h1 g1",
"f5 a5", "a8 a6",
};
}
static public String[] takeBishopOut() {
return new String[]{
"e2 e4", "b7 b6",
"f1 c4", "c8 b7",
"c4 g8", "b7 a8", // wrong moves - over piece/onto own piece
"c4 d4", "b7 b4", // wrong moves - horizontal i vertical
"c4 f7", "b7 e4",
"f7 g8", "e4 c2", // in future there's a check
};
}
static public String[] takeKnightsOut() {
return new String[]{
"b1 a3", "g8 f6",
"g1 g3", "f6 h7", // wrong moves - occupied own piece/illegal field
"a3 c4", "f6 d5",
"a3 c4", "f6 d5",
"c4 e3", "d5 e3",
};
}
static public String[] takeQueenOut() {
return new String[]{
"e2 e4", "e7 e6", // move pawns out
"d1 f3", "d8 h4", // move queens out
"f3 b4", "h4 h1", // wrong move - random field/jump over piece <<<
"f3 b3", "h4 f6", // move queens other horizontally and diagonally
"b3 b7", "f6 b2", // capture pawns with queens
};
}
static public String[] takeKingOut() {
return new String[]{
"e2 e4", "b7 b6", // move pawns out
"e1 e2", "f7 f5", // move one king out and pawn to it
"e2 f3", "h7 h6", // move one king out and queen out
"f3 f4", "b8 c6", // come with king closer to pawn and move knight for castling
"f4 f5", "c8 b7", // take pawn by king and move bishop for castling
"f5 f4", "e7 e5", // get back with king and attack with pawn
"f4 e3", "d8 h4", // run away with king and get out queen for castling
"g2 g3", "h4 g5", // attack queen and check the white king with queen
"a2 a3", "a2 a3", // invalid move - makes CHECK, black invalid too for handicapp <<
"f2 f4", "c6 e7", // valid move - hide behind the pawn and prepare knight to check king
"f4 g5", "e7 d5", // kill black queen with pawn and attack white king with knight
"d1 h5", // invalid move - try to check black king, but check from knight
};
}
static public String[] getOpeningMoves() {
return new String[]{
"e2 e4", "e7 e5",
"g1 f3", "b8 c6",
"f1 c4", "g8 f6",
"d2 d4", "e5 d4",
"f3 d4", "f6 d5",
"e4 d5", "e7 e6",
"c1 g5", "d8 f6",
"d1 f3", "e8 g8",
"e1 g1", "f8 e7", // castling
"g1 h1", "d5 c6",
"d4 c5", "c8 d7",
"g5 h6", "f6 h6",
};
}
static public String[] getCastlingMoves() {
return new String[]{
"e2 e4", "d7 d6",
"f1 c4", "c8 f5",
"g1 f3", "b8 c6",
"g1 f3", "b8 c6",
"e1 g1", "d8 d7", // castling 1
"a2 a3", "e8 c8", // castling 2
};
}
static public String[] getPawnPromotion() {
return new String[]{
"e2 e4", "d7 d5",
"e4 e5", "d5 d4",
"e5 e6", "d4 d3",
"e6 f7", "e8 d7",
"h2 h3", "d3 c2",
"f7 g8", "c2 b1", // promote to queens both
"g8 b3", "b1 f5", // move queens to demonstrate
"b3 b7", // take pawn downs
};
}
static public void delay(int milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void displayCurrentMove(String playerColor, String moveFrom, String moveTo) {
System.out.println("[DEBUG] Moving " + playerColor + " from " + moveFrom + " to " + moveTo);
}
}