Staredit Network > Forums > Technology & Computers > Topic: Chess Implementation
Chess Implementation
Aug 7 2010, 7:07 pm
By: Aristocrat  

Aug 7 2010, 7:07 pm Aristocrat Post #1



Apos was saying something about needing over 2000 lines of code to make a working chess program, so I dug up this old project after he reminded me of it. Essentially a complete functional chess board at less than 700 lines (a large number of which are comments/blank/a single brace).

Don't worry, I don't understand this code either. Been a god damn long time since I made this, and I just started learning Java then. Lulz.

(The .rar holds the .gif files that you will need to compile this.)

Code
/************************************************************************
**
**  Java Chess Implementation - INCOMPLETE
**
**  Chess.java
**  June 12, 2004
**
**  A crude Java implementation of Chess.
**
**  SUPPORTS: Correct standard moves made by all pieces, turn-by-turn moving, highlighting
**            possible move locations, auto pawn promotion to queen, piece capture.
**
**  DOES NOT SUPPORT: game termination upon loss of king,
**                    check warning, checkmate detection, stalemate detection.
**
*/

import javax.swing.*;
import java.awt.*;
import java.applet.*;
import java.awt.image.*;
import java.awt.event.*;
import java.net.*;

public class Chess extends JApplet implements ActionListener
{
    private static JButton[][] board = new JButton[8][8];                 //Array of JButtons, used to display the chess pieces
    private static Grid[][] men = new Grid[8][8];                         //Array of "Grid" objects corresponding to the buttons
    private static int a, b, c, d, type, x, y;                             //Variable placeholders, no particular significance
    private static Grid piece, prevpiece, bking, wking;                                 //Holds the most recently selected piece and the previously selected piece
    private static int move = 0;
    private static String capture = "";

    //Constants used for the highlight(int, int, Grid) method, tells the method in which direction it should highlight things
    public static final int WEST = -1;
    public static final int SOUTH = -1;
    public static final int EAST = 1;
    public static final int NORTH = 1;
    public static final int NONE = 0;

    private static boolean currentPlayer = Grid.WHITE;                 //The current player and a boolean placeholder


    public void init()
    {
        setSize(256, 256);                                         //Sets the size of the applet
        setLayout(new GridLayout(8,8));                             //Sets the layout so the chess pieces display in an 8x8 grid


        //Loops through all 64 pieces
        for(a = 0; a < 8; a++)
        {
            for(b = 0; b < 8; b++)
            {
                men[a][b] = new Grid(Grid.WHITE, Grid.EMPTY);                                                 //Sets each one to an empty tile
                board[a][b] = new JButton(new ImageIcon(Toolkit.getDefaultToolkit().getImage("tile.gif"))); //Initializes the image icon
                board[a][b].addActionListener(this);                                                         //Adds an actionlistener to the JButton
                add(board[a][b]);                                                                             //Adds the JButton to the applet
            }
        }


        //Initializes the board with the correct pieces
        for(a = 0; a < 8; a++)
        {
            men[1][a] = new Grid(Grid.BLACK, Grid.PAWN);
            men[6][a] = new Grid(Grid.WHITE, Grid.PAWN);
        }

        men[0][0] = new Grid(Grid.BLACK, Grid.ROOK);
        men[0][7] = new Grid(Grid.BLACK, Grid.ROOK);

        men[7][0] = new Grid(Grid.WHITE, Grid.ROOK);
        men[7][7] = new Grid(Grid.WHITE, Grid.ROOK);

        men[0][1] = new Grid(Grid.BLACK, Grid.KNIGHT);
        men[0][6] = new Grid(Grid.BLACK, Grid.KNIGHT);

        men[7][1] = new Grid(Grid.WHITE, Grid.KNIGHT);
        men[7][6] = new Grid(Grid.WHITE, Grid.KNIGHT);

        men[0][2] = new Grid(Grid.BLACK, Grid.BISHOP);
        men[0][5] = new Grid(Grid.BLACK, Grid.BISHOP);

        men[7][2] = new Grid(Grid.WHITE, Grid.BISHOP);
        men[7][5] = new Grid(Grid.WHITE, Grid.BISHOP);

        men[0][3] = new Grid(Grid.BLACK, Grid.QUEEN);
        bking = men[0][4] = new Grid(Grid.BLACK, Grid.KING);

        men[7][3] = new Grid(Grid.WHITE, Grid.QUEEN);
        wking = men[7][4] = new Grid(Grid.WHITE, Grid.KING);




        //Set the row and column tags of each Grid object in the array
        for(a = 0; a < 8; a++)
        {
            for(b = 0; b < 8; b++)
            {
                men[a][b].setRow(a);
                men[a][b].setColumn(b);
            }
        }

        //Refreshes display
        setTiles();

        System.out.println("Chess initialized.");
    }

