Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,29 @@ local/
lib_testing/
.pypirc

test.py
test.py

# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
45 changes: 0 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,3 @@
This is a chess engine implemented in python.

> Note: This is being rewritten in Java now

## Features
What you __can__ do now:
1. Import any game using a FEN string
2. Move any piece
3. Capture any piece
4. Check the king

What you __cannot__ do now:
1. Checkmate the king
2. Castle
3. En passant capture

## How to play:
First, clone this repository and then run:
```
python main.py
```
If you want to overwrite default starting position, you can import a custom board by passing a fen string as an argument as follows:
```
python main.py "starting_fen"
```
By default game starts in GUI, if you want to debug and run in CLI use the ``-c`` flag like below:
```
python main.py -c
```
## How to play
Just drag and drop a piece to move it.

## How to give user input in CLI
Input is taken as follows, __with__ space in between
```
<starting_square> <ending square>
```
A square is denoted by the following:
```
<rank><file> // algebraic notation
```
where ranks (horizontal rows) are from 1 to 8 (bottom to top), and files (vertical columns) from A to H (left to right).

For example if you want to move your pawn from ``e2`` to ``e4`` then:
```
e2 e4
```
The inputs are case __insensitive__.
1 change: 0 additions & 1 deletion requirements.txt

This file was deleted.

52 changes: 52 additions & 0 deletions src/board/Board.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package src.board;

import src.fen.Fen;
import src.fen.InvalidFenStringException;
import src.pieces.Color;
import src.positions.PositionTuple;

public class Board {
public static final int BOARD_SIZE = 8;

private Grid grid;
private Color activeColor;

private boolean canWhiteCastleKingSide = false;
private boolean canWhiteCastleQueenSide = false;
private boolean canBlackCastleKingSide = false;
private boolean canBlackCastleQueenSide = false;

private PositionTuple enPassantMove;

private int halfMoveCounter;
private int fullMoveCounter;

public Board(String fen_string) {
Fen fen;
try {
fen = new Fen(fen_string);
} catch (InvalidFenStringException err) {
System.out.println("Error: " + err);
return;
}

grid = new Grid(fen.boardState);

activeColor = fen.activeColor == 'w' ? Color.WHITE : Color.BLACK;

canWhiteCastleKingSide = fen.canWhiteCastleKingSide;
canWhiteCastleQueenSide = fen.canWhiteCastleQueenSide;
canBlackCastleKingSide = fen.canBlackCastleKingSide;
canBlackCastleQueenSide = fen.canBlackCastleQueenSide;

if (fen.enPassantMove.compareTo("-") == 0) {
enPassantMove = null;
}
else {
enPassantMove = new PositionTuple(fen.enPassantMove);
}

halfMoveCounter = fen.halfMoveCounter;
fullMoveCounter = fen.fullMoveCounter;
}
}
41 changes: 41 additions & 0 deletions src/board/Grid.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package src.board;

import src.pieces.*;

import static src.board.Board.BOARD_SIZE;

class Grid {
private Piece[][] grid;

public Grid(char[][] boardState) {
grid = new Piece[BOARD_SIZE][BOARD_SIZE];

for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
switch (boardState[i][j]) {
case 'K' -> { grid[i][j] = new King(Color.WHITE); }
case 'Q' -> { grid[i][j] = new Queen(Color.WHITE); }
case 'R' -> { grid[i][j] = new Rook(Color.WHITE); }
case 'B' -> { grid[i][j] = new Bishop(Color.WHITE); }
case 'N' -> { grid[i][j] = new Knight(Color.WHITE); }
case 'P' -> { grid[i][j] = new Pawn(Color.WHITE); }
case 'k' -> { grid[i][j] = new King(Color.BLACK); }
case 'q' -> { grid[i][j] = new Queen(Color.BLACK); }
case 'r' -> { grid[i][j] = new Rook(Color.BLACK); }
case 'b' -> { grid[i][j] = new Bishop(Color.BLACK); }
case 'n' -> { grid[i][j] = new Knight(Color.BLACK); }
case 'p' -> { grid[i][j] = new Pawn(Color.BLACK); }
case '-' -> {}
}
}
}
}

public void setPiece(int rank, int file, Piece piece) {
grid[rank][file] = piece;
}

public Piece getPiece(int rank, int file) {
return grid[rank][file];
}
}
94 changes: 94 additions & 0 deletions src/fen/Fen.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package src.fen;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static src.board.Board.BOARD_SIZE;

public class Fen {
private static final Pattern FEN_PATTERN = Pattern.compile(
"^([1-8kqrbnp]+\\/){7}[1-8kqrbnp]+\\s[wb]\\s([-]|[kq]+)\\s([-]|[a-h][1-8])\\s(\\d+)\\s(\\d+)$",
Pattern.CASE_INSENSITIVE
);

// Position data in a FEN string
private static final int BOARD_STATE = 0;
private static final int ACTIVE_COLOR = 1;
private static final int CASTLING_AVAILABILITY = 2;
private static final int EN_PASSANT_MOVE = 3;
private static final int HALF_MOVE_COUNT = 4;
private static final int FULL_MOVE_COUNT = 5;

public char[][] boardState;
public char activeColor;

public boolean canWhiteCastleKingSide = false;
public boolean canWhiteCastleQueenSide = false;
public boolean canBlackCastleKingSide = false;
public boolean canBlackCastleQueenSide = false;

public String enPassantMove;

public int halfMoveCounter;
public int fullMoveCounter;

public Fen(String fenString) throws InvalidFenStringException {
Matcher matcher = FEN_PATTERN.matcher(fenString);
if (!matcher.matches()) {
throw new InvalidFenStringException();
}

String[] fenData = fenString.split(" ");

boardState = new char[BOARD_SIZE][BOARD_SIZE];
parseBoardState(fenData[BOARD_STATE]);

activeColor = fenData[ACTIVE_COLOR].charAt(0);

setCastlingAvailability(fenData[CASTLING_AVAILABILITY]);

enPassantMove = fenData[EN_PASSANT_MOVE];

halfMoveCounter = Integer.parseInt(fenData[HALF_MOVE_COUNT]);
fullMoveCounter = Integer.parseInt(fenData[FULL_MOVE_COUNT]);
}

private void parseBoardState(String boardStateString) throws InvalidFenStringException {
String[] ranks = boardStateString.split("/");

for (int i = 0; i < BOARD_SIZE; i++) {
int j = 0;

for (char ch: ranks[i].toCharArray()) {
if (j >= BOARD_SIZE) throw new InvalidFenStringException();

if (Character.isDigit(ch)) {
int noOfEmptySquares = ch - '0';

for (int k = 0; k < noOfEmptySquares; k++) {
if (j >= BOARD_SIZE) throw new InvalidFenStringException();

boardState[i][j] = '-';
j++;
}
}

else {
boardState[i][j] = ch;
j++;
}
}
}
}

private void setCastlingAvailability(String castlingData) {
for (char ch: castlingData.toCharArray()) {
switch (ch) {
case 'K' -> { canWhiteCastleKingSide = true; }
case 'Q' -> { canWhiteCastleQueenSide = true; }
case 'k' -> { canBlackCastleKingSide = true; }
case 'q' -> { canBlackCastleQueenSide = true; }
}
}
}
}
7 changes: 7 additions & 0 deletions src/fen/InvalidFenStringException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package src.fen;

public class InvalidFenStringException extends Exception {
public InvalidFenStringException() {
super("Invalid Fen String");
}
}
15 changes: 15 additions & 0 deletions src/pieces/Bishop.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package src.pieces;

public class Bishop extends Piece {
private static final String ICON_WHITE = "♗";
private static final String ICON_BLACK = "♝";

public Bishop(Color color) {
this.color = color;

name = Pieces.BISHOP;
isSlider = true;
isMoved = false;
icon = color == Color.WHITE ? ICON_WHITE : ICON_BLACK;
}
}
16 changes: 16 additions & 0 deletions src/pieces/Color.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package src.pieces;

public enum Color {
WHITE(0),
BLACK(1);

private final int value;

private Color(int value) {
this.value = value;
}

public int getValue() {
return value;
}
}
15 changes: 15 additions & 0 deletions src/pieces/King.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package src.pieces;

public class King extends Piece {
private static final String ICON_WHITE = "♔";
private static final String ICON_BLACK = "♚";

public King(Color color) {
this.color = color;

name = Pieces.KING;
isSlider = false;
isMoved = false;
icon = color == Color.WHITE ? ICON_WHITE : ICON_BLACK;
}
}
15 changes: 15 additions & 0 deletions src/pieces/Knight.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package src.pieces;

public class Knight extends Piece {
private static final String ICON_WHITE = "♘";
private static final String ICON_BLACK = "♞";

public Knight(Color color) {
this.color = color;

name = Pieces.KNIGHT;
isSlider = false;
isMoved = false;
icon = color == Color.WHITE ? ICON_WHITE : ICON_BLACK;
}
}
15 changes: 15 additions & 0 deletions src/pieces/Pawn.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package src.pieces;

public class Pawn extends Piece {
private static final String ICON_WHITE = "♙";
private static final String ICON_BLACK = "♟";

public Pawn(Color color) {
this.color = color;

name = Pieces.KING;
isSlider = false;
isMoved = false;
icon = color == Color.WHITE ? ICON_WHITE : ICON_BLACK;
}
}
22 changes: 22 additions & 0 deletions src/pieces/Piece.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package src.pieces;

public abstract class Piece {
Pieces name;
Color color;

String icon;
boolean isMoved;
boolean isSlider;

public Color getColor() {
return color;
}

public Pieces getName() {
return name;
}

public String getIcon() {
return icon;
}
}
Loading