Initial commit
23
.gitignore
vendored
Normal file → Executable file
|
@ -1,22 +1 @@
|
|||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
spec.pdf
|
||||
|
|
4
media/LICENSE
Executable file
|
@ -0,0 +1,4 @@
|
|||
The image files for the chess pieces were made by Wikipedia user @Cburnett
|
||||
<https://en.wikipedia.org/wiki/User:Cburnett> and licensed under a Creative
|
||||
Commons BY-SA 3.0 Unported License. More information about this license can be
|
||||
found at <https://creativecommons.org/licenses/by-sa/3.0/>.
|
BIN
media/SelectedSquare.jpg
Executable file
After Width: | Height: | Size: 666 B |
BIN
media/black1.png
Executable file
After Width: | Height: | Size: 984 B |
BIN
media/black2.png
Executable file
After Width: | Height: | Size: 838 B |
BIN
media/black3.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
media/black4.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
media/black5.png
Executable file
After Width: | Height: | Size: 2.3 KiB |
BIN
media/black6.png
Executable file
After Width: | Height: | Size: 1.9 KiB |
BIN
media/white1.png
Executable file
After Width: | Height: | Size: 970 B |
BIN
media/white2.png
Executable file
After Width: | Height: | Size: 812 B |
BIN
media/white3.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
media/white4.png
Executable file
After Width: | Height: | Size: 1.4 KiB |
BIN
media/white5.png
Executable file
After Width: | Height: | Size: 2.3 KiB |
BIN
media/white6.png
Executable file
After Width: | Height: | Size: 1.9 KiB |
420
src/ChessBoard.java
Executable file
|
@ -0,0 +1,420 @@
|
|||
/******************************************************************************
|
||||
* ChessSim 0.9 *
|
||||
* Copyright © 2015 Ben Goldsworthy (rumperuu) *
|
||||
* *
|
||||
* A program to simulate a game of chess between two human players. *
|
||||
* *
|
||||
* This file is part of ChessSim. *
|
||||
* *
|
||||
* ChessSim is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* ChessSim is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with ChessSim. If not, see <http://www.gnu.org/licenses/>. *
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
** This class represents a chess board, utilised in the ChessSim program.
|
||||
**/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.Frame;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.event.*;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
** @author Ben Goldsworthy (rumperuu) <me+chesssim@bengoldsworthy.net>
|
||||
** @version 0.92
|
||||
**/
|
||||
public class ChessBoard implements ActionListener, MouseListener {
|
||||
private final int DEFAULT = 0, PIECESELECTED = 1;
|
||||
private final int PAWN = 0, ROOK = 1, KNIGHT = 2, BISHOP = 3, QUEEN = 4,
|
||||
KING = 5;
|
||||
private final int WHITE = 0, BLACK = 1;
|
||||
private final int NONE = 0, MOVABLE = 1, ATTACKABLE = 2;
|
||||
private final int NULL = 9999;
|
||||
|
||||
private boolean colour = true;
|
||||
// Sets the initial piece (as a BLACK PAWN because the first piece placed
|
||||
// is `piece++`, or the ROOK).
|
||||
private int piece = PAWN, team = BLACK;
|
||||
// Creates the 2D array to hold the `ChessBoard` of `ChessSquare`s.
|
||||
private ChessSquare[][] chessSquare = new ChessSquare[8][8];
|
||||
// Creates a 3D array to hold the `ChessBoard` of chess `Piece`s.
|
||||
private Piece[][][] pieces = new Piece[6][2][8];
|
||||
private Piece selectedPiece;
|
||||
// Admittedly, the `ChessLogic` object doesn't do an awful lot right now
|
||||
// but it'll be useful if I come back to this to add actual game rules
|
||||
// (https://github.com/Rumperuu/ChessSim/issues/1).
|
||||
private ChessLogic logic = new ChessLogic();
|
||||
|
||||
public ChessBoard() {
|
||||
// Initialises the piece indices.
|
||||
int pawnNum = 0, rookNum = 0, knightNum = 0, bishopNum = 0;
|
||||
|
||||
// Sorts out the window, fullscreening and suchlike.
|
||||
JFrame window = new JFrame();
|
||||
window.setExtendedState(Frame.MAXIMIZED_BOTH);
|
||||
window.setUndecorated(true);
|
||||
window.setTitle("Chess, but not as you know it");
|
||||
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
// Creates a grid panel for the `ChessBoard` of `ChessSquare`s.
|
||||
JPanel board = new JPanel();
|
||||
GridLayout grid = new GridLayout(8,8);
|
||||
board.setLayout(grid);
|
||||
|
||||
// For each rank 'y'...
|
||||
for (int y = 0; y <= 7; y++) {
|
||||
// ...switch the populating team to white if the black team's done.
|
||||
if (y == 2) {
|
||||
team = WHITE;
|
||||
pawnNum = 0;
|
||||
rookNum = 0;
|
||||
knightNum = 0;
|
||||
bishopNum = 0;
|
||||
}
|
||||
// Reset the square colour (e.g. the last square of row 0 is black,
|
||||
// meaning the first square of row 1 would be set to white later on
|
||||
// if not for this line).
|
||||
colour = !colour;
|
||||
// Resets the piece to `PAWN`.
|
||||
piece = 0;
|
||||
// ...and for each square in file 'x' of rank 'y'...
|
||||
for (int x = 0; x <= 7; x++) {
|
||||
// ...populate the board array with a new `ChessSquare`.
|
||||
chessSquare[x][y] = new ChessSquare(x,y,colour);
|
||||
// Change the colour for the next square.
|
||||
colour = !colour;
|
||||
// Add the `ChessSquare` to the board.
|
||||
board.add(chessSquare[x][y]);
|
||||
// Checks if the current rank is the top or bottom two
|
||||
// (one of the only current uses of the `ChessLogic` class).
|
||||
if (logic.startingRow(y)) {
|
||||
// Checks if the current rank is the back rank
|
||||
// (one of the other uses).
|
||||
if (logic.backRank(y)) {
|
||||
// If the square in file 'x' is the Queen or lower, increment
|
||||
// `piece`...
|
||||
if (x <= 4) piece++;
|
||||
// ...else, if the square is the King, subtract 2 (to avoid
|
||||
// two Queens).
|
||||
else if (x == 5) piece = piece - 2;
|
||||
// Otherwise, decrement `piece`.
|
||||
else piece--;
|
||||
|
||||
// Depending on the piece currently being added, populate
|
||||
// the appropriate array dimension.
|
||||
switch(piece) {
|
||||
case ROOK:
|
||||
pieces[ROOK][team][rookNum] = new Piece(x,y,team,
|
||||
ROOK,rookNum);
|
||||
chessSquare[x][y].setPiece(pieces[ROOK][team][rookNum++]);
|
||||
break;
|
||||
case KNIGHT:
|
||||
pieces[KNIGHT][team][knightNum]= new Piece(x,y,team,KNIGHT,
|
||||
knightNum);
|
||||
chessSquare[x][y].setPiece(pieces[KNIGHT][team][knightNum++]);
|
||||
break;
|
||||
case BISHOP:
|
||||
pieces[BISHOP][team][bishopNum]= new Piece(x,y,team,BISHOP,
|
||||
bishopNum);
|
||||
chessSquare[x][y].setPiece(pieces[BISHOP][team][bishopNum++]);
|
||||
break;
|
||||
case QUEEN:
|
||||
pieces[QUEEN][team][0] = new Piece(x,y,team,QUEEN,0);
|
||||
chessSquare[x][y].setPiece(pieces[QUEEN][team][0]);
|
||||
break;
|
||||
case KING:
|
||||
pieces[KING][team][0] = new Piece(x,y,team,KING,0);
|
||||
chessSquare[x][y].setPiece(pieces[KING][team][0]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
pieces[PAWN][team][pawnNum]= new Piece(x,y,team,PAWN,pawnNum);
|
||||
chessSquare[x][y].setPiece(pieces[PAWN][team][pawnNum++]);
|
||||
}
|
||||
}
|
||||
// Adds the relevant listeners to the `ChessSquare`s.
|
||||
chessSquare[x][y].addActionListener(this);
|
||||
chessSquare[x][y].addMouseListener(this);
|
||||
}
|
||||
}
|
||||
// Finishes off the display.
|
||||
window.setContentPane(board);
|
||||
window.setVisible(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles the event of a `JButton` (or rather a `JButton`-extending
|
||||
* `ChessSquare`) being moused over. As long as no piece is currently
|
||||
* selected, the function displays faintly-highlighted available moves for
|
||||
* the piece moused over.
|
||||
*/
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
if (logic.getState() == DEFAULT) {
|
||||
ChessSquare enteredSquare = (ChessSquare)e.getSource();
|
||||
Piece presentPiece = null;
|
||||
if (enteredSquare.hasPiece()) {
|
||||
presentPiece = enteredSquare.getPiece();
|
||||
displayMoves(presentPiece, false);
|
||||
} else defaultSquares();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the other `MouseEvent`s, by not doing anything. Mouse dragging
|
||||
* could potentially be useful in a later version for some sort of click-and-
|
||||
* drag movement of pieces, but for now they're just here to get the compiler
|
||||
* to stop throwing up errors at me.
|
||||
*/
|
||||
public void mouseExited(MouseEvent e) {
|
||||
}
|
||||
public void mousePressed(MouseEvent e) {
|
||||
}
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
}
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles the event of a `JButton` (or rather a `JButton`-extending
|
||||
* `ChessSquare`) being clicked. The function, depending on the game state
|
||||
* and state of the `ChessSquare` clicked on, wipes the displayed moves from
|
||||
* the `ChessBoard` or moves the selected piece, removing an attacked piece
|
||||
* is necessary.
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
switch(logic.getState()) {
|
||||
case DEFAULT:
|
||||
ChessSquare selectedSquare = (ChessSquare) e.getSource();
|
||||
if (selectedSquare.hasPiece()) {
|
||||
selectedPiece = selectedSquare.getPiece();
|
||||
// If no piece is selected, select the clicked piece...
|
||||
displayMoves(selectedPiece, true);
|
||||
logic.setState(PIECESELECTED);
|
||||
}
|
||||
break;
|
||||
case PIECESELECTED:
|
||||
// ...else, if a piece is selected...
|
||||
ChessSquare clickedSquare = (ChessSquare)e.getSource();
|
||||
switch(clickedSquare.getState()) {
|
||||
case NONE:
|
||||
// ...if the square just clicked is an illegal move, wipe all moves
|
||||
// from the `ChessBoard`...
|
||||
defaultSquares();
|
||||
break;
|
||||
case MOVABLE:case ATTACKABLE:
|
||||
// get the coords of the new, clicked square
|
||||
int newX = clickedSquare.getXPosition();
|
||||
int newY = clickedSquare.getYPosition();
|
||||
// and the details of the old, selected piece
|
||||
int oldX = selectedPiece.getXPosition();
|
||||
int oldY = selectedPiece.getYPosition();
|
||||
int oldType = selectedPiece.getType();
|
||||
int oldTeam = selectedPiece.getTeam();
|
||||
int oldIndex = selectedPiece.getIndex();
|
||||
// move (and take the currently-residing piece, if
|
||||
// applicable) to the square clicked
|
||||
chessSquare[oldX][oldY].removePiece();
|
||||
clickedSquare.setPiece(selectedPiece);
|
||||
// update the location of the moved piece
|
||||
pieces[oldType][oldTeam][oldIndex].setXPosition(newX);
|
||||
pieces[oldType][oldTeam][oldIndex].setYPosition(newY);
|
||||
// if the moved piece was a pawn on its first move, disable its
|
||||
// two-square move ability
|
||||
if (oldType == PAWN)
|
||||
pieces[PAWN][oldTeam][oldIndex].usedUpFirstMove();
|
||||
|
||||
// wipes the `ChessBoard` clean
|
||||
defaultSquares();
|
||||
}
|
||||
// resets the state of the game
|
||||
logic.setState(DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Displays the legal moves a selected or hovered-over piece can make,
|
||||
* coloured according to whether the piece is selected or just hovered on.
|
||||
*/
|
||||
private void displayMoves(Piece piece, boolean hard) {
|
||||
// get the relevant details of the piece now
|
||||
List moves = new ArrayList();
|
||||
int pieceIndex = piece.getIndex();
|
||||
int pieceTeam = piece.getTeam();
|
||||
int pieceType = piece.getType();
|
||||
// get the relevant piece's complete moveset
|
||||
moves = pieces[pieceType][pieceTeam][pieceIndex].showMoves();
|
||||
|
||||
// wipe the ChessBoard
|
||||
defaultSquares();
|
||||
|
||||
// initialise the variable used to truncate movement paths due to
|
||||
// obstacles
|
||||
boolean skip = false;
|
||||
boolean pawn = (pieceType == PAWN) ? true : false;
|
||||
|
||||
// for the list of moves...
|
||||
for (int i = 0; i < moves.size()-1; i++) {
|
||||
// if the current move isn't the NULL character used as a terminator
|
||||
// between chains of moves (e.g. all in a given direction)...
|
||||
if ((int)moves.get(i) != NULL) {
|
||||
// gets the x- and y-coords for later
|
||||
int moveX = (int)moves.get(i);
|
||||
int moveY = (int)moves.get(++i);
|
||||
// sets skip to false, in case i got here from a truncate
|
||||
skip = false;
|
||||
// determines if the given ChessSquare is legal or illegal
|
||||
skip = highlightSquare(moveX, moveY, pieceTeam, pawn, hard);
|
||||
// if the square is illegal...
|
||||
if (skip) {
|
||||
// sets j to i to start from the current point in the movelist
|
||||
int j = i;
|
||||
// increment down the list from i until the next NULL
|
||||
// separator/end of the line
|
||||
while (((int)moves.get(j) != NULL) && (j < moves.size()-1)) {
|
||||
j++;
|
||||
}
|
||||
// set i to the value after that NULL
|
||||
i = j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the given piece is a pawn...
|
||||
if (pieceType == PAWN) {
|
||||
// get the coordinate for the square up and to the right of the pawn
|
||||
// (pX and pY have been used instead of something perhaps more
|
||||
// informative in order to keep the source code within 80
|
||||
// characters' width in the for loop below)
|
||||
int pX = pieces[PAWN][pieceTeam][pieceIndex].getXPosition() + 1;
|
||||
int pY = pieces[PAWN][pieceTeam][pieceIndex].getYPosition();
|
||||
|
||||
// gets the appropriate rank for the direction the pawn is moving
|
||||
if (pieceTeam == WHITE) pY -= 1;
|
||||
else pY += 1;
|
||||
|
||||
// performs the same task as highlightSquare(), but for the squares
|
||||
// a pawn can make an attack to
|
||||
for (int i=0;(pX < 8) && (pX > -1) && (i < 2);pX-=2,i++) {
|
||||
boolean squareEmpty = false;
|
||||
Piece presentPiece = null;
|
||||
if (chessSquare[pX][pY].hasPiece())
|
||||
presentPiece = chessSquare[pX][pY].getPiece();
|
||||
else squareEmpty = true;
|
||||
|
||||
if (!squareEmpty) {
|
||||
if ((presentPiece.getTeam() != pieceTeam)
|
||||
&& (presentPiece.getType() != KING)) {
|
||||
if (hard) {
|
||||
chessSquare[pX][pY].setBackground(new Color(255,0,0));
|
||||
chessSquare[pX][pY].setState(ATTACKABLE);
|
||||
} else {
|
||||
chessSquare[pX][pY].setBackground(new Color(127,127,127));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if this displaySquares() call is as a result of a piece being
|
||||
// selected...
|
||||
if (hard) {
|
||||
// changes the game state
|
||||
logic.setState(PIECESELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wipes the ChessBoard restoring the initial black & white checks.
|
||||
*/
|
||||
private void defaultSquares() {
|
||||
// this is the same code from the constructor earlier
|
||||
colour = true;
|
||||
for (int x = 0; x <= 7; x++) {
|
||||
colour = !colour;
|
||||
for (int y = 0; y <= 7; y++) {
|
||||
if (colour) chessSquare[x][y].setBackground(new Color(0, 0, 0));
|
||||
else chessSquare[x][y].setBackground(new Color(255, 255, 255));
|
||||
chessSquare[x][y].setState(NONE);
|
||||
|
||||
colour = !colour;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Highlights a given ChessSquare with colours dependent on a number of
|
||||
* factors.
|
||||
*/
|
||||
private boolean highlightSquare(int x, int y, int team,
|
||||
boolean pawn, boolean selected) {
|
||||
boolean squareEmpty = false;
|
||||
// get the piece on the selected square, if applicable
|
||||
Piece presentPiece = null;
|
||||
if (chessSquare[x][y].hasPiece())
|
||||
presentPiece = chessSquare[x][y].getPiece();
|
||||
else squareEmpty = true;
|
||||
// if this highlighting is a result of a piece being selected, rather
|
||||
// than just moused over...
|
||||
if (selected) {
|
||||
// if the square is clear...
|
||||
if (squareEmpty) {
|
||||
// sets the colour to green, and the state to that of a legal move
|
||||
chessSquare[x][y].setBackground(new Color(0, 100, 0));
|
||||
chessSquare[x][y].setState(MOVABLE);
|
||||
|
||||
// return that the square doesn't represent an obstacle
|
||||
return false;
|
||||
// ...else...
|
||||
} else {
|
||||
// ...if the square is occupied by an enemy piece...
|
||||
if (presentPiece.getTeam() != team) {
|
||||
// ...and the selected piece isn't a pawn (because their move
|
||||
// forward can't be used as an attack), and the occupying piece
|
||||
// isn't the enemy's king (because they can't be taken, only
|
||||
// put in check)...
|
||||
if ((!pawn) && (presentPiece.getType() != KING)) {
|
||||
// sets the colour to red, and the state to that of a legal
|
||||
// attack
|
||||
chessSquare[x][y].setBackground(new Color(255, 0, 0));
|
||||
chessSquare[x][y].setState(ATTACKABLE);
|
||||
}
|
||||
}
|
||||
|
||||
// return that the square does represent an obstacle
|
||||
return true;
|
||||
}
|
||||
// ...else, if the piece has just been highlighted over, do the same as
|
||||
// before, but with fainter shades of red and green
|
||||
} else {
|
||||
if (squareEmpty) {
|
||||
chessSquare[x][y].setBackground(new Color(127, 127, 127));
|
||||
|
||||
return false;
|
||||
} else {
|
||||
if (presentPiece.getTeam() != team) {
|
||||
if ((pawn)
|
||||
&& (presentPiece.getType() != KING)) {
|
||||
// sets the colour to red, and the state to that of a legal
|
||||
// attack
|
||||
chessSquare[x][y].setBackground(new Color(127, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
80
src/ChessLogic.java
Executable file
|
@ -0,0 +1,80 @@
|
|||
/******************************************************************************
|
||||
* ChessSim 0.9 *
|
||||
* Copyright © 2015 Ben Goldsworthy (rumperuu) *
|
||||
* *
|
||||
* A program to simulate a game of chess between two human players. *
|
||||
* *
|
||||
* This file is part of ChessSim. *
|
||||
* *
|
||||
* ChessSim is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* ChessSim is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with ChessSim. If not, see <http://www.gnu.org/licenses/>. *
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
** This class represents chess logic, utilised in the ChessSim program.
|
||||
**/
|
||||
|
||||
/**
|
||||
** @author Ben Goldsworthy (rumperuu) <me+chesssim@bengoldsworthy.net>
|
||||
** @version 0.90
|
||||
**/
|
||||
public class ChessLogic {
|
||||
// rumperuu <3 C-style pre-processor macros
|
||||
private final int DEFAULT = 0, PIECESELECTED = 1;
|
||||
|
||||
// stores the current state of the game
|
||||
private int currentState;
|
||||
|
||||
/**
|
||||
** Constructor function.
|
||||
**/
|
||||
public ChessLogic() {
|
||||
currentState = DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
** Determines if a given rank is the top or bottom two.
|
||||
** @param y the rank number
|
||||
** @return a boolean value
|
||||
**/
|
||||
public boolean startingRow(int y) {
|
||||
return (((y <= 1) || (y >= 6)) ? true : false);
|
||||
}
|
||||
|
||||
/**
|
||||
** Determines if a given rank is either team's back rank. Currently
|
||||
** used to populate pieces, but could also be called to deal with pawn
|
||||
** promotion if I ever got around to adding that.
|
||||
** @param y the rank number
|
||||
** @return a boolean value
|
||||
**/
|
||||
public boolean backRank(int y) {
|
||||
return (((y == 0) || (y == 7)) ? true: false);
|
||||
}
|
||||
|
||||
/**
|
||||
** Gets the current state of this chess game.
|
||||
** @return the state of this chess game
|
||||
*/
|
||||
public int getState() {
|
||||
return currentState;
|
||||
}
|
||||
|
||||
/**
|
||||
** Sets the state of this chess game.
|
||||
** @param state the state of this chess game
|
||||
*/
|
||||
public void setState(int state) {
|
||||
currentState = state;
|
||||
}
|
||||
}
|
32
src/ChessProgram.java
Executable file
|
@ -0,0 +1,32 @@
|
|||
/******************************************************************************
|
||||
* ChessSim 0.9 *
|
||||
* Copyright © 2015 Ben Goldsworthy (rumperuu) *
|
||||
* *
|
||||
* A program to simulate a game of chess between two human players. *
|
||||
* *
|
||||
* This file is part of ChessSim. *
|
||||
* *
|
||||
* ChessSim is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* ChessSim is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with ChessSim. If not, see <http://www.gnu.org/licenses/>. *
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
** @author Ben Goldsworthy (rumperuu) <me+chesssim@bengoldsworthy.net>
|
||||
** @version 0.90
|
||||
**/
|
||||
public class ChessProgram {
|
||||
public static void main(String[] arguments) {
|
||||
// creates a new instance of the ChessBoard object
|
||||
ChessBoard board = new ChessBoard();
|
||||
}
|
||||
}
|
160
src/ChessSquare.java
Executable file
|
@ -0,0 +1,160 @@
|
|||
/******************************************************************************
|
||||
* ChessSim 0.9 *
|
||||
* Copyright © 2015 Ben Goldsworthy (rumperuu) *
|
||||
* *
|
||||
* A program to simulate a game of chess between two human players. *
|
||||
* *
|
||||
* This file is part of ChessSim. *
|
||||
* *
|
||||
* ChessSim is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* ChessSim is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with ChessSim. If not, see <http://www.gnu.org/licenses/>. *
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
** This class represents a chess square, utilised in the ChessSim program.
|
||||
**/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
** @author Ben Goldsworthy (rumperuu) <me+chesssim@bengoldsworthy.net>
|
||||
** @version 0.90
|
||||
**/
|
||||
public class ChessSquare extends JButton {
|
||||
// C sells C shells on the C shore
|
||||
private final int NONE = 0, MOVABLE = 1, ATTACKABLE = 2;
|
||||
private final int NULL = 9999;
|
||||
private final int WHITE = 0, BLACK = 1;
|
||||
|
||||
// declares the array for piece icons
|
||||
private ImageIcon[][] pieces = new ImageIcon[2][6];
|
||||
// declares the values for storing the details relevant to each instance of
|
||||
// the ChessSquare
|
||||
private Piece currentPiece;
|
||||
private int xPosition, yPosition;
|
||||
private int currentState;
|
||||
|
||||
/**
|
||||
** Constructor function.
|
||||
** @param x the x-coord of the square, which doubles as its array x-index
|
||||
** @param y the y-coord of the square, which doubles as its array y-index
|
||||
** @param colour the colour of the square
|
||||
**/
|
||||
public ChessSquare(int x, int y, boolean colour) {
|
||||
// populates the array of piece icons
|
||||
for (int i = 1; i <= 6; i++) {
|
||||
pieces[WHITE][i-1] = new ImageIcon("images/white"+i+".png");
|
||||
pieces[BLACK][i-1] = new ImageIcon("images/black"+i+".png");
|
||||
}
|
||||
|
||||
xPosition = x;
|
||||
yPosition = y;
|
||||
|
||||
// sets the background appropriately
|
||||
setBackground(colour ? new Color(0,0,0) : new Color(255,255,255));
|
||||
|
||||
// sets the square to empty
|
||||
currentPiece = null;
|
||||
}
|
||||
|
||||
/**
|
||||
** Removes the currently-occupying piece of this ChessSquare.
|
||||
**/
|
||||
public void removePiece() {
|
||||
currentPiece = null;
|
||||
setIcon(null);
|
||||
}
|
||||
|
||||
public boolean hasPiece() {
|
||||
if (currentPiece != null) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
** Gets the current x-coord of this ChessSquare.
|
||||
** @return the x-coord of this ChessSquare within the ChessBoard
|
||||
**/
|
||||
public int getXPosition() {
|
||||
return xPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
** Gets the current y-coord of this ChessSquare.
|
||||
** @return the y-coord of this ChessSquare within the ChessBoard
|
||||
**/
|
||||
public int getYPosition() {
|
||||
return yPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
** Gets the current piece on this ChessSquare.
|
||||
** @return the Piece object on this ChessSquare within the ChessBoard
|
||||
**/
|
||||
public Piece getPiece()
|
||||
{
|
||||
return currentPiece;
|
||||
}
|
||||
|
||||
/**
|
||||
** Gets the current index of this ChessSquare.
|
||||
** @return the index of this ChessSquare within the ChessBoard
|
||||
**/
|
||||
public int getPieceIndex()
|
||||
{
|
||||
return currentPiece.getIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the type of the currently-occupying piece of this ChessSquare.
|
||||
* @return the current piece type on this ChessSquare within the ChessBoard
|
||||
*/
|
||||
public int getPieceType()
|
||||
{
|
||||
return currentPiece.getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the team of the currently-occupying piece of this ChessSquare.
|
||||
* @return the current piece team on this ChessSquare within the ChessBoard
|
||||
*/
|
||||
public int getPieceTeam() {
|
||||
return currentPiece.getTeam();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the state of this ChessSquare.
|
||||
* @return the state of this ChessSquare within the ChessBoard
|
||||
*/
|
||||
public int getState()
|
||||
{
|
||||
return currentState;
|
||||
}
|
||||
|
||||
/**
|
||||
** Sets the currently-occupying piece on this ChessSquare.
|
||||
** @param piece the Piece object
|
||||
**/
|
||||
public void setPiece(Piece piece) {
|
||||
currentPiece = piece;
|
||||
setIcon(pieces[piece.getTeam()][piece.getType()]);
|
||||
}
|
||||
|
||||
/**
|
||||
** Sets the current state of this ChessSquare.
|
||||
** @param state the new state
|
||||
**/
|
||||
public void setState(int state) {
|
||||
currentState = state;
|
||||
}
|
||||
}
|
322
src/Piece.java
Executable file
|
@ -0,0 +1,322 @@
|
|||
/******************************************************************************
|
||||
* ChessSim 0.9 *
|
||||
* Copyright © 2015 Ben Goldsworthy (rumperuu) *
|
||||
* *
|
||||
* A program to simulate a game of chess between two human players. *
|
||||
* *
|
||||
* This file is part of ChessSim. *
|
||||
* *
|
||||
* ChessSim is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* ChessSim is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with ChessSim. If not, see <http://www.gnu.org/licenses/>. *
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
** This class represents a chess piece, utilised in the ChessSim program.
|
||||
**/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
** @author Ben Goldsworthy (rumperuu) <me+chesssim@bengoldsworthy.net>
|
||||
** @version 0.92
|
||||
**/
|
||||
public class Piece {
|
||||
// they C me rollin', they hatin'
|
||||
private final int NULL = 9999;
|
||||
private final int WHITE = 0, BLACK = 1;
|
||||
private final int PAWN = 0, ROOK = 1, KNIGHT = 2, BISHOP = 3, QUEEN = 4,
|
||||
KING = 5;
|
||||
|
||||
// declares all the variables that every piece, regardless of type, has
|
||||
private int xPosition, yPosition;
|
||||
private int pieceNum;
|
||||
private int pieceTeam;
|
||||
private int pieceType;
|
||||
private List<Integer> moves = new ArrayList<Integer>();
|
||||
private boolean firstMove = false;
|
||||
|
||||
|
||||
/**
|
||||
** Constructor function.
|
||||
** @param x the x-coord of the piece
|
||||
** @param y the y-coord of the piece
|
||||
** @param team the team of the piece
|
||||
** @param type the type of the piece
|
||||
**/
|
||||
public Piece(int x, int y, int team, int type, int num) {
|
||||
xPosition = x;
|
||||
yPosition = y;
|
||||
pieceTeam = team;
|
||||
pieceType = type;
|
||||
pieceNum = num;
|
||||
|
||||
if (type == PAWN)
|
||||
firstMove = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this is the first move for the piece, if it is a Pawn.
|
||||
* @return a boolean value
|
||||
*/
|
||||
public boolean firstMove() {
|
||||
return firstMove;
|
||||
}
|
||||
|
||||
/**
|
||||
** Sets the first move as used up.
|
||||
**/
|
||||
public void usedUpFirstMove() {
|
||||
firstMove = false;
|
||||
}
|
||||
|
||||
/**
|
||||
** Populates the movelist of the piece.
|
||||
** @return The list of moves, with NULL characters seperating linear paths
|
||||
**/
|
||||
public List showMoves() {
|
||||
// clears the movelist
|
||||
getMoves().clear();
|
||||
|
||||
switch(pieceType) {
|
||||
case PAWN:
|
||||
// adds the the square(s) directly ahead of the piece
|
||||
addPawn(firstMove);
|
||||
break;
|
||||
case ROOK:
|
||||
// adds linear paths in all four orthagonal directions
|
||||
addOrthagonals(1, 8);
|
||||
break;
|
||||
case KNIGHT:
|
||||
// adds the non-linear L-shaped jump squares
|
||||
addLs();
|
||||
break;
|
||||
case BISHOP:
|
||||
// adds linear paths in all four diagonal directions
|
||||
addDiagonals(1, 8);
|
||||
break;
|
||||
case QUEEN:
|
||||
// adds linear paths in all four diagonal and orthagonal directions
|
||||
addDiagonals(1, 8);
|
||||
addSeparator();
|
||||
addOrthagonals(1, 8);
|
||||
break;
|
||||
case KING:
|
||||
// adds all adjacent squares
|
||||
addDiagonals(1, 1);
|
||||
addSeparator();
|
||||
addOrthagonals(1, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
// returns the movelist
|
||||
return getMoves();
|
||||
}
|
||||
|
||||
/**
|
||||
** Gets the current x-coord of this Piece.
|
||||
** @return the x-coord of this Piece within the ChessBoard.
|
||||
**/
|
||||
public int getXPosition() {
|
||||
return xPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
** Gets the current y-coord of this Piece.
|
||||
** @return the y-coord of this Piece within the ChessBoard.
|
||||
**/
|
||||
public int getYPosition() {
|
||||
return yPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
** Gets the array index of this Piece.
|
||||
** @return the array index of this Piece within the ChessBoard.
|
||||
**/
|
||||
public int getIndex() {
|
||||
return pieceNum;
|
||||
}
|
||||
|
||||
/**
|
||||
** Obtains the type of this Piece.
|
||||
** @return the current type of this Piece within the ChessBoard.
|
||||
**/
|
||||
public int getType() {
|
||||
return pieceType;
|
||||
}
|
||||
|
||||
/**
|
||||
** Obtains the team of this Piece.
|
||||
** @return the team of this Piece within the ChessBoard.
|
||||
**/
|
||||
public int getTeam() {
|
||||
return pieceTeam;
|
||||
}
|
||||
|
||||
/**
|
||||
** Sets the x-coord of this Piece.
|
||||
** @param x the x-coord of this Piece within the ChessBoard.
|
||||
**/
|
||||
public void setXPosition(int x) {
|
||||
xPosition = x;
|
||||
}
|
||||
|
||||
/**
|
||||
** Sets the y-coord of this Piece.
|
||||
** @param y the y-coord of this Piece within the ChessBoard.
|
||||
**/
|
||||
public void setYPosition(int y) {
|
||||
yPosition = y;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a move to this Piece.
|
||||
*/
|
||||
private void addMovement(int x, int y) {
|
||||
moves.add(x);
|
||||
moves.add(y);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a separator to the movelist.
|
||||
*/
|
||||
private void addSeparator() {
|
||||
moves.add(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
** Gets the list of on-board moves for the piece
|
||||
** @return the list of moves.
|
||||
**/
|
||||
public List getMoves() {
|
||||
return moves;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determines whether a given move is on the board or not, i.e. that neither
|
||||
* the x- or y-coords are less than 0 or more than 7. The direction passed
|
||||
* as a param starts at diagonally up and to the left, and proceeds
|
||||
* clockwise
|
||||
*/
|
||||
private boolean moveOnBoard(int x, int dir) {
|
||||
switch(dir) {
|
||||
case 0:
|
||||
return ((xPosition - x >= 0) && (yPosition - x >= 0));
|
||||
case 1:
|
||||
return (yPosition - x >= 0);
|
||||
case 2:
|
||||
return ((xPosition + x <= 7) && (yPosition - x >= 0));
|
||||
case 3:
|
||||
return (xPosition + x <= 7);
|
||||
case 4:
|
||||
return ((xPosition + x <= 7) && (yPosition + x <= 7));
|
||||
case 5:
|
||||
return (yPosition + x <= 7);
|
||||
case 6:
|
||||
return ((xPosition - x >= 0) && (yPosition + x <= 7));
|
||||
case 7:
|
||||
return (xPosition - x >= 0);
|
||||
default:
|
||||
System.out.println("Error 02: no direction sent.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a number of diagonal vectors to the movelist, separated by the
|
||||
* NULL separator.
|
||||
*/
|
||||
private void addDiagonals(int x1, int x2) {
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
if (moveOnBoard(x, 0))
|
||||
addMovement(xPosition - x, yPosition - x);
|
||||
}
|
||||
addSeparator();
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
if (moveOnBoard(x, 2))
|
||||
addMovement(xPosition + x, yPosition - x);
|
||||
}
|
||||
addSeparator();
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
if (moveOnBoard(x, 4))
|
||||
addMovement(xPosition + x, yPosition + x);
|
||||
}
|
||||
addSeparator();
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
if (moveOnBoard(x, 6))
|
||||
addMovement(xPosition - x, yPosition + x);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a number of orthagonal vectors to the movelist, separated by the
|
||||
* NULL separator.
|
||||
*/
|
||||
private void addOrthagonals(int x1, int x2) {
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
if (moveOnBoard(x, 1))
|
||||
addMovement(xPosition, yPosition - x);
|
||||
}
|
||||
addSeparator();
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
if (moveOnBoard(x, 3))
|
||||
addMovement(xPosition + x, yPosition);
|
||||
}
|
||||
addSeparator();
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
if (moveOnBoard(x, 5))
|
||||
addMovement(xPosition, yPosition + x);
|
||||
}
|
||||
addSeparator();
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
if (moveOnBoard(x, 7))
|
||||
addMovement(xPosition - x, yPosition);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a number of non-linear L-shaped paths to the movelist, separated
|
||||
* by the NULL separator.
|
||||
*/
|
||||
private void addLs() {
|
||||
for (int x = 1, x2 = 2; x <= 2; x++, x2--) {
|
||||
if ((xPosition + x <= 7) && (yPosition + x2 <= 7))
|
||||
addMovement(xPosition + x, yPosition + x2);
|
||||
addSeparator();
|
||||
if ((xPosition - x >= 0) && (yPosition + x2 <= 7))
|
||||
addMovement(xPosition - x, yPosition + x2);
|
||||
addSeparator();
|
||||
if ((xPosition + x <= 7) && (yPosition - x2 >= 0))
|
||||
addMovement(xPosition + x, yPosition - x2);
|
||||
addSeparator();
|
||||
if ((xPosition - x >= 0) && (yPosition - x2 >= 0))
|
||||
addMovement(xPosition - x, yPosition - x2);
|
||||
if (x2 == 2) addSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds the square(s) directly ahead of the pawn's current coords.
|
||||
*/
|
||||
private void addPawn(boolean firstMove) {
|
||||
// adds the the square(s) directly ahead of the piece
|
||||
if (pieceTeam == WHITE) {
|
||||
if (moveOnBoard(1, 1))
|
||||
addMovement(getXPosition(), getYPosition() - 1);
|
||||
if (firstMove) addMovement(getXPosition(), getYPosition() - 2);
|
||||
} else if (pieceTeam == BLACK) {
|
||||
if (moveOnBoard(1, 5))
|
||||
addMovement(getXPosition(), getYPosition() + 1);
|
||||
if (firstMove) addMovement(getXPosition(), getYPosition() + 2);
|
||||
}
|
||||
}
|
||||
}
|