    public void actionPerformed(ActionEvent e)
    {
        type = 0; x = 0; y = 0;                         //Init to make compiler happy
        prevpiece = piece;                             //Marks previous piece
        piece = men[0][0];                             //Init to make compiler happy
        JButton source = (JButton)e.getSource();     //Gets the source of the click

        //Loop through all 64 pieces...
        for(a = 0; a < 8; a++)
        {
            for(b = 0; b < 8; b++)
            {
                if (source == board[a][b])             //If the current JButton is equal to the source of the click
                {
                    x = a;                             //Record row
                    y = b;                             //Record column
                    piece = men[a][b];                 //Record the piece associated with the JButton
                }
            }
        }


        /*
            If the tile clicked on is not highlighted or the piece previously selected.
            does not belong to the current player, clears the highlighting and selects
            the piece that was just clicked on.

            Otherwise, move the previously selected piece to the tile that was clicked on.

            Code for castling added.
        */

        if(piece.getCastlable() && prevpiece.getType() == Grid.KING && prevpiece.getPlayer() == currentPlayer)
        {
            if (currentPlayer == Grid.WHITE)
            {
                move++;
                System.out.print("\n" + move + ".\t");
            }

            piece.setType(Grid.KING);
            piece.setPlayer(prevpiece.getPlayer());
            men[piece.getRow()][(piece.getColumn() + prevpiece.getColumn()) / 2].setType(Grid.ROOK);
            men[piece.getRow()][(piece.getColumn() + prevpiece.getColumn()) / 2].setPlayer(piece.getPlayer());

            prevpiece.setType(Grid.EMPTY);

            if(piece.getColumn() == 2)
            {
                men[piece.getRow()][0].setType(Grid.EMPTY);
                System.out.print("O-O-O");
            }
            if(piece.getColumn() == 6)
            {
                men[piece.getRow()][7].setType(Grid.EMPTY);
                System.out.print("O-O ");
            }

            piece.setHasMoved(true);
            prevpiece.setHasMoved(true);

            currentPlayer = !currentPlayer;         //Changes player

            //Clear highlights, castlables and en passant flags
            for(a = 0; a < 8; a++)
            {
                for(b = 0; b < 8; b++)
                {
                    men[a][b].setHighlight(false);
                    men[a][b].setenpassant(false);
                    men[a][b].setCastlable(false);
                }
            }

            setTiles();
        }
        else
        {
            if(piece.getHighlight() == false || prevpiece.getPlayer() != currentPlayer)
            {
                for(a = 0; a < 8; a++)
                {
                    for(b = 0; b < 8; b++)
                    {
                        men[a][b].setHighlight(false);     //Clear highlights & castlables
                        men[a][b].setCastlable(false);
                    }
                }

                switch (piece.getType())                 //Switch statement, depending on the piece you just clicked on
                {
                    case Grid.PAWN:

                    if (piece.getPlayer() == Grid.BLACK)
                    {
                        highlightEmpty(x + 1, y);
                        highlightEnemy(x + 1, y - 1, piece);
                        highlightEnemy(x + 1, y + 1, piece);

                        if (!piece.getHasMoved() && men[x+1][y].isEmpty())     //Allows you to move two spaces on the first turn
                            highlightEmpty(x + 2, y);

                        if (isValid(x + 1, y - 1) && men[x + 1][y - 1].getenpassant())
                            highlightEmpty(x + 1, y - 1);
                        if (isValid(x + 1, y + 1) && men[x + 1][y + 1].getenpassant())
                            highlightEmpty(x + 1, y + 1);
                    }
                    else
                    {
                        highlightEmpty(x - 1, y);
                        highlightEnemy(x - 1, y - 1, piece);
                        highlightEnemy(x - 1, y + 1, piece);

                        if (!piece.getHasMoved() && men[x-1][y].isEmpty())     //Allows you to move two spaces on the first turn
                            highlightEmpty(x - 2, y);

                        if (isValid(x - 1, y - 1) && men[x - 1][y - 1].getenpassant())
                            highlightEmpty(x - 1, y - 1);
                        if (isValid(x - 1, y + 1) && men[x - 1][y + 1].getenpassant())
                            highlightEmpty(x - 1, y + 1);
                    }


                    break;

                    case Grid.ROOK:

                    //Highlights all possible move locations

                    highlight(WEST, NONE, piece);
                    highlight(EAST, NONE, piece);
                    highlight(NONE, NORTH, piece);
                    highlight(NONE, SOUTH, piece);

                    break;

                    case Grid.KNIGHT:

                    //Highlights all possible move locations

                    highlightTile(x - 1, y + 2, piece);
                    highlightTile(x - 1, y - 2, piece);
                    highlightTile(x - 2, y + 1, piece);
                    highlightTile(x - 2, y - 1, piece);
                    highlightTile(x + 1, y + 2, piece);
                    highlightTile(x + 1, y - 2, piece);
                    highlightTile(x + 2, y + 1, piece);
                    highlightTile(x + 2, y - 1, piece);

                    break;

                    case Grid.BISHOP:

                    //Highlights all possible move locations

                    highlight(WEST, NORTH, piece);
                    highlight(EAST, NORTH, piece);
                    highlight(WEST, SOUTH, piece);
                    highlight(EAST, SOUTH, piece);

                    break;

                    case Grid.QUEEN:

                    //Highlights all possible move locations

                    highlight(WEST, NONE, piece);
                    highlight(EAST, NONE, piece);
                    highlight(NONE, NORTH, piece);
                    highlight(NONE, SOUTH, piece);
                    highlight(WEST, NORTH, piece);
                    highlight(EAST, NORTH, piece);
                    highlight(WEST, SOUTH, piece);
                    highlight(EAST, SOUTH, piece);

                    break;

                    case Grid.KING:

                    //Highlights all possible move locations

                    highlightTile(x + 1, y + 1, piece);
                    highlightTile(x + 1, y, piece);
                    highlightTile(x + 1, y - 1, piece);
                    highlightTile(x, y + 1, piece);
                    highlightTile(x, y - 1, piece);
                    highlightTile(x - 1, y + 1, piece);
                    highlightTile(x - 1, y, piece);
                    highlightTile(x - 1, y - 1, piece);

                    if(!piece.getHasMoved())
                    {
                        a = piece.getRow();
                        if(!men[a][0].getHasMoved() && men[a][1].isEmpty() && men[a][2].isEmpty() && men[a][3].isEmpty())
                            men[a][2].setCastlable(true);
                        if(!men[a][7].getHasMoved() && men[a][6].isEmpty() && men[a][5].isEmpty())
                            men[a][6].setCastlable(true);
                    }

                    break;

                    case Grid.EMPTY:
                    break;

                    default:
                    break;
                }

                setTiles();         //Refresh display
            }
            else     //Moves the piece
            {
                capture = "";
                if (!piece.isEmpty())
                    capture = "x";

                piece.setPlayer(prevpiece.getPlayer());
                piece.setType(prevpiece.getType());

                if(piece.getType() == Grid.PAWN && piece.getenpassant())
                {
                    if (piece.getPlayer() == Grid.WHITE)
                        men[x+1][y].setType(Grid.EMPTY);

                    if (piece.getPlayer() == Grid.BLACK)
                        men[x-1][y].setType(Grid.EMPTY);
                }

                if (currentPlayer == Grid.WHITE)
                {
                    move++;
                    System.out.print("\n" + move + ".\t");
                }

                System.out.print("" + prevpiece + piece + capture);


                prevpiece.setType(Grid.EMPTY);

                piece.setHasMoved(true);
                prevpiece.setHasMoved(true);

                //Clear highlights, castlables and en passant flags
                for(a = 0; a < 8; a++)
                {
                    for(b = 0; b < 8; b++)
                    {
                        men[a][b].setHighlight(false);
                        men[a][b].setenpassant(false);
                        men[a][b].setCastlable(false);
                    }
                }

                if(piece.getType() == Grid.PAWN && Math.abs(piece.getRow() - prevpiece.getRow()) == 2)
                {
                    if (piece.getPlayer() == Grid.WHITE)
                        men[x+1][y].setenpassant(true);

                    if (piece.getPlayer() == Grid.BLACK)
                        men[x-1][y].setenpassant(true);
                }

                if(piece.getType() == Grid.KING)
                {
                    if (piece.getPlayer() == Grid.WHITE)
                        wking = piece;
                    else
                        bking = piece;
                }

                currentPlayer = !currentPlayer;         //Changes player

                //Pawn promotion
                if (piece.getType() == Grid.PAWN && piece.getRow() % 7 == 0)
                {
                    piece.setType(Grid.QUEEN);
                    System.out.print("=Q");
                }

                System.out.print("\n \t");

                setTiles();         //Refresh display
            }
        }
    }

