Created
May 3, 2017 23:04
-
-
Save IbrahimAyed1/5cacb725035561cb9e6c804f553f3ad8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <component name="ProjectDictionaryState"> | |
| <dictionary name="ibrahim"> | |
| <words> | |
| <w>polymorphicly</w> | |
| </words> | |
| </dictionary> | |
| </component> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <project version="4"> | |
| <component name="KotlinCommonCompilerArguments"> | |
| <option name="languageVersion" value="1.1" /> | |
| <option name="apiVersion" value="1.1" /> | |
| </component> | |
| </project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <component name="libraryTable"> | |
| <library name="gdx-setup"> | |
| <CLASSES> | |
| <root url="jar://$USER_HOME$/Downloads/gdx-setup.jar!/" /> | |
| </CLASSES> | |
| <JAVADOC /> | |
| <SOURCES /> | |
| </library> | |
| </component> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <component name="libraryTable"> | |
| <library name="guava-18.0"> | |
| <CLASSES> | |
| <root url="jar://$USER_HOME$/Downloads/OOP Project/BlackWidow-Chess-master/lib/guava-18.0.jar!/" /> | |
| </CLASSES> | |
| <JAVADOC /> | |
| <SOURCES /> | |
| </library> | |
| </component> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <project version="4"> | |
| <component name="ClientPropertiesManager"> | |
| <properties class="javax.swing.AbstractButton"> | |
| <property name="hideActionText" class="java.lang.Boolean" /> | |
| </properties> | |
| <properties class="javax.swing.JComponent"> | |
| <property name="html.disable" class="java.lang.Boolean" /> | |
| </properties> | |
| <properties class="javax.swing.JEditorPane"> | |
| <property name="JEditorPane.w3cLengthUnits" class="java.lang.Boolean" /> | |
| <property name="JEditorPane.honorDisplayProperties" class="java.lang.Boolean" /> | |
| <property name="charset" class="java.lang.String" /> | |
| </properties> | |
| <properties class="javax.swing.JList"> | |
| <property name="List.isFileList" class="java.lang.Boolean" /> | |
| </properties> | |
| <properties class="javax.swing.JPasswordField"> | |
| <property name="JPasswordField.cutCopyAllowed" class="java.lang.Boolean" /> | |
| </properties> | |
| <properties class="javax.swing.JSlider"> | |
| <property name="Slider.paintThumbArrowShape" class="java.lang.Boolean" /> | |
| <property name="JSlider.isFilled" class="java.lang.Boolean" /> | |
| </properties> | |
| <properties class="javax.swing.JTable"> | |
| <property name="Table.isFileList" class="java.lang.Boolean" /> | |
| <property name="JTable.autoStartsEdit" class="java.lang.Boolean" /> | |
| <property name="terminateEditOnFocusLost" class="java.lang.Boolean" /> | |
| </properties> | |
| <properties class="javax.swing.JToolBar"> | |
| <property name="JToolBar.isRollover" class="java.lang.Boolean" /> | |
| </properties> | |
| <properties class="javax.swing.JTree"> | |
| <property name="JTree.lineStyle" class="java.lang.String" /> | |
| </properties> | |
| <properties class="javax.swing.text.JTextComponent"> | |
| <property name="caretAspectRatio" class="java.lang.Double" /> | |
| <property name="caretWidth" class="java.lang.Integer" /> | |
| </properties> | |
| </component> | |
| <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> | |
| <output url="file://$PROJECT_DIR$/out" /> | |
| </component> | |
| </project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <project version="4"> | |
| <component name="ProjectModuleManager"> | |
| <modules> | |
| <module fileurl="file://$PROJECT_DIR$/Chess.iml" filepath="$PROJECT_DIR$/Chess.iml" /> | |
| </modules> | |
| </component> | |
| </project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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" /> | |
| <orderEntry type="library" name="guava-18.0" level="project" /> | |
| <orderEntry type="library" name="gdx-setup" level="project" /> | |
| </component> | |
| </module> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine; | |
| import com.chess.engine.player.BlackPlayer; | |
| import com.chess.engine.player.Player; | |
| import com.chess.engine.player.WhitePlayer; | |
| /** | |
| * Created by ibrahim on 4/25/17. | |
| */ | |
| public enum Alliance { | |
| WHITE { | |
| @Override | |
| public int getDirection() { | |
| return -1; | |
| } | |
| @Override | |
| public boolean isBlack() { | |
| return false; | |
| } | |
| @Override | |
| public boolean isWhite() { | |
| return true; | |
| } | |
| @Override | |
| public Player choosePlayer(final WhitePlayer whitePlayer,final BlackPlayer blackPlayer) { | |
| return whitePlayer; | |
| } | |
| }, | |
| BLACK { | |
| @Override | |
| public int getDirection() { | |
| return 1; | |
| } | |
| @Override | |
| public boolean isBlack() { | |
| return true; | |
| } | |
| @Override | |
| public boolean isWhite() { | |
| return false; | |
| } | |
| @Override | |
| public Player choosePlayer(final WhitePlayer whitePlayer,final BlackPlayer blackPlayer) { | |
| return blackPlayer; | |
| } | |
| }; | |
| public abstract int getDirection(); | |
| public abstract boolean isBlack(); | |
| public abstract boolean isWhite(); | |
| public abstract Player choosePlayer(WhitePlayer whitePlayer, BlackPlayer blackPlayer); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.board; | |
| import com.chess.engine.Alliance; | |
| import com.chess.engine.pieces.*; | |
| import com.chess.engine.player.BlackPlayer; | |
| import com.chess.engine.player.Player; | |
| import com.chess.engine.player.WhitePlayer; | |
| import com.google.common.collect.ImmutableList; | |
| import com.google.common.collect.Iterables; | |
| import java.util.*; | |
| /** | |
| * Created by ibrahim on 4/25/17. | |
| */ | |
| public class Board { | |
| //We will make a collection of tiles | |
| //Here we will use lists , because you can NOT have an IMMUTABLE array in java , but you CAN have IMMUTABLE list. | |
| private final List<Tile> gameBoard; | |
| private final Collection<Piece> whitePieces; | |
| private final Collection<Piece> blackPieces; | |
| private final WhitePlayer whitePlayer; | |
| private final BlackPlayer blackPlayer; | |
| private final Player currentPlayer; | |
| public Board(final Builder builder) { | |
| this.gameBoard = createGameBoard(builder); | |
| this.whitePieces = calculateActivePieces(this.gameBoard,Alliance.WHITE); | |
| this.blackPieces = calculateActivePieces(this.gameBoard,Alliance.BLACK); | |
| final Collection<Moves> whiteStanderedLegalMoves=calculateLegalMoves(this.whitePieces); | |
| final Collection<Moves> blackStanderedLegalMoves=calculateLegalMoves(this.blackPieces); | |
| this.whitePlayer = new WhitePlayer(this,whiteStanderedLegalMoves,blackStanderedLegalMoves); | |
| this.blackPlayer = new BlackPlayer(this,whiteStanderedLegalMoves,blackStanderedLegalMoves); | |
| this.currentPlayer = builder.nextMoveMaker.choosePlayer(this.whitePlayer,this.blackPlayer); | |
| }//Constructor end | |
| @Override | |
| public String toString(){ | |
| //This will determine what board looks like when it's turn into string | |
| final StringBuilder builder = new StringBuilder(); | |
| for (int i=0;i < BoardUtils.NUM_TILES;i++){ | |
| final String tileTest = this.gameBoard.get(i).toString(); | |
| builder.append(String.format("%3s",tileTest)); | |
| if( (i+1) % BoardUtils.NUM_TILES_PER_ROW == 0 ){ | |
| builder.append("\n"); | |
| } | |
| }//for loop ends here | |
| return builder.toString(); | |
| } //string builder ends here | |
| public Player whitePlayer(){ | |
| return this.whitePlayer; | |
| } | |
| public Player blackPlayer(){ | |
| return this.blackPlayer; | |
| } | |
| public Player currentPlayer(){ | |
| return this.currentPlayer; | |
| } | |
| public Collection<Piece> getBlackPieces(){ | |
| return this.blackPieces; | |
| } | |
| public Collection<Piece> getWhitePieces(){ | |
| return this.whitePieces; | |
| } | |
| private Collection<Moves> calculateLegalMoves(final Collection<Piece> pieces) { | |
| final List<Moves>legalMoves = new ArrayList<>(); | |
| for (final Piece piece : pieces){ | |
| legalMoves.addAll(piece.calculateLegalMoves(this)); //Legal moves is like a container that contains all the legal moves | |
| }//End of for | |
| return ImmutableList.copyOf(legalMoves); | |
| }//end of calculating legal moves method | |
| private static Collection<Piece> calculateActivePieces(final List<Tile> gameBoard,final Alliance alliance) { | |
| final List<Piece> activePieces = new ArrayList<>(); | |
| for(final Tile tile : gameBoard){ | |
| if(tile.isTileOccupied()){ | |
| final Piece piece=tile.getPiece(); | |
| if(piece.getPieceAlliance() == alliance){ | |
| activePieces.add(piece); | |
| }//end if | |
| }//end if | |
| }//end for | |
| return ImmutableList.copyOf(activePieces); | |
| }//end method calculate active pieces | |
| public Tile getTile(final int tileCoordinate) { | |
| return gameBoard.get(tileCoordinate); | |
| }//Tile object | |
| //Now we will make a method that makes list of tiles numbered form 0 to 63 that'll represent the chess board , we gonna see that in the for loop later | |
| //that we will go through , | |
| // what we gonna see is that in that loop we go through and we get from the config wherever we set our config to associate we're going to map a piece onto tile ID | |
| //Then when we call create tile | |
| public static List<Tile> createGameBoard(final Builder builder){ | |
| final Tile[] tiles = new Tile[BoardUtils.NUM_TILES]; //THIS WILL BUILD ARRAY OF 64 TILES | |
| for (int i=0;i<BoardUtils.NUM_TILES;i++){ | |
| //Then when we call create tile here ,we're going to associate a piece to a tile for it | |
| //يعني انا بقوم جايب المنطقة مثلا رقم 4 و اقوم مخصصها للملك او عن طريق ID خاص بيه | |
| tiles[i]=Tile.createTile(i,builder.boardConfig.get(i)); | |
| //It'll bring ID's of the pieces from the lower method as we know ! , but if there was not any pieces? | |
| //So it'll bring NULL | |
| /* | |
| backing to the condition " public static Tile createTile(final int tileCoordinate,final Piece piece){ | |
| return piece != null ? new OccupiedTile(tileCoordinate,piece) : EMPTY_TILES_CACHE.get(tileCoordinate); " | |
| in the Tile class , if the tile is not occupied ,create an empty tile from that we retrieve from the tile cache | |
| */ | |
| }//end of for loop | |
| return ImmutableList.copyOf(tiles); | |
| }//List of tiles "Creating game board" end | |
| public static Board createStanderedBoard(){ | |
| //here we'll create the initial position for a chess board "مكان كل قطعة" | |
| final Builder builder = new Builder(); | |
| // Black Layout | |
| builder.setPiece(new Rook(Alliance.BLACK, 0)); | |
| builder.setPiece(new Knight(Alliance.BLACK, 1)); | |
| builder.setPiece(new Bishop(Alliance.BLACK, 2)); | |
| builder.setPiece(new Queen(Alliance.BLACK, 3)); | |
| builder.setPiece(new King(Alliance.BLACK, 4)); | |
| builder.setPiece(new Bishop(Alliance.BLACK, 5)); | |
| builder.setPiece(new Knight(Alliance.BLACK, 6)); | |
| builder.setPiece(new Rook(Alliance.BLACK, 7)); | |
| builder.setPiece(new Pawn(Alliance.BLACK, 8)); | |
| builder.setPiece(new Pawn(Alliance.BLACK, 9)); | |
| builder.setPiece(new Pawn(Alliance.BLACK, 10)); | |
| builder.setPiece(new Pawn(Alliance.BLACK, 11)); | |
| builder.setPiece(new Pawn(Alliance.BLACK, 12)); | |
| builder.setPiece(new Pawn(Alliance.BLACK, 13)); | |
| builder.setPiece(new Pawn(Alliance.BLACK, 14)); | |
| builder.setPiece(new Pawn(Alliance.BLACK, 15)); | |
| // White Layout | |
| builder.setPiece(new Pawn(Alliance.WHITE, 48)); | |
| builder.setPiece(new Pawn(Alliance.WHITE, 49)); | |
| builder.setPiece(new Pawn(Alliance.WHITE, 50)); | |
| builder.setPiece(new Pawn(Alliance.WHITE, 51)); | |
| builder.setPiece(new Pawn(Alliance.WHITE, 52)); | |
| builder.setPiece(new Pawn(Alliance.WHITE, 53)); | |
| builder.setPiece(new Pawn(Alliance.WHITE, 54)); | |
| builder.setPiece(new Pawn(Alliance.WHITE, 55)); | |
| builder.setPiece(new Rook(Alliance.WHITE, 56)); | |
| builder.setPiece(new Knight(Alliance.WHITE, 57)); | |
| builder.setPiece(new Bishop(Alliance.WHITE, 58)); | |
| builder.setPiece(new Queen(Alliance.WHITE, 59)); | |
| builder.setPiece(new King(Alliance.WHITE, 60)); | |
| builder.setPiece(new Bishop(Alliance.WHITE, 61)); | |
| builder.setPiece(new Knight(Alliance.WHITE, 62)); | |
| builder.setPiece(new Rook(Alliance.WHITE, 63)); | |
| //white to move | |
| builder.setMoveMaker(Alliance.WHITE); | |
| //build the board | |
| return builder.build(); | |
| }//Standeredbuilder method end | |
| /*==============================================================*/ | |
| //Iterable is a build in function in GUAVA Library | |
| /*=============================================================*/ | |
| public Iterable<Moves> getAllLegalMoves() { | |
| return Iterables.unmodifiableIterable(Iterables.concat(this.whitePlayer.getLegalMoves(), | |
| this.blackPlayer.getLegalMoves())); | |
| } | |
| public static class Builder{ | |
| HashMap boardConfig; | |
| Alliance nextMoveMaker; | |
| Pawn enPassantPawn; | |
| public Builder(){ | |
| this.boardConfig = new HashMap<>(33,1.0f); | |
| }//End of constructor | |
| //Next methods are setting some property and return that builder back | |
| public Builder setPiece(final Piece piece){ | |
| this.boardConfig.put(piece.getPiecePosition(),piece); | |
| return this; | |
| } | |
| public Builder setMoveMaker(final Alliance nextMoveMaker){ | |
| this.nextMoveMaker = nextMoveMaker; | |
| return this; | |
| } | |
| public Board build(){ | |
| return new Board(this); | |
| } | |
| public void setEnPassantPawn(Pawn enPassantPawn) { | |
| this.enPassantPawn = enPassantPawn; | |
| } | |
| }//End of builder class | |
| }//End of board class |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.board; | |
| import java.util.List; | |
| /** | |
| * Created by ibrahim on 4/26/17. | |
| */ | |
| public class BoardUtils { | |
| public static final boolean[] FIRST_COLUMN = initColumn(0); | |
| public static final boolean[] SECOND_COLUMN =initColumn(1); | |
| public static final boolean[] THIRD_COLUMN = initColumn(2); | |
| public static final boolean[] FOURTH_COLUMN = initColumn(3); | |
| public static final boolean[] FIFTH_COLUMN = initColumn(4); | |
| public static final boolean[] SIXTH_COLUMN = initColumn(5); | |
| public static final boolean[] SEVENTH_COLUMN =initColumn(6); | |
| public static final boolean[] EIGHTH_COLUMN =initColumn(7); | |
| public static final boolean[] EIGHTH_RANK = initRow(0); | |
| public static final boolean[] SEVENTH_RANK =initRow(8); | |
| public static final boolean[] SIXTH_RANK = initRow(16); | |
| public static final boolean[] FIFTH_RANK = initRow(24); | |
| public static final boolean[] FOURTH_RANK = initRow(32); | |
| public static final boolean[] THIRD_RANK = initRow(40); | |
| public static final boolean[] SECOND_RANK =initRow(48); | |
| public static final boolean[] FIRST_RANK = initRow(56); | |
| public static final int NUM_TILES=64; | |
| public static final int NUM_TILES_PER_ROW=8; | |
| private BoardUtils(){ | |
| throw new RuntimeException("You Can't Instantiate me !"); | |
| } //Constructor end | |
| //Initialization method | |
| private static boolean[] initColumn(int columnNumber) { | |
| final boolean[] column = new boolean[NUM_TILES]; | |
| do { | |
| column[columnNumber]=true; | |
| columnNumber+=NUM_TILES_PER_ROW; | |
| } while (columnNumber < NUM_TILES); | |
| return column; | |
| } //End of the initColumn method. | |
| private static boolean[] initRow(int rowNumber) { | |
| final boolean[] row = new boolean[NUM_TILES]; | |
| do{ | |
| row[rowNumber] = true; | |
| rowNumber++; | |
| }while (rowNumber % NUM_TILES_PER_ROW !=0); | |
| return row; | |
| } | |
| public static boolean isValidTileCoordinate(int coordinate) { | |
| return coordinate >=0 && coordinate < NUM_TILES; | |
| } //Validation method end | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.board; | |
| import com.chess.engine.pieces.Pawn; | |
| import com.chess.engine.pieces.Piece; | |
| import com.chess.engine.pieces.Rook; | |
| import static com.chess.engine.board.Board.*; | |
| /** | |
| * Created by ibrahim on 4/25/17. | |
| */ | |
| public abstract class Moves { | |
| final Board board; | |
| final Piece movedPieces; | |
| final int destinationCandidate; | |
| public static final Moves NULL_MOVE = new NullMove(); | |
| private Moves(final Board board, | |
| final Piece movedPieces, | |
| final int destinationCandidate) { | |
| this.board = board; | |
| this.movedPieces = movedPieces; | |
| this.destinationCandidate = destinationCandidate; | |
| } | |
| //============= SubClasses & Methods =================// | |
| @Override | |
| public int hashCode(){ | |
| final int prime=31; | |
| int result=1; | |
| result = prime * result +this.destinationCandidate; | |
| result = prime * result + this.movedPieces.hashCode(); | |
| return result; | |
| } | |
| @Override | |
| public boolean equals(final Object other){ | |
| if(this == other) { | |
| return true; | |
| } | |
| if(!(other instanceof Moves)){ | |
| return false; | |
| } | |
| final Moves otherMove = (Moves) other; | |
| return getDestinationCoordinate() == otherMove.getDestinationCoordinate() && | |
| getMovedPieces().equals(otherMove.getMovedPieces()); | |
| } | |
| public int getCurrentCoordinate() { | |
| return this.getMovedPieces().getPiecePosition(); | |
| } | |
| public int getDestinationCoordinate() { | |
| return this.destinationCandidate; | |
| } | |
| public Piece getMovedPieces() { | |
| return this.movedPieces; | |
| } | |
| public boolean isAttack(){ | |
| return false; | |
| } | |
| public boolean isCastelingMove(){ | |
| return false; | |
| } | |
| public Piece getAttackedPiece(){ | |
| return null; | |
| } | |
| public Board execute() { | |
| final Builder builder = new Builder(); //1- we use board builder , to materialize a board to execute | |
| for (final Piece piece : this.board.currentPlayer().getActivePieces()) { | |
| //2- check that pieces that have not moved and place it again in it's places without making any changes | |
| if (!this.movedPieces.equals(piece)) { | |
| builder.setPiece(piece); // here we go through and set all of thepieces on the new out pound board | |
| } | |
| } | |
| //3-we are going to do the same thing for blacks | |
| for (final Piece piece : this.board.currentPlayer().getOpponent().getActivePieces()) { | |
| builder.setPiece(piece); | |
| } | |
| builder.setPiece(this.movedPieces.movePiece(this)); //4- we are setting the piece for the moved piece and MOVE THE MOVED PIECE | |
| builder.setMoveMaker(this.board.currentPlayer().getOpponent().getAlliance()); //5-set the move maker to the opponentd | |
| return builder.build(); | |
| } | |
| public static final class MajorMove extends Moves { | |
| public MajorMove(final Board board, final Piece movedPieces, final int destinationCandidator) { | |
| super(board, movedPieces, destinationCandidator); | |
| } | |
| } | |
| public static class AttackMove extends Moves { | |
| final Piece attackedPiece; | |
| public AttackMove(final Board board, | |
| final Piece movedPieces, | |
| final int destinationCandidate, | |
| final Piece AttackedPiece) { | |
| super(board, movedPieces, destinationCandidate); | |
| this.attackedPiece = AttackedPiece; | |
| } | |
| @Override | |
| public int hashCode(){ | |
| return this.attackedPiece.hashCode() + super.hashCode(); | |
| } | |
| @Override | |
| public boolean equals(final Object other){ | |
| if(this == other){ | |
| return true; | |
| } | |
| if(!(other instanceof AttackMove)){ | |
| return false; | |
| } | |
| final AttackMove otherAttackMove = (AttackMove) other; | |
| return super.equals(otherAttackMove) && getAttackedPiece().equals(otherAttackMove.getAttackedPiece()); | |
| } | |
| @Override | |
| public Board execute() { | |
| return null; | |
| } | |
| @Override | |
| public boolean isAttack() { | |
| return false; | |
| } | |
| @Override | |
| public Piece getAttackedPiece() { | |
| return this.attackedPiece; | |
| } | |
| }//End of attack move calss | |
| public static final class PawnMove extends Moves { | |
| public PawnMove(final Board board, | |
| final Piece movedPieces, | |
| final int destinationCandidate) { | |
| super(board, movedPieces, destinationCandidate); | |
| } | |
| } | |
| public static class PawnAttackMove extends AttackMove { | |
| public PawnAttackMove(final Board board, | |
| final Piece movedPieces, | |
| final int destinationCandidate, | |
| final Piece AttackedPiece) { | |
| super(board, movedPieces, destinationCandidate, AttackedPiece); | |
| } | |
| } | |
| public static final class PawnEnPassantAttackMove extends AttackMove { | |
| public PawnEnPassantAttackMove(final Board board, | |
| final Piece movedPieces, | |
| final int destinationCandidate, | |
| final Piece AttackedPiece) { | |
| super(board, movedPieces, destinationCandidate, AttackedPiece); | |
| } | |
| } | |
| public static final class PawnJump extends Moves { | |
| public PawnJump(final Board board, | |
| final Piece movedPieces, | |
| final int destinationCandidate) { | |
| super(board, movedPieces, destinationCandidate); | |
| } | |
| @Override | |
| public Board execute(){ | |
| final Builder builder = new Builder(); | |
| for (final Piece piece : this.board.currentPlayer().getActivePieces()){ | |
| if(!(this.movedPieces.equals(piece))){ | |
| builder.setPiece(piece); | |
| } | |
| } | |
| for (final Piece piece:this.board.currentPlayer().getOpponent().getActivePieces()){ | |
| builder.setPiece(piece); | |
| } | |
| final Pawn movedPawn = (Pawn) this.movedPieces.movePiece(this); | |
| builder.setPiece(movedPawn); | |
| builder.setEnPassantPawn(movedPawn); | |
| builder.setMoveMaker(this.board.currentPlayer().getOpponent().getAlliance()); | |
| return builder.build(); | |
| } | |
| } | |
| static abstract class CastleMove extends Moves { | |
| //TODO : Read more about castle move on Wikipedia | |
| protected final Rook castleRook; | |
| protected final int castleRookStart; | |
| protected final int castleRookDestination; | |
| public CastleMove(final Board board, | |
| final Piece movedPieces, | |
| final int destinationCandidator, | |
| final Rook castleRook, | |
| final int castleRookDestination, | |
| final int castleRookStart) { | |
| super(board, movedPieces, destinationCandidator); | |
| this.castleRook = castleRook; | |
| this.castleRookDestination=castleRookDestination; | |
| this.castleRookStart=castleRookStart; | |
| } | |
| public Rook getCastleRook(){ | |
| return this.castleRook; | |
| } | |
| @Override | |
| public boolean isCastelingMove(){ | |
| return true; | |
| } | |
| @Override | |
| public Board execute(){ | |
| final Builder builder = new Builder(); | |
| for (final Piece piece : this.board.currentPlayer().getActivePieces()){ | |
| //This loop meaning : if the piece that we're setting on the board is not the moved piece & is not the castle rook ,then set the piece | |
| if(!(this.movedPieces.equals(piece)) && !this.castleRook.equals(piece)){ | |
| builder.setPiece(piece); | |
| } | |
| } | |
| for (final Piece piece:this.board.currentPlayer().getOpponent().getActivePieces()){ | |
| builder.setPiece(piece); | |
| } | |
| //HERE : Move the king to it's desitnaiotn location and we moved the Rook with 2nd and 3rd statement | |
| // and made an new rook and set it on castle side | |
| builder.setPiece(this.movedPieces.movePiece(this)); | |
| builder.setPiece(new Rook(this.castleRook.getPieceAlliance(),this.castleRookDestination)); | |
| builder.setMoveMaker(this.board.currentPlayer().getOpponent().getAlliance()); | |
| return builder.build(); | |
| } | |
| }//CstleMove class end | |
| public static final class KingSideCastleMove extends CastleMove { | |
| public KingSideCastleMove(final Board board, | |
| final Piece movedPieces, | |
| final int destinationCandidate, | |
| final Rook castleRook, | |
| final int castleRookDestination, | |
| final int castleRookStart) { | |
| super(board, movedPieces, destinationCandidate,castleRook,castleRookDestination,castleRookStart); | |
| } | |
| @Override | |
| public String toString(){ | |
| return "O-O"; | |
| } | |
| } | |
| public static final class QueenSideCastleMove extends CastleMove { | |
| public QueenSideCastleMove(final Board board, | |
| final Piece movedPieces, | |
| final int destinationCandidate, | |
| final Rook castleRook, | |
| final int castleRookDestination, | |
| final int castleRookStart) { | |
| super(board, movedPieces, destinationCandidate,castleRook,castleRookDestination,castleRookStart); | |
| } | |
| public String toString(){ | |
| return "O-O-O"; | |
| } | |
| } | |
| public static final class NullMove extends Moves { | |
| public NullMove() { | |
| super(null, null, -1); | |
| } | |
| @Override | |
| public Board execute() { | |
| throw new RuntimeException("Can't execute this null move"); | |
| } | |
| } | |
| public static class MoveFactory { | |
| private MoveFactory() { | |
| throw new RuntimeException("Not instantiatable!"); | |
| } | |
| public static Moves createMove(final Board board, | |
| final int currentCoordinate, | |
| final int destinationCoordinate) { | |
| for (final Moves move : board.getAllLegalMoves()) { | |
| if (move.getCurrentCoordinate() == currentCoordinate && | |
| move.getDestinationCoordinate() == destinationCoordinate) { | |
| return move; | |
| } | |
| } | |
| return NULL_MOVE; | |
| } | |
| } | |
| }///Class end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Created by ibrahim on 4/25/17. | |
| */ | |
| package com.chess.engine.board; | |
| import com.chess.engine.pieces.Piece; | |
| import com.google.common.collect.ImmutableMap; | |
| import java.util.HashMap; | |
| import java.util.Map; | |
| public abstract class Tile { | |
| //It's will be set on the construction time ->final , it can only be accessed by its subclasses ->protected | |
| protected final int tileCoordinate; | |
| //Empty tile map constructor , and we made it private because we don't want anybody to change it later | |
| //to use the empty tile map you MUST have the guava library on your pc | |
| private static final Map<Integer,EmptyTile> EMPTY_TILES_CACHE = createAllPossibleEmptyTiles(); | |
| private static Map<Integer,EmptyTile> createAllPossibleEmptyTiles(){ | |
| final Map<Integer,EmptyTile>emptyTileMap = new HashMap<>(); | |
| for(int i=0;i<BoardUtils.NUM_TILES;i++){ | |
| emptyTileMap.put(i,new EmptyTile(i)); | |
| } | |
| return ImmutableMap.copyOf(emptyTileMap); | |
| /* | |
| Immutable time map is part of guava library which is 3rd party library provided by google | |
| i want an immutable map ,a map | |
| to understand mutable and immutable class you can check Effective Java book . | |
| */ | |
| } | |
| public static Tile createTile(final int tileCoordinate,final Object piece){ | |
| return piece != null ? new OccupiedTile(tileCoordinate, (Piece) piece) : EMPTY_TILES_CACHE.get(tileCoordinate); | |
| /* | |
| the only method that anyone's going to be allowed to use on my class to create a tile | |
| is going to be discrete tile . | |
| and they ever won an empty tile they're going to get one of the cached empty tiles | |
| Otherwise, they're going to create a new occupied tile | |
| we could cash all possible occupied tiles | |
| */ | |
| } //End of my method for creating or getting cached tile | |
| //My Coordinator constructor | |
| private Tile(final int tileCoordinate){ | |
| this.tileCoordinate = tileCoordinate; | |
| } | |
| //Abstract boolean method for checking is the tile occupied or not! | |
| public abstract boolean isTileOccupied(); | |
| public abstract Piece getPiece(); | |
| public int getTileCoordinate(){ | |
| return this.tileCoordinate; | |
| } | |
| //Empty tile class | |
| public static final class EmptyTile extends Tile{ | |
| private EmptyTile(final int coordinate){ | |
| super(coordinate); | |
| } //End of the Constructor | |
| @Override | |
| public String toString(){ | |
| return "-"; | |
| //if the tile is empty it will return " - " | |
| } | |
| @Override | |
| public boolean isTileOccupied(){ | |
| return false; | |
| } //End of boolean method TileOccupied | |
| @Override | |
| public Piece getPiece(){ | |
| return null; | |
| } //End of the Piece getPiece method. | |
| } | |
| /* | |
| ====================================================================== | |
| If you are coding after me, i was thinking about coordinating out tile,Then | |
| i'll find my way to draw and get some piece of art :"D | |
| */ | |
| //Otherwise , if the tile is not empty but occupied !.. | |
| public static final class OccupiedTile extends Tile{ | |
| private final Piece pieceOnTile; //Object of Piece class | |
| //Constructor for occupied tile will take the coordinate and the piece | |
| private OccupiedTile(int tileCoordinate,final Piece pieceOnTile){ | |
| super(tileCoordinate); //super class constructor will establish the tile coordinate | |
| this.pieceOnTile=pieceOnTile; // pieceOnTile will be equal the pieceOnTile that passed form the constructor | |
| } //end of OccupiedTile Constructor | |
| @Override | |
| public String toString(){ | |
| return getPiece().getPieceAlliance().isBlack() ? getPiece().toString().toLowerCase() : | |
| getPiece().toString(); | |
| //if the tile is occupied it'll print it out | |
| //#Black pieces will be shown up in UPERCASE , #White pieces will be in lower case | |
| } | |
| @Override | |
| public boolean isTileOccupied(){ | |
| return true; | |
| }//end of the boolean method isTileOccupied | |
| @Override | |
| public Piece getPiece(){ | |
| return this.pieceOnTile; | |
| } //End of getting my piece | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.pieces; | |
| import com.chess.engine.Alliance; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.BoardUtils; | |
| import com.chess.engine.board.Moves; | |
| import com.chess.engine.board.Tile; | |
| import com.google.common.collect.ImmutableList; | |
| import java.util.ArrayList; | |
| import java.util.Collection; | |
| import java.util.List; | |
| import static com.chess.engine.board.Moves.*; | |
| /** | |
| * Created by ibrahim on 4/28/17. | |
| */ | |
| public class Bishop extends Piece { | |
| private final static int[] CANDIDATE_MOVE_VECTOR_COORDINATE = {-9 , -7 , 7 , 9}; | |
| public Bishop( final Alliance pieceAlliance,final int piecePosition) { | |
| super(PieceType.BISHOP,piecePosition, pieceAlliance); | |
| } | |
| @Override | |
| public Collection<Moves> calculateLegalMoves(final Board board) { | |
| final List<Moves> legalMoves = new ArrayList<>(); | |
| for (final int candidateCoordinateOffset:CANDIDATE_MOVE_VECTOR_COORDINATE){ | |
| int candidateDestinationCoordinate = this.piecePosition; | |
| while (BoardUtils.isValidTileCoordinate(candidateDestinationCoordinate)){ | |
| if(isFirstColumnExclusion(candidateDestinationCoordinate,candidateCoordinateOffset) || | |
| isEighthColumnExclusion(candidateDestinationCoordinate,candidateCoordinateOffset)) | |
| { | |
| break; | |
| } | |
| candidateDestinationCoordinate += candidateCoordinateOffset; | |
| if(BoardUtils.isValidTileCoordinate(candidateDestinationCoordinate)) { | |
| final Tile candidateDestinationTile = board.getTile(candidateDestinationCoordinate); //We can say it's lyk an next destination where the piece will go on | |
| if(!candidateDestinationTile.isTileOccupied()){ | |
| legalMoves.add(new MajorMove(board,this,candidateDestinationCoordinate)); | |
| } //End of if condition | |
| else { | |
| final Piece pieceAtDestination=candidateDestinationTile.getPiece(); | |
| final Alliance pieceAlliance = pieceAtDestination.getPieceAlliance(); //The Alliance of the piece | |
| if(this.pieceAlliance != pieceAlliance) { | |
| legalMoves.add(new AttackMove(board,this,candidateDestinationCoordinate,pieceAtDestination)); | |
| } //The current piece "knight" Alliance != the piece alliance of the piece that's at our destination | |
| break; //This means the tile is occupied then we will keep going on , if it's done we will stop doing that | |
| }//if it's occupied | |
| } | |
| } | |
| } | |
| return ImmutableList.copyOf(legalMoves); | |
| } | |
| @Override | |
| public Bishop movePiece(Moves move) { | |
| return new Bishop(move.getMovedPieces().getPieceAlliance(),move.getDestinationCoordinate()); | |
| } | |
| @Override | |
| public String toString(){ | |
| return PieceType.BISHOP.toString(); | |
| } | |
| private static boolean isFirstColumnExclusion(final int currentPosition, final int candidateOffset) { | |
| return BoardUtils.FIRST_COLUMN[currentPosition] && (candidateOffset ==-1); | |
| }//End of the method | |
| private static boolean isEighthColumnExclusion(final int currentPosition, final int candidateOffset) { | |
| return BoardUtils.EIGHTH_COLUMN[currentPosition] && (candidateOffset ==1); | |
| }//End of the method | |
| } | |
| /* | |
| You Can check the Knight's class to understand this code too. | |
| */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.pieces; | |
| import com.chess.engine.Alliance; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.BoardUtils; | |
| import com.chess.engine.board.Moves; | |
| import com.chess.engine.board.Tile; | |
| import com.google.common.collect.ImmutableList; | |
| import java.util.ArrayList; | |
| import java.util.Collection; | |
| import java.util.List; | |
| import static com.chess.engine.board.Moves.*; | |
| /** | |
| * Created by ibrahim on 4/30/17. | |
| */ | |
| public class King extends Piece { | |
| private final static int[] CANDIDATE_MOVE_COORDINATE = {-9,-8,-7,-1,1,7,8,9}; | |
| public King(final Alliance pieceAlliance,final int piecePosition) { | |
| super(PieceType.KING,piecePosition, pieceAlliance); | |
| } | |
| @Override | |
| public Collection<Moves> calculateLegalMoves(Board board) { | |
| final List<Moves> legalMoves = new ArrayList<>(); | |
| for (final int currentCandidateOffset:CANDIDATE_MOVE_COORDINATE){ | |
| final int candidateDestinationCoordinate = this.piecePosition+currentCandidateOffset; | |
| if(isFirstColumnExclusion(this.piecePosition,currentCandidateOffset) || | |
| isEighthColumnExclusion(this.piecePosition,currentCandidateOffset)) { | |
| continue; | |
| } | |
| if(BoardUtils.isValidTileCoordinate(candidateDestinationCoordinate)){ | |
| final Tile candidateDestinationTile = board.getTile(candidateDestinationCoordinate); | |
| if(!candidateDestinationTile.isTileOccupied()){ | |
| legalMoves.add(new MajorMove(board,this,candidateDestinationCoordinate)); | |
| } //End of if condition | |
| else { | |
| final Piece pieceAtDestination=candidateDestinationTile.getPiece(); | |
| final Alliance pieceAlliance = pieceAtDestination.getPieceAlliance(); //The Alliance of the piece | |
| if(this.pieceAlliance != pieceAlliance) { | |
| legalMoves.add(new AttackMove(board,this,candidateDestinationCoordinate,pieceAtDestination)); | |
| } //The current piece "knight" Alliance != the piece alliance of the piece that's at our destination | |
| }//if it's occupied | |
| }//If condition end | |
| }//End of the for loop | |
| return ImmutableList.copyOf(legalMoves); | |
| }//Override end | |
| @Override | |
| public King movePiece(Moves move) { | |
| return new King(move.getMovedPieces().getPieceAlliance(),move.getDestinationCoordinate()); | |
| } | |
| @Override | |
| public String toString(){ | |
| return PieceType.KING.toString(); | |
| } | |
| private static boolean isFirstColumnExclusion(final int currentPosition,final int candidateOffset){ | |
| /* We need a way to capture all the tile coordinates , the correspond to give a column or a raw */ | |
| return BoardUtils.FIRST_COLUMN[currentPosition] && (candidateOffset == -9 || candidateOffset == -1 | |
| || candidateOffset == 7); | |
| } | |
| private static boolean isEighthColumnExclusion(final int currentPosition,final int candidateOffset){ | |
| return BoardUtils.EIGHTH_COLUMN[currentPosition] && (candidateOffset == 9 || candidateOffset ==-7 || candidateOffset ==1); | |
| } | |
| }//Class end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.pieces; | |
| import com.chess.engine.Alliance; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.BoardUtils; | |
| import com.chess.engine.board.Moves; | |
| import com.chess.engine.board.Tile; | |
| import com.google.common.collect.ImmutableList; | |
| import java.util.ArrayList; | |
| import java.util.Collection; | |
| import java.util.List; | |
| import static com.chess.engine.board.Moves.*; | |
| //Beginning of the knight class | |
| public class Knight extends Piece { | |
| private final static int[] CANDIDATE_MOVE_CORDINATES = { -17,-15,-10,-6,6,10,15,17}; //Fixed candidate destinations for the knight | |
| public Knight( Alliance pieceAlliance, int piecePosition) { | |
| super(PieceType.KNIGHT,piecePosition, pieceAlliance); | |
| } | |
| @Override | |
| public Collection<Moves> calculateLegalMoves(final Board board) { | |
| final List<Moves> legalMoves= new ArrayList<>(); | |
| for (final int currentCandidateOffset:CANDIDATE_MOVE_CORDINATES){ | |
| /* ====================How This Code Works ? =========================================================== | |
| We say that the candidate destination coordinate is my current position plus the current canidate , | |
| then if that is a valid tile and noneOccupied then we gonna add sort of non-attacking legal move, | |
| Otherwise if it's occupied ,then we get the alliance of the piece that is occupying the tile | |
| and if the alliance of that piece is not equal to this current knights alliance then we going to | |
| add an attacking move, | |
| After we built those all up we're going to return all of those legal moves | |
| "You can read the most bottom comment to understand it better .. | |
| ==================================================================================================== | |
| */ | |
| final int candidateDestinationCoordinate = this.piecePosition + currentCandidateOffset; | |
| if(BoardUtils.isValidTileCoordinate(candidateDestinationCoordinate)) { | |
| if(isFirstColumnExclusion(this.piecePosition,currentCandidateOffset) || | |
| isSecondColumnExclusion(this.piecePosition,currentCandidateOffset) || | |
| isSeventhColumnExclusion(this.piecePosition,currentCandidateOffset) || | |
| isEighthColumnExclusion(this.piecePosition,currentCandidateOffset)) { | |
| continue; | |
| } | |
| final Tile candidateDestinationTile = board.getTile(candidateDestinationCoordinate); //We can say it's lyk an next destination where the piece will go on | |
| if(!candidateDestinationTile.isTileOccupied()){ | |
| legalMoves.add(new MajorMove(board,this,candidateDestinationCoordinate)); | |
| } //End of if condition | |
| else { | |
| final Piece pieceAtDestination=candidateDestinationTile.getPiece(); | |
| final Alliance pieceAlliance = pieceAtDestination.getPieceAlliance(); //The Alliance of the piece | |
| if(this.pieceAlliance != pieceAlliance) { | |
| legalMoves.add(new AttackMove(board,this,candidateDestinationCoordinate,pieceAtDestination)); | |
| } //The current piece "knight" Alliance != the piece alliance of the piece that's at our destination | |
| }//if it's occupied | |
| } | |
| } //End of for loop | |
| return ImmutableList.copyOf(legalMoves); | |
| } //End of method | |
| @Override | |
| public Knight movePiece(Moves move) { | |
| return new Knight(move.getMovedPieces().getPieceAlliance(),move.getDestinationCoordinate()); | |
| } | |
| @Override | |
| public String toString(){ | |
| return PieceType.KNIGHT.toString(); | |
| } | |
| private static boolean isFirstColumnExclusion(final int currentPosition,final int candidateOffset){ | |
| /* We need a way to capture all the tile coordiantes , the corespond to give a column or a raw */ | |
| return BoardUtils.FIRST_COLUMN[currentPosition] && (candidateOffset == -17 || candidateOffset == -10 | |
| || candidateOffset == 6 || candidateOffset ==15); | |
| } | |
| private static boolean isSecondColumnExclusion(final int currentPosition,final int candidateOffset){ | |
| return BoardUtils.SECOND_COLUMN[currentPosition] && (candidateOffset == -10 || candidateOffset ==6); | |
| } | |
| private static boolean isSeventhColumnExclusion(final int currentPosition,final int candidateOffset){ | |
| return BoardUtils.SEVENTH_COLUMN[currentPosition] && (candidateOffset == -6 || candidateOffset ==10); | |
| } | |
| private static boolean isEighthColumnExclusion(final int currentPosition,final int candidateOffset){ | |
| return BoardUtils.EIGHTH_COLUMN[currentPosition] && (candidateOffset == -15 || candidateOffset ==-6 | |
| ||candidateOffset==10 || candidateOffset==17); | |
| } | |
| } | |
| /* | |
| ===============================Algorithm of code :"D ============================== | |
| You can google it easier :"D !.. | |
| =================================================================================== | |
| =================================================================================== | |
| we will loop through candidate offsets "CANDIDATE_MOVE_CORDINATES" , and we want to | |
| go ahead and apply the offset to the current position | |
| "if that position is valid on tile" -> then we will check if it's occupied or not | |
| if it's not occupied -> we will make non-attacking move ! | |
| else -> we will end it's occupying by and enemy piece by making an attacking move | |
| =================================================================================== | |
| */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.pieces; | |
| import com.chess.engine.Alliance; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.BoardUtils; | |
| import com.chess.engine.board.Moves; | |
| import com.google.common.collect.ImmutableList; | |
| import java.util.ArrayList; | |
| import java.util.Collection; | |
| import java.util.List; | |
| import static com.chess.engine.board.Moves.*; | |
| /** | |
| * Created by ibrahim on 4/30/17. | |
| */ | |
| public class Pawn extends Piece { | |
| private final static int[] CANDIDATE_MOVE_COORDINATE = {8,16,7,9}; | |
| public Pawn(final Alliance pieceAlliance, final int piecePosition) { | |
| super(PieceType.PAWN,piecePosition, pieceAlliance); | |
| } | |
| @Override | |
| public Collection<Moves> calculateLegalMoves(final Board board) { | |
| final List<Moves> legalMoves = new ArrayList<>(); | |
| for (final int currentCandidateOffset:CANDIDATE_MOVE_COORDINATE){ | |
| final int candidateDestinationCoordinate = this.piecePosition + (this.pieceAlliance.getDirection()*currentCandidateOffset); //For blacks it'll apply 8 , for whites will apply -8 | |
| if (BoardUtils.isValidTileCoordinate(candidateDestinationCoordinate)){ | |
| continue; | |
| }//End of if condition | |
| if (currentCandidateOffset==8 && !board.getTile(candidateDestinationCoordinate).isTileOccupied()) //If the tile is not occupied then i'll try to make a jump or an regular move | |
| { | |
| //TODO we will be back soon to this condition. | |
| legalMoves.add(new MajorMove(board,this,candidateDestinationCoordinate)); | |
| } | |
| //The first else if statement describes the first pawn jump | |
| else if (currentCandidateOffset == 16 && this.isFirstMove() && (BoardUtils.SEVENTH_RANK[this.piecePosition] && this.getPieceAlliance().isBlack()) | |
| ||(BoardUtils.SECOND_RANK[this.piecePosition] && this.getPieceAlliance().isWhite())) { | |
| final int behindCandidateDestinationCoordinate = this.piecePosition +(this.getPieceAlliance().getDirection()*8); | |
| if(!board.getTile(behindCandidateDestinationCoordinate).isTileOccupied() && !board.getTile(candidateDestinationCoordinate).isTileOccupied()) { | |
| legalMoves.add(new MajorMove(board,this,candidateDestinationCoordinate)); | |
| }//End of if statement | |
| } //end of else if | |
| else if (currentCandidateOffset == 7 && | |
| !(BoardUtils.EIGHTH_COLUMN[this.piecePosition] && this.pieceAlliance.isWhite() || | |
| BoardUtils.FIRST_COLUMN[this.piecePosition] && this.pieceAlliance.isBlack())) | |
| /*When you are in the eighth column & you are white then the 7 rule does'nt work , because you'll be in the same row , so you need extra 2 - so you'll use 9 rule- steps to attack | |
| To understand this more you can see a tile and a pawn in 1st or 8th column , if he's black or white how can he attack another piece from another alliance | |
| I think by this way you gonna understand it well. | |
| */ | |
| { | |
| if(board.getTile(candidateDestinationCoordinate).isTileOccupied()) { | |
| final Piece pieceOnCandidate =board.getTile(candidateDestinationCoordinate).getPiece(); | |
| if(this.pieceAlliance != pieceOnCandidate.getPieceAlliance()) { | |
| //TODO "There is more work here". | |
| legalMoves.add(new MajorMove(board,this,candidateDestinationCoordinate)); | |
| }//End of if statement | |
| }//End of bigger if statement | |
| }//End of else if | |
| else if (currentCandidateOffset == 9 && | |
| !(BoardUtils.FIRST_COLUMN[this.piecePosition] && this.pieceAlliance.isWhite() || | |
| BoardUtils.EIGHTH_COLUMN[this.piecePosition] && this.pieceAlliance.isBlack())){ | |
| if(board.getTile(candidateDestinationCoordinate).isTileOccupied()) { | |
| final Piece pieceOnCandidate =board.getTile(candidateDestinationCoordinate).getPiece(); | |
| if(this.pieceAlliance != pieceOnCandidate.getPieceAlliance()) { | |
| //TODO "There is more work here". | |
| legalMoves.add(new MajorMove(board,this,candidateDestinationCoordinate)); | |
| }//End of if statement | |
| }//End of bigger if statement | |
| }//End of else if statement | |
| }//End of the for loop | |
| return ImmutableList.copyOf(legalMoves); | |
| }//End of the overriding | |
| @Override | |
| public Pawn movePiece(Moves move) { | |
| return new Pawn(move.getMovedPieces().getPieceAlliance(),move.getDestinationCoordinate()); | |
| } | |
| @Override | |
| public String toString(){ | |
| return PieceType.PAWN.toString(); | |
| } | |
| }//End of the class |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Created by ibrahim on 4/25/17. | |
| */ | |
| package com.chess.engine.pieces; | |
| //List of imports | |
| import com.chess.engine.Alliance; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.Moves; | |
| import java.util.Collection; | |
| //My Class | |
| public abstract class Piece { | |
| protected final PieceType pieceType; | |
| protected final int piecePosition; //Every piece has it own position | |
| protected final Alliance pieceAlliance; //i have whites and blacks , so i should have alliance | |
| protected final boolean isFirstMove; | |
| private final int cachedHashCode; | |
| Piece(final PieceType pieceType, | |
| final int piecePosition , | |
| final Alliance pieceAlliance) { | |
| this.pieceType=pieceType; | |
| this.pieceAlliance= pieceAlliance; | |
| this.piecePosition= piecePosition; | |
| this.cachedHashCode=computeHashCode(); | |
| this.isFirstMove = false; | |
| } //End of constructor | |
| @Override | |
| public boolean equals(final Object other){ | |
| if(this == other){ | |
| return true; | |
| } | |
| if(!(other instanceof Piece)){ | |
| return false; | |
| } | |
| final Piece otherPiece = (Piece) other; | |
| return piecePosition == otherPiece.piecePosition && pieceType == otherPiece.pieceType && | |
| pieceAlliance == otherPiece.pieceAlliance && isFirstMove == otherPiece.isFirstMove; | |
| } | |
| @Override | |
| public int hashCode(){ | |
| return this.cachedHashCode; | |
| } | |
| private int computeHashCode() { | |
| int result = pieceType.hashCode(); | |
| result = 31 * result + pieceAlliance.hashCode(); | |
| result = 31 * result + piecePosition; | |
| result = 31 * result + (isFirstMove ? 1 : 0); | |
| return result; | |
| } | |
| public PieceType getPieceType(){ | |
| return this.pieceType; | |
| } | |
| public int getPiecePosition(){ | |
| return this.piecePosition; | |
| } | |
| public Alliance getPieceAlliance() { | |
| return this.pieceAlliance; | |
| }//Piece alliance method end | |
| //public Alliance pieceAlliance() { return this.pieceAlliance; } | |
| public boolean isFirstMove(){ | |
| return this.isFirstMove; | |
| }//End of isFristMove method | |
| //Every piece will be extend of this method , and override the calculate move. | |
| public abstract Collection<Moves> calculateLegalMoves(final Board board); //method for calculating legal moves | |
| public abstract Piece movePiece(Moves move); | |
| public enum PieceType{ | |
| PAWN("P") { | |
| @Override | |
| public boolean isKing() { | |
| return false; | |
| } | |
| @Override | |
| public boolean isRook() { | |
| return false; | |
| } | |
| }, | |
| KNIGHT("N") { | |
| @Override | |
| public boolean isKing() { | |
| return false; | |
| } | |
| @Override | |
| public boolean isRook() { | |
| return false; | |
| } | |
| }, | |
| BISHOP("B") { | |
| @Override | |
| public boolean isKing() { | |
| return false; | |
| } | |
| @Override | |
| public boolean isRook() { | |
| return false; | |
| } | |
| }, | |
| ROOK("R") { | |
| @Override | |
| public boolean isKing() { | |
| return false; | |
| } | |
| @Override | |
| public boolean isRook() { | |
| return true; | |
| } | |
| }, | |
| QUEEN("Q") { | |
| @Override | |
| public boolean isKing() { | |
| return false; | |
| } | |
| @Override | |
| public boolean isRook() { | |
| return false; | |
| } | |
| }, | |
| KING("K") { | |
| @Override | |
| public boolean isKing() { | |
| return true; | |
| } | |
| @Override | |
| public boolean isRook() { | |
| return false; | |
| } | |
| }; | |
| private String pieceName; | |
| PieceType(final String pieceName) { | |
| this.pieceName = pieceName; | |
| }//Piece name method end | |
| @Override | |
| public String toString(){ | |
| return this.pieceName; | |
| } | |
| public abstract boolean isKing(); | |
| public abstract boolean isRook(); | |
| }//end of the enum | |
| } //End of the Piece class |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.pieces; | |
| import com.chess.engine.Alliance; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.BoardUtils; | |
| import com.chess.engine.board.Moves; | |
| import com.chess.engine.board.Tile; | |
| import com.google.common.collect.ImmutableList; | |
| import java.util.ArrayList; | |
| import java.util.Collection; | |
| import java.util.List; | |
| /** | |
| * Created by ibrahim on 4/28/17. | |
| */ | |
| public class Queen extends Piece{ | |
| private final static int[] CANDIDATE_MOVE_VECTOR_COORDINATE = {-9,-8,-7, -1, 1,7,8,9}; | |
| public Queen( Alliance pieceAlliance, int piecePosition) { | |
| super(PieceType.QUEEN,piecePosition, pieceAlliance); | |
| } | |
| @Override | |
| public Collection<Moves> calculateLegalMoves(final Board board) { | |
| final List<Moves> legalMoves = new ArrayList<>(); | |
| for (final int candidateCoordinateOffset:CANDIDATE_MOVE_VECTOR_COORDINATE){ | |
| int candidateDestinationCoordinate = this.piecePosition; | |
| while (BoardUtils.isValidTileCoordinate(candidateDestinationCoordinate)){ | |
| if(isFirstColumnExclusion(candidateDestinationCoordinate,candidateCoordinateOffset) || | |
| isEighthColumnExclusion(candidateDestinationCoordinate,candidateCoordinateOffset)) | |
| { | |
| break; | |
| } | |
| candidateDestinationCoordinate += candidateCoordinateOffset; | |
| if(BoardUtils.isValidTileCoordinate(candidateDestinationCoordinate)) { | |
| final Tile candidateDestinationTile = board.getTile(candidateDestinationCoordinate); //We can say it's lyk an next destination where the piece will go on | |
| if(!candidateDestinationTile.isTileOccupied()){ | |
| legalMoves.add(new Moves.MajorMove(board,this,candidateDestinationCoordinate)); | |
| } //End of if condition | |
| else { | |
| final Piece pieceAtDestination=candidateDestinationTile.getPiece(); | |
| final Alliance pieceAlliance = pieceAtDestination.getPieceAlliance(); //The Alliance of the piece | |
| if(this.pieceAlliance != pieceAlliance) { | |
| legalMoves.add(new Moves.AttackMove(board,this,candidateDestinationCoordinate,pieceAtDestination)); | |
| } //The current piece "knight" Alliance != the piece alliance of the piece that's at our destination | |
| break; //This means the tile is occupied then we will keep going on , if it's done we will stop doing that | |
| }//if it's occupied | |
| } | |
| } | |
| } | |
| return ImmutableList.copyOf(legalMoves); | |
| } | |
| @Override | |
| public Queen movePiece(Moves move) { | |
| return new Queen(move.getMovedPieces().getPieceAlliance(),move.getDestinationCoordinate()); | |
| } | |
| @Override | |
| public String toString(){ | |
| return PieceType.QUEEN.toString(); | |
| } | |
| private static boolean isFirstColumnExclusion(final int currentPosition, final int candidateOffset) { | |
| return BoardUtils.FIRST_COLUMN[currentPosition] && (candidateOffset == -9 || candidateOffset == -1 || | |
| candidateOffset == 7); | |
| }//End of the method | |
| private static boolean isEighthColumnExclusion(final int currentPosition, final int candidateOffset) { | |
| return BoardUtils.EIGHTH_COLUMN[currentPosition] && (candidateOffset == 9 || candidateOffset == 1|| | |
| candidateOffset == -7); | |
| }//End of the method} | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.pieces; | |
| import com.chess.engine.Alliance; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.BoardUtils; | |
| import com.chess.engine.board.Moves; | |
| import com.chess.engine.board.Tile; | |
| import com.google.common.collect.ImmutableList; | |
| import java.util.ArrayList; | |
| import java.util.Collection; | |
| import java.util.List; | |
| /** | |
| * Created by ibrahim on 4/28/17. | |
| */ | |
| public class Rook extends Piece { | |
| private final static int[] CANDIDATE_MOVE_VECTOR_COORDINATE = {-8, -1, 1, 8}; | |
| public Rook(Alliance pieceAlliance | |
| ,int piecePosition) { | |
| super(PieceType.ROOK,piecePosition, pieceAlliance); | |
| } | |
| @Override | |
| public Collection<Moves> calculateLegalMoves(final Board board) { | |
| final List<Moves> legalMoves = new ArrayList<>(); | |
| for (final int candidateCoordinateOffset : CANDIDATE_MOVE_VECTOR_COORDINATE) { | |
| int candidateDestinationCoordinate = this.piecePosition; | |
| while (BoardUtils.isValidTileCoordinate(candidateDestinationCoordinate)) { | |
| if (isFirstColumnExclusion(candidateDestinationCoordinate, candidateCoordinateOffset) || | |
| isEighthColumnExclusion(candidateDestinationCoordinate, candidateCoordinateOffset)) { | |
| break; | |
| } | |
| candidateDestinationCoordinate += candidateCoordinateOffset; | |
| if (BoardUtils.isValidTileCoordinate(candidateDestinationCoordinate)) { | |
| final Tile candidateDestinationTile = board.getTile(candidateDestinationCoordinate); //We can say it's lyk an next destination where the piece will go on | |
| if (!candidateDestinationTile.isTileOccupied()) { | |
| legalMoves.add(new Moves.MajorMove(board, this, candidateDestinationCoordinate)); | |
| } //End of if condition | |
| else { | |
| final Piece pieceAtDestination = candidateDestinationTile.getPiece(); | |
| final Alliance pieceAlliance = pieceAtDestination.getPieceAlliance(); //The Alliance of the piece | |
| if (this.pieceAlliance != pieceAlliance) { | |
| legalMoves.add(new Moves.AttackMove(board, this, candidateDestinationCoordinate, pieceAtDestination)); | |
| } //The current piece "knight" Alliance != the piece alliance of the piece that's at our destination | |
| break; //This means the tile is occupied then we will keep going on , if it's done we will stop doing that | |
| }//if it's occupied | |
| } | |
| } | |
| } | |
| return ImmutableList.copyOf(legalMoves); | |
| } | |
| @Override | |
| public Rook movePiece(Moves move) { | |
| return new Rook(move.getMovedPieces().getPieceAlliance(),move.getDestinationCoordinate()); | |
| } | |
| @Override | |
| public String toString(){ | |
| return PieceType.ROOK.toString(); | |
| } | |
| private static boolean isFirstColumnExclusion(final int currentPosition, final int candidateOffset) { | |
| return BoardUtils.FIRST_COLUMN[currentPosition] && (candidateOffset == -9 || candidateOffset == 7); | |
| }//End of the method | |
| private static boolean isEighthColumnExclusion(final int currentPosition, final int candidateOffset) { | |
| return BoardUtils.EIGHTH_COLUMN[currentPosition] && (candidateOffset == 9 || candidateOffset == -7); | |
| }//End of the method} | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.player; | |
| import com.chess.engine.Alliance; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.Moves; | |
| import com.chess.engine.board.Tile; | |
| import com.chess.engine.pieces.Piece; | |
| import com.chess.engine.pieces.Rook; | |
| import com.google.common.collect.ImmutableList; | |
| import java.util.ArrayList; | |
| import java.util.Collection; | |
| import java.util.List; | |
| import static com.chess.engine.board.Moves.*; | |
| /** | |
| * Created by ibrahim on 5/1/17. | |
| */ | |
| public class BlackPlayer extends Player{ | |
| public BlackPlayer(final Board board, | |
| final Collection<Moves> whiteStanderedLegalMoves, | |
| final Collection<Moves> blackStanderedLegalMoves) { | |
| super(board,blackStanderedLegalMoves,whiteStanderedLegalMoves); | |
| } | |
| @Override | |
| public Collection<Piece> getActivePieces() { | |
| return this.board.getBlackPieces(); | |
| } | |
| @Override | |
| public Alliance getAlliance() { | |
| return Alliance.BLACK; | |
| } | |
| @Override | |
| public Player getOpponent() { | |
| return this.board.whitePlayer(); | |
| } | |
| @Override | |
| protected Collection<Moves> calculateKingCastles(final Collection<Moves> playerLegals, | |
| final Collection<Moves> opponentsLegals) { | |
| final List<Moves> KingCastles = new ArrayList<>(); | |
| if(this.playerKing.isFirstMove() && !this.isInCheck()){ | |
| //Black King Side Castle | |
| if(!this.board.getTile(5).isTileOccupied() && !this.board.getTile(6).isTileOccupied()){ | |
| final Tile rookTile = this.board.getTile(7); | |
| if(rookTile.isTileOccupied() && rookTile.getPiece().isFirstMove()){ | |
| if(Player.calculateAttacksOnTile(5,opponentsLegals).isEmpty() && | |
| Player.calculateAttacksOnTile(6,opponentsLegals).isEmpty() && | |
| rookTile.getPiece().getPieceType().isRook()){ | |
| KingCastles.add(new KingSideCastleMove(this.board, | |
| this.playerKing, | |
| 6, | |
| (Rook)rookTile.getPiece(), | |
| rookTile.getTileCoordinate(), | |
| 5)); | |
| }//one more if | |
| }//end if | |
| }//end if | |
| //Black Queen Side Castle | |
| if(!this.board.getTile(1).isTileOccupied() && | |
| !this.board.getTile(2).isTileOccupied() && | |
| !this.board.getTile(3).isTileOccupied()){ | |
| final Tile rookTile = this.board.getTile(0); | |
| if(rookTile.isTileOccupied() && rookTile.getPiece().isFirstMove() && | |
| Player.calculateAttacksOnTile(2,opponentsLegals).isEmpty() && | |
| Player.calculateAttacksOnTile(3,opponentsLegals).isEmpty() && | |
| rookTile.getPiece().getPieceType().isRook()){ | |
| KingCastles.add(new QueenSideCastleMove(this.board, | |
| this.playerKing, | |
| 2, | |
| (Rook)rookTile.getPiece(), | |
| rookTile.getTileCoordinate(), | |
| 3)); | |
| } | |
| } | |
| }//end if | |
| return ImmutableList.copyOf(KingCastles); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.player; | |
| /** | |
| * Created by ibrahim on 5/1/17. | |
| */ | |
| public enum MoveStatus { | |
| DONE{ | |
| @Override | |
| boolean isDone(){ | |
| return true; | |
| } | |
| }, | |
| ILLEGAL_MOVE{ | |
| @Override | |
| boolean isDone(){ | |
| return false; | |
| } | |
| }, | |
| LEAVES_PLAYER_IN_CHECK{ | |
| @Override | |
| boolean isDone(){ | |
| return false; | |
| } | |
| }; | |
| abstract boolean isDone(); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.player; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.Moves; | |
| /** | |
| * Created by ibrahim on 5/1/17. | |
| */ | |
| public class MoveTransition { | |
| //The transition board , the board that you going to make a transion to after making a move | |
| private final Board transitionBoard; | |
| private final Moves move; | |
| private final MoveStatus moveStatus; //it'll tell us weather we are able to do the move or not | |
| public MoveTransition(final Board transitionBoard, | |
| final Moves move, | |
| final MoveStatus moveStatus){ | |
| this.moveStatus=moveStatus; | |
| this.move=move; | |
| this.transitionBoard=transitionBoard; | |
| } | |
| public MoveStatus getMoveStatus(){ | |
| return this.moveStatus; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.player; | |
| import com.chess.engine.Alliance; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.Moves; | |
| import com.chess.engine.pieces.King; | |
| import com.chess.engine.pieces.Piece; | |
| import com.google.common.collect.ImmutableList; | |
| import com.google.common.collect.Iterables; | |
| import java.util.ArrayList; | |
| import java.util.Collection; | |
| import java.util.List; | |
| /** | |
| * Created by ibrahim on 5/1/17. | |
| */ | |
| public abstract class Player { | |
| protected final Board board; | |
| protected final King playerKing; | |
| protected final Collection<Moves> legalMoves; | |
| private final boolean isInCheck; | |
| protected Player(final Board board, | |
| final Collection<Moves> legalMoves, | |
| final Collection<Moves> opponentMoves) { | |
| // | |
| this.board =board; | |
| this.playerKing = establishKing(); | |
| this.legalMoves = ImmutableList.copyOf(Iterables.concat(legalMoves,calculateKingCastles(legalMoves,opponentMoves))); | |
| this.isInCheck = !Player.calculateAttacksOnTile(this.playerKing.getPiecePosition(),opponentMoves).isEmpty(); | |
| //we will pass the king's current location , and pass the enimes moves , and see if the destination coordinate of ther moves | |
| //if it does attacking the king , we will get a collection of moves that attacks the king's position | |
| //and calculate the current player check , if the list is empty so it's not a check | |
| }//constructor end | |
| public King getPlayerKing(){ | |
| return this.playerKing; | |
| } | |
| public Collection<Moves> getLegalMoves(){ | |
| return this.legalMoves; | |
| } | |
| protected static Collection<Moves> calculateAttacksOnTile(int piecePosition, Collection<Moves> moves) | |
| { | |
| final List<Moves> attackMoves = new ArrayList<>(); | |
| for (final Moves move:moves){ | |
| if(piecePosition == move.getDestinationCoordinate()){ | |
| attackMoves.add(move); | |
| } | |
| } | |
| return ImmutableList.copyOf(attackMoves); | |
| } | |
| protected King establishKing() { | |
| for(final Piece piece : getActivePieces()) { | |
| if(piece.getPieceType().isKing()) { | |
| return (King) piece; | |
| } | |
| } | |
| throw new RuntimeException("Should not reach here! " +this.getAlliance()+ " king could not be established!"); | |
| //If the piece is the king and it's going to return it ,if we get through the loop | |
| //we were not able to establish the king we are going to throw a run time exception | |
| //زي كأنك بتقول للي بيلعب ان المنطقة دي مينفعش يلعب فيها | |
| } | |
| public boolean isMoveLeagl(final Moves move){ | |
| return this.legalMoves.contains(move); //TODO review this syntax again on google | |
| } | |
| public boolean isInCheck(){ | |
| return this.isInCheck; | |
| } | |
| public boolean isInCheckMate(){ | |
| return this.isInCheck && !hasEscapeMoves(); | |
| } | |
| private boolean hasEscapeMoves(){ | |
| for (final Moves move : this.legalMoves){ | |
| final MoveTransition transition = makeMove(move); | |
| if (transition.getMoveStatus().isDone()){ | |
| return true; | |
| } | |
| } | |
| return false; | |
| //we will pass the king's current location , and pass the enimes moves , and see if the destination coordinate of ther moves | |
| //if it does attacking the king , we will get a collection of moves that attacks the king's position | |
| //and calculate the current player check , if the list is empty so it's not a check | |
| //For loop for making a move , if there is noway , so it will return false and it'll be a checkmate | |
| //بيعمل زي حركات وهمية بس مش علي الBoard قدامك , بيشوف فيها ازاي الملك ميبقاش كش مات | |
| } | |
| public boolean isInStaleMate(){ | |
| //You are not in check but also you don't have escape moves ! | |
| return !this.isInCheck && !hasEscapeMoves(); | |
| } | |
| public boolean isCasteled(){ | |
| return false; | |
| } | |
| //when we make a move we are going to return a move transition to rap the board that the transition is to. | |
| public MoveTransition makeMove(final Moves move){ | |
| if (!isMoveLeagl(move)){ | |
| return new MoveTransition(this.board,move,MoveStatus.ILLEGAL_MOVE); | |
| }//end if | |
| //if the move is not illegal | |
| final Board transitionBoard= move.execute(); | |
| final Collection<Moves> kingAttacks = Player.calculateAttacksOnTile(transitionBoard.currentPlayer().getOpponent().getPlayerKing().getPiecePosition(), | |
| transitionBoard.currentPlayer().getLegalMoves()); | |
| if(!kingAttacks.isEmpty()){ | |
| return new MoveTransition(this.board,move,MoveStatus.LEAVES_PLAYER_IN_CHECK); | |
| } | |
| return new MoveTransition(transitionBoard,move,MoveStatus.DONE); | |
| /* ========================Explanation=====================*/ | |
| /* if the move is ILLEGAL it's not part of the collection of legal moves that the player has, | |
| then, do the move transation that your return that doesn't take us to a new board, | |
| it returns to the same board and the move status is illegal.. | |
| --- | |
| The next thing is we use the move to POLYMORPHICLY EXECUTE the move and return us a new board | |
| the we transition to. | |
| And we ask ,Are there any attacks on the current player's king when we do that ? | |
| if there are -> you can NOT make that move.. | |
| otherwise -> return the move transition board wrapped in a new move transition | |
| you can't make any moves that exposes your king to check. | |
| To calculate the attacks on the king , we invoked " calculateAttacksOnTile" , and we pass in | |
| the current player's opponent king, becaus after we make the move , we're no longer the current player | |
| ,so we get the king's current position and then we get the curent players legal moves. | |
| this's gonna return a new board, where the current player switches to the opponent | |
| "Lyk if we are whites and seeing if blacks can have an attacks on the king or not" | |
| */ | |
| } | |
| public abstract Collection<Piece> getActivePieces(); | |
| public abstract Alliance getAlliance(); | |
| public abstract Player getOpponent(); | |
| protected abstract Collection<Moves> calculateKingCastles(Collection<Moves> playerLegals, Collection<Moves> opponentsLegals); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.engine.player; | |
| import com.chess.engine.Alliance; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.Moves; | |
| import com.chess.engine.board.Tile; | |
| import com.chess.engine.pieces.Piece; | |
| import com.chess.engine.pieces.Rook; | |
| import com.google.common.collect.ImmutableList; | |
| import java.util.ArrayList; | |
| import java.util.Collection; | |
| import java.util.List; | |
| import static com.chess.engine.board.Moves.*; | |
| /** | |
| * Created by ibrahim on 5/1/17. | |
| */ | |
| public class WhitePlayer extends Player { | |
| public WhitePlayer(final Board board, | |
| final Collection<Moves> whiteStanderedLegalMoves, | |
| final Collection<Moves> blackStanderedLegalMoves) { | |
| super(board,whiteStanderedLegalMoves,blackStanderedLegalMoves); | |
| } | |
| @Override | |
| public Collection<Piece> getActivePieces() { | |
| return this.board.getWhitePieces(); | |
| } | |
| @Override | |
| public Alliance getAlliance() { | |
| return Alliance.WHITE; | |
| } | |
| @Override | |
| public Player getOpponent() { | |
| return this.board.blackPlayer(); | |
| } | |
| @Override | |
| protected Collection<Moves> calculateKingCastles(final Collection<Moves> playerLegals, | |
| final Collection<Moves> opponentsLegals) { | |
| final List<Moves> KingCastles = new ArrayList<>(); | |
| if(this.playerKing.isFirstMove() && !this.isInCheck()){ | |
| //King Side Castle | |
| if(!this.board.getTile(61).isTileOccupied() && !this.board.getTile(62).isTileOccupied()){ | |
| final Tile rookTile = this.board.getTile(63); | |
| if(rookTile.isTileOccupied() && rookTile.getPiece().isFirstMove()){ | |
| if(Player.calculateAttacksOnTile(61,opponentsLegals).isEmpty() && | |
| Player.calculateAttacksOnTile(62,opponentsLegals).isEmpty() && | |
| rookTile.getPiece().getPieceType().isRook()){ | |
| KingCastles.add(new KingSideCastleMove(this.board, | |
| this.playerKing, | |
| 62, | |
| (Rook)rookTile.getPiece(), | |
| rookTile.getTileCoordinate(), | |
| 61)); | |
| //The above statements are the in between tiles in castling | |
| }//one more if | |
| }//end if | |
| }//end if | |
| //Queen Side Castle | |
| if(!this.board.getTile(59).isTileOccupied() && | |
| !this.board.getTile(58).isTileOccupied() && | |
| !this.board.getTile(57).isTileOccupied()){ | |
| final Tile rookTile = this.board.getTile(56); | |
| if(rookTile.isTileOccupied() && rookTile.getPiece().isFirstMove() && | |
| Player.calculateAttacksOnTile(58,opponentsLegals).isEmpty() && | |
| Player.calculateAttacksOnTile(59,opponentsLegals).isEmpty() && | |
| rookTile.getPiece().getPieceType().isRook()){ | |
| KingCastles.add(new QueenSideCastleMove(this.board, | |
| this.playerKing, | |
| 58, | |
| (Rook)rookTile.getPiece(), | |
| rookTile.getTileCoordinate(), | |
| 59)); | |
| } | |
| } | |
| }//end if | |
| return ImmutableList.copyOf(KingCastles); | |
| }//end of collection | |
| }//class end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess.gui; | |
| import com.chess.engine.board.Board; | |
| import com.chess.engine.board.BoardUtils; | |
| import javax.imageio.ImageIO; | |
| import javax.swing.*; | |
| import java.awt.*; | |
| import java.awt.event.ActionEvent; | |
| import java.awt.event.ActionListener; | |
| import java.awt.image.BufferedImage; | |
| import java.io.File; | |
| import java.io.IOException; | |
| import java.util.*; | |
| import java.util.List; | |
| /** | |
| * Created by ibrahim on 5/3/17. | |
| */ | |
| public class Table { | |
| private final JFrame gameFrame; | |
| private final BoardPanel boardPanel; | |
| private final Board chessBoard; | |
| private static String defaultPieceImagePath = "art/pieces/plains/"; | |
| private static final Dimension BOARD_PANEL_DIMENSION = new Dimension(400,400); | |
| private final static Dimension OUTER_FRAME_DIMENSION = new Dimension(600,600); | |
| private static final Dimension TILE_PANEL_DIMENSION =new Dimension(10,10) ; | |
| private final Color lightTileColor = Color.decode("#FFFACD"); | |
| private final Color darkTileColor = Color.decode("#593E1A"); | |
| public Table() { | |
| this.gameFrame = new JFrame("JChess"); | |
| this.gameFrame.setLayout(new BorderLayout()); | |
| final JMenuBar tableMenuBar= createTableMenuBar(); | |
| this.gameFrame.setJMenuBar(tableMenuBar); | |
| this.boardPanel= new BoardPanel(); | |
| this.gameFrame.add(this.boardPanel,BorderLayout.CENTER); | |
| this.chessBoard = Board.createStanderedBoard(); | |
| this.gameFrame.setSize(OUTER_FRAME_DIMENSION); | |
| this.gameFrame.setVisible(true); | |
| } | |
| private JMenuBar createTableMenuBar() { | |
| final JMenuBar tableMenuBar = new JMenuBar(); | |
| tableMenuBar.add(createFileMenu()); | |
| return tableMenuBar; | |
| }//end of method " populate menu bar" | |
| private JMenu createFileMenu() { | |
| final JMenu fileMenu = new JMenu("file"); | |
| final JMenuItem openPGN = new JMenuItem("Load PGN File"); | |
| openPGN.addActionListener(new ActionListener() { | |
| @Override | |
| public void actionPerformed(ActionEvent e) { | |
| System.out.println("Open up the PGN File!"); | |
| } | |
| }); | |
| fileMenu.add(openPGN); | |
| final JMenuItem exitMenuItem= new JMenuItem("Exit"); | |
| exitMenuItem.addActionListener(new ActionListener() { | |
| @Override | |
| public void actionPerformed(ActionEvent e) { | |
| System.exit(0); | |
| } | |
| }); | |
| fileMenu.add(exitMenuItem); | |
| return fileMenu; | |
| }//End of create file menu | |
| private class BoardPanel extends JPanel { | |
| //this class creats 8*8 JPanel -> 64 tiles for chess | |
| final List<TilePanel> boardTiles; | |
| BoardPanel(){ | |
| super(new GridLayout(8,8)); | |
| this.boardTiles = new ArrayList<>(); | |
| for (int i=0 ; i< BoardUtils.NUM_TILES;i++){ | |
| final TilePanel tilePanel= new TilePanel(this,i); | |
| this.boardTiles.add(tilePanel); | |
| add(tilePanel); | |
| //Each tile keeping and adding two of JPanels | |
| }//for loop end | |
| setPreferredSize(BOARD_PANEL_DIMENSION); | |
| validate(); | |
| } | |
| }//end of board panel | |
| private class TilePanel extends JPanel{ | |
| //Maps our tile in our game | |
| private final int tileId; | |
| TilePanel(final BoardPanel boardPanel, | |
| final int tileId){ | |
| super(new GridBagLayout()); | |
| this.tileId = tileId; | |
| setPreferredSize(TILE_PANEL_DIMENSION); | |
| assignTileColor(); | |
| assignTilePieceIcon(Board.createStanderedBoard()); | |
| validate(); | |
| } | |
| private void assignTilePieceIcon(final Board board){ | |
| this.removeAll(); | |
| if (board.getTile(this.tileId).isTileOccupied()){ | |
| try { | |
| final BufferedImage image = ImageIO.read(new File(defaultPieceImagePath + | |
| board.getTile(this.tileId).getPiece().getPieceAlliance().toString().substring(0, 1) + | |
| board.getTile(this.tileId).getPiece().toString() + ".gif")); | |
| add(new JLabel(new ImageIcon(image))); | |
| } catch (IOException e) { | |
| e.printStackTrace(); | |
| } | |
| } | |
| } | |
| private void assignTileColor() { | |
| if (BoardUtils.EIGHTH_RANK[this.tileId] || | |
| BoardUtils.SIXTH_RANK[this.tileId] || | |
| BoardUtils.FOURTH_RANK[this.tileId]|| | |
| BoardUtils.SECOND_RANK[this.tileId]){ | |
| setBackground(this.tileId % 2 == 0 ? lightTileColor : darkTileColor); | |
| } | |
| else if(BoardUtils.SEVENTH_RANK[this.tileId]|| | |
| BoardUtils.FIFTH_RANK[this.tileId]|| | |
| BoardUtils.THIRD_RANK[this.tileId]|| | |
| BoardUtils.FIRST_RANK[this.tileId]){ | |
| setBackground(this.tileId % 2 != 0 ? lightTileColor : darkTileColor); | |
| } | |
| }///Assign tile color | |
| }//end of tile panel | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.chess; | |
| import com.chess.engine.board.Board; | |
| import com.chess.gui.Table; | |
| /** | |
| * Created by ibrahim on 5/1/17. | |
| */ | |
| public class JChess { | |
| public static void main(String[] args){ | |
| Board board = Board.createStanderedBoard(); | |
| System.out.println(board); | |
| Table table = new Table(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment