Initial commit

This commit is contained in:
Ben Goldsworthy 2020-06-23 22:33:38 +01:00
parent 69f374fc51
commit e7b8466e96
21 changed files with 1693 additions and 696 deletions

23
.gitignore vendored Normal file → Executable file
View 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

1348
LICENSE Normal file → Executable file

File diff suppressed because it is too large Load Diff

4
media/LICENSE Executable file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

BIN
media/black1.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 984 B

BIN
media/black2.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

BIN
media/black3.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
media/black4.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
media/black5.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
media/black6.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
media/white1.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 970 B

BIN
media/white2.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

BIN
media/white3.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
media/white4.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
media/white5.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
media/white6.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

420
src/ChessBoard.java Executable file
View 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
View 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
View 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
View 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
View 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);
}
}
}