    //Highlights all pieces in a particular direction as specified by the parameters horizontal and vertical
    private static void highlight(int horizontal, int vertical, Grid unit)
    {
        a = unit.getRow() + vertical;
        b = unit.getColumn() + horizontal;

        //While tile is valid and empty, highlights
        while(isValid(a, b) && men[a][b].isEmpty())
        {
            highlightEmpty(a, b);

            a += vertical;
            b += horizontal;
        }

        highlightEnemy(a, b, unit);         //Highlights last tile in path if it belongs to the enemy
    }

    //Highlights a tile if it is not empty and belongs to the enemy
    private static void highlightEnemy(int row, int column, Grid unit)
    {
        if(isValid(row, column))
            if (!men[row][column].isEmpty() && men[row][column].getPlayer() != unit.getPlayer())
                men[row][column].setHighlight(true);
    }

    //Highlights a tile if it is empty
    private static void highlightEmpty(int row, int column)
    {
        if(isValid(row, column))
            if (men[row][column].isEmpty())
                men[row][column].setHighlight(true);
    }

    //Highlights a tile if it is either empty or if it belongs to the enemy
    private static void highlightTile(int row, int column, Grid unit)
    {
        highlightEmpty(row, column);
        highlightEnemy(row, column, unit);
    }

    //Checks if (a,b) is within bounds
    private static boolean isValid(int a, int b)
    {
        if (a >= 0 && a < 8 && b >= 0 && b < 8)
            return true;
        return false;
    }

    //Refreshes the display by updating the ImageIcons
    public static void setTiles()
    {
        for(a = 0; a < 8; a++)
        {
            for(b = 0; b < 8; b++)
            {
                board[a][b].setIcon(new ImageIcon(Toolkit.getDefaultToolkit().getImage(men[a][b].getImageName())));
            }
        }
    }

//Implement check-detection later

/*     private static boolean isInCheck(Grid loc)
    {
        a = loc.getRow();
        b = loc.getColumn();

        return checkKnights(a, b) || checkRBQ(a, b) || checkPawn(a, b) || checkKing(a, b);
    }

    private static boolean checkKnights(int p, int q)
    {
        return ((isValid(p - 1, q - 2) && men[p - 1][q - 2].getPlayer() != men[p][q].getPlayer() && men[p - 1][q - 2].getType() == Grid.KNIGHT) || (isValid(p - 1, q + 2) && men[p - 1][q + 2].getPlayer() != men[p][q].getPlayer() && men[p - 1][q + 2].getType() == Grid.KNIGHT) || (isValid(p - 2, q - 1) && men[p - 2][q - 1].getPlayer() != men[p][q].getPlayer() && men[p - 2][q - 1].getType() == Grid.KNIGHT) || (isValid(p - 2, q + 1) && men[p - 2][q + 1].getPlayer() != men[p][q].getPlayer() && men[p - 2][q + 1].getType() == Grid.KNIGHT) || (isValid(p + 1, q - 2) && men[p + 1][q - 2].getPlayer() != men[p][q].getPlayer() && men[p + 1][q - 2].getType() == Grid.KNIGHT) || (isValid(p + 1, q + 2) && men[p + 1][q + 2].getPlayer() != men[p][q].getPlayer() && men[p + 1][q + 2].getType() == Grid.KNIGHT) || (isValid(p + 2, q - 1) && men[p + 2][q - 1].getPlayer() != men[p][q].getPlayer() && men[p + 2][q - 1].getType() == Grid.KNIGHT) || (isValid(p + 2, q + 1) && men[p + 2][q + 1].getPlayer() != men[p][q].getPlayer() && men[p + 2][q + 1].getType() == Grid.KNIGHT));
    }

    private static boolean checkRBQ(int p, int q)
    {
        return dirRBQ(WEST, NONE, men[p][q]) || dirRBQ(EAST, NONE, men[p][q]) || dirRBQ(NONE, NORTH, men[p][q]) || dirRBQ(NONE, SOUTH, men[p][q]) || dirRBQ(WEST, NORTH, men[p][q]) || dirRBQ(EAST, NORTH, men[p][q]) || dirRBQ(WEST, SOUTH, men[p][q]) || dirRBQ(EAST, SOUTH, men[p][q]);
    }

    private static boolean dirRBQ(int horizontal, int vertical, Grid unit)
    {
        a = unit.getRow() + vertical;
        b = unit.getColumn() + horizontal;

        while(isValid(a, b) && men[a][b].isEmpty())
        {
            a += vertical;
            b += horizontal;
        }

        if (isValid(a, b))
        {
            if(men[a][b].getPlayer() != unit.getPlayer())
            {
                if (men[a][b].getType() == Grid.QUEEN)
                    return true;
                if ((a + b) % 2 == 0)
                {
                    if (men[a][b].getType() == Grid.BISHOP)
                        return true;
                }
                else
                {
                    if (men[a][b].getType() == Grid.ROOK)
                        return true;
                }
            }
        }
        return false;
    }
    */
}

class Grid
{
    public static final boolean BLACK = false;
    public static final boolean WHITE = true;

    public static final int KING = 0;
    public static final int QUEEN = 1;
    public static final int BISHOP = 2;
    public static final int KNIGHT = 3;
    public static final int ROOK = 4;
    public static final int PAWN = 5;
    public static final int EMPTY = 6;

    private boolean player;
    private int piece, row, column;
    private boolean highlighted = false, hasMoved = false;
    private boolean castlable = false, en_passant = false;

    private char temp;

    public Grid(boolean side, int type)
    {
        player = side;
        piece = type;
    }

    public boolean isEmpty()
    {
        return piece == EMPTY;
    }

    public boolean getHasMoved()
    {
        return hasMoved;
    }

    public void setHasMoved(boolean hm)
    {
        hasMoved = hm;
    }

    public int getType()
    {
        return piece;
    }

    public void setType(int type)
    {
        piece = type;
    }

    public boolean getPlayer()
    {
        return player;
    }

    public void setPlayer(boolean side)
    {
        player = side;
    }

    public boolean getHighlight()
    {
        return highlighted;
    }

    public void setHighlight(boolean a)
    {
        highlighted = a;
    }

    public boolean getenpassant()
    {
        return en_passant;
    }

    public void setenpassant(boolean e)
    {
        en_passant = e;
    }

    public boolean getCastlable()
    {
        return castlable;
    }

    public void setCastlable(boolean a)
    {
        castlable = a;
    }

    public void setRow(int a)
    {
        row = a;
    }

    public int getRow()
    {
        return row;
    }

    public void setColumn(int a)
    {
        column = a;
    }

    public int getColumn()
    {
        return column;
    }

    public String getImageName()
    {
        //Gets the name of the picture/icon that corresponds to the piece.
        String nameholder;
        if(player)
            nameholder = "w";
        else
            nameholder = "b";

        switch(piece)
        {
            case KING:         nameholder += "king"; break;
            case QUEEN:         nameholder += "queen"; break;
            case BISHOP:     nameholder += "bishop"; break;
            case KNIGHT:     nameholder += "knight"; break;
            case ROOK:         nameholder += "rook"; break;
            case PAWN:         nameholder += "pawn"; break;
            case EMPTY:         nameholder = "tile"; break;
            default:         break;
        }

        if (highlighted)
            nameholder += "hl";

        if (castlable)
            nameholder += "blue";

        return nameholder += ".gif";
    }

    public String toString()
    {
        //Really bad chess notation converter for debugging
        return "" + (char)(column + 97) + (8 - row);
    }
}


Attachments:
Java chess.rar
Hits: 0 Size: 10.81kb



None.

Aug 13 2010, 12:11 am Apos Post #2

I order you to forgive yourself!

I got more lines now :P

My goal is not to make a chess game, it's to make a UCI chess engine that can play against other UCI or Winboard engines using a UCI chess interface. If possible, I want it to be very easy to understand for others and still be able to beat the crap out of the other engines. :P




Options
  Back to forum
Please log in to reply to this topic or to report it.
Members in this topic: None.
[07:32 pm]
Zoan -- I got $2000 bonus. I would like 2000 minerals, please
[04:15 am]
DarkenedFantasies -- you eat lots of beans
[03:46 am]
IskatuMesk -- how do i get gas
[2026-4-15. : 11:43 pm]
Moose -- you don't
[2026-4-15. : 10:06 pm]
Zoan -- how do i get minerals
[2026-4-14. : 11:45 pm]
ClansAreForGays -- Anyone wanna played Skewed StarCraft?
[2026-4-14. : 12:07 am]
Vrael -- NudeRaider
NudeRaider shouted: Vrael ranting still is though
you're a gentleman and a scholar, thank you
[2026-4-13. : 10:07 pm]
NudeRaider -- ya why phone people when you can just write letters
[2026-4-13. : 9:37 pm]
IskatuMesk -- I have never and will never own a phone
[2026-4-13. : 9:15 pm]
NudeRaider -- Vrael ranting still is though
Please log in to shout.


Members Online: Zoan, Prankenstein