import java.awt.*;
import java.util.LinkedList;
import javax.swing.*;

public class Board extends Minimax implements Cloneable
{
    private Move lastWhiteMove;
    private Move lastBlackMove;

    private long whitePawns;
    private long whiteRooks;
    private long whiteKnights;
    private long whiteBishops;
    private long whiteKings;
    private long whiteQueens;
    private boolean whiteCanShortCastle;
    private boolean whiteCanLongCastle;

    private long blackPawns;
    private long blackRooks;
    private long blackKnights;
    private long blackBishops;
    private long blackKings;
    private long blackQueens;
    private boolean blackCanShortCastle;
    private boolean blackCanLongCastle;

    // A priori bit boards
    private static long[] squaresAttackedByWhitePawns = new long[64];
    private static long[] whitePawnAdvances = new long[64];
    private static long[] squaresAttackedByBlackPawns = new long[64];
    private static long[] blackPawnAdvances = new long[64];
    private static long[] squaresAttackedByKnights = new long[64];
    private static long[] squaresAttackedByKings = new long[64];
    private static long[] upMoves = new long[64];
    private static long[] downMoves = new long[64];
    private static long[] leftMoves = new long[64];
    private static long[] rightMoves = new long[64];
    private static long[] diagonalUpLeftMoves = new long[64];
    private static long[] diagonalDownLeftMoves = new long[64];
    private static long[] diagonalUpRightMoves = new long[64];
    private static long[] diagonalDownRightMoves = new long[64];
 
    public static final long fileA = 1L | (1L << 8) | (1L << 16) | (1L << 24) |(1L << 32) |
                                        (1L << 40) | (1L << 48) | (1L << 56);
    public static final long fileB = (1L << 1) | (1L << 9) | (1L << 17) | (1L << 25) | (1L << 33) |
                                        (1L << 41) | (1L << 49) | (1L << 57);
    public static final long fileC = (1L << 2) | (1L << 10) | (1L << 18) | (1L << 26) | (1L << 34) |
                                        (1L << 42) | (1L << 50) | (1L << 58);
    public static final long fileD = (1L << 3) | (1L << 11) | (1L << 19) | (1L << 27) | (1L << 35) |
                                        (1L << 43) | (1L << 51) | (1L << 59);
    public static final long fileE = (1L << 4) | (1L << 12) | (1L << 20) | (1L << 28) | (1L << 36) |
                                        (1L << 44) | (1L << 52) | (1L << 60);
    public static final long fileF = (1L << 5) | (1L << 13) | (1L << 21) | (1L << 29) | (1L << 37) |
                                        (1L << 45) | (1L << 53) | (1L << 61);
    public static final long fileG = (1L << 6) | (1L << 14) | (1L << 22) | (1L << 30) | (1L << 38) |
                                        (1L << 46) | (1L << 54) | (1L << 62);
    public static final long fileH = (1L << 7) | (1L << 15) | (1L << 23) | (1L << 31) | (1L << 39) |
                                        (1L << 47) | (1L << 55) | (1L << 63);
    public static final long row1  = 1L | (1L << 1) | (1L << 2) | (1L << 3) | (1L << 4) |
                                        (1L << 5) | (1L << 6) | (1L << 7);
    public static final long row2  = (1L << 8) | (1L << 9) | (1L << 10) | (1L << 11) |
                                        (1L << 12) | (1L << 13) | (1L << 14) | (1L << 15);
    public static final long row3 = (1L << 16) | (1L << 17) | (1L << 18) | (1L << 19) |
                                        (1L << 20) | (1L << 21) | (1L << 22) | (1L << 23);
    public static final long row4 = (1L << 24) | (1L << 25) | (1L << 26) | (1L << 27) |
                                        (1L << 28) | (1L << 29) | (1L << 30) | (1L << 31);
    public static final long row5 = (1L << 32) | (1L << 33) | (1L << 34) | (1L << 35) |
                                        (1L << 36) | (1L << 37) | (1L << 38) | (1L << 39);
    public static final long row6 = (1L << 40) | (1L << 41) | (1L << 42) | (1L << 43) |
                                        (1L << 44) | (1L << 45) | (1L << 46) | (1L << 47);
    public static final long row7  = (1L << 48) | (1L << 49) | (1L << 50) | (1L << 51) |
                                        (1L << 52) | (1L << 53) | (1L << 54) | (1L << 55);
    public static final long row8  = (1L << 56) | (1L << 57) | (1L << 58) | (1L << 59) |
                                        (1L << 60) | (1L << 61) | (1L << 62) | (1L << 63);

    public Board()
    {      
        createAPrioriBitBoards();

        resetPieces();
    }
    
    public Object clone()
    {
        Board b = (Board)super.clone();

        b.whitePawns          = this.getWhitePawns();
        b.whiteRooks          = this.getWhiteRooks();
        b.whiteKnights        = this.getWhiteKnights();
        b.whiteBishops        = this.getWhiteBishops();
        b.whiteKings          = this.getWhiteKings();
        b.whiteQueens         = this.getWhiteQueens();
        b.whiteCanShortCastle = this.canWhiteShortCastle();
        b.whiteCanLongCastle  = this.canWhiteLongCastle();

        b.blackPawns          = this.getBlackPawns();
        b.blackRooks          = this.getBlackRooks();
        b.blackKnights        = this.getBlackKnights();
        b.blackBishops        = this.getBlackBishops();
        b.blackKings          = this.getBlackKings();
        b.blackQueens         = this.getBlackQueens();
        b.blackCanShortCastle = this.canBlackShortCastle();
        b.blackCanLongCastle  = this.canBlackLongCastle();
        return b;
    }

    public long getWhitePawns()
    {
        return this.whitePawns;
    }

    public long getWhiteRooks()
    {
        return this.whiteRooks;
    }

    public long getWhiteKnights()
    {
        return this.whiteKnights;
    }

    public long getWhiteBishops()
    {
        return this.whiteBishops;
    }

    public long getWhiteKings()
    {
        return this.whiteKings;
    }

    public long getWhiteQueens()
    {
        return this.whiteQueens;
    }

    public boolean canWhiteShortCastle()
    {
        return this.whiteCanShortCastle;
    }

    public boolean canWhiteLongCastle()
    {
        return this.whiteCanLongCastle;
    }

    public long getBlackPawns()
    {
        return this.blackPawns;
    }

    public long getBlackRooks()
    {
        return this.blackRooks;
    }

    public long getBlackKnights()
    {
        return this.blackKnights;
    }

    public long getBlackBishops()
    {
        return this.blackBishops;
    }

    public long getBlackKings()
    {
        return this.blackKings;
    }

    public long getBlackQueens()
    {
        return this.blackQueens;
    }

    public boolean canBlackShortCastle()
    {
        return this.blackCanShortCastle;
    }

    public boolean canBlackLongCastle()
    {
        return this.blackCanLongCastle;
    }

    public boolean isWhitesTurn()
    {
        return this.getPlayer() == Minimax.MAX_TURN;
    }

    public long squaresContainingBlackPieces()
    {
        return blackPawns | blackRooks | blackKnights | blackBishops | blackKings | blackQueens;
    }
    
    public long squaresContainingWhitePieces()
    {
        return whitePawns | whiteRooks | whiteKnights | whiteBishops | whiteKings | whiteQueens;
    }
    
    public long legalWhiteMoves(int square)
    {
        long squaresContainingBlackPieces = squaresContainingBlackPieces();
        long squaresContainingWhitePieces = squaresContainingWhitePieces();
        long emptySquares                 = ~squaresContainingBlackPieces & ~squaresContainingWhitePieces;
        long a = 1L << square, r = 0;
        
        // If this square contains a white pawn then store the legal white pawn moves from this square
        if((whitePawns & a) != 0)
        {
            r = whitePawnAdvances[square] & emptySquares;
            r |= squaresAttackedByWhitePawns[square] & squaresContainingBlackPieces;

            // Allow pawns to move forward two squares if they are still on the second row
            if(square >= 48 && square < 56 && (emptySquares & (1L << (square - 8))) != 0)
            {
                // Check the target square is empty
                if((emptySquares & (1L << (square - 16))) != 0)
                {
                    r |= 1L << (square - 16);
                }
            }

            return r;
        }
        
        // If this square contains a white knight then store the legal white knight moves from this square
        if((whiteKnights & a) != 0)
        {
            return squaresAttackedByKnights[square] & ~squaresContainingWhitePieces;
        }
        
        // If this square contains a white king then store the legal white king moves from this square
        if((whiteKings & a) != 0)
        {
            return squaresAttackedByKings[square] & ~squaresContainingWhitePieces;
        }

        // If this square contains a white rook or a white queen then store all the legal white rook
        // moves from this square (since white queens can make every move a white rook can make)
        if((whiteRooks & a) != 0 || (whiteQueens & a) != 0)
        {
            // Create a set of squares to the right which the piece cannot move to
            long legalRightMoves = rightMoves[square] & ~emptySquares;
            legalRightMoves = (legalRightMoves << 1) | (legalRightMoves << 2) | (legalRightMoves << 3) |
                                (legalRightMoves << 4) | (legalRightMoves << 5) | (legalRightMoves << 6);
            legalRightMoves &= rightMoves[square];
            
            // Use the list of squares to the right which the piece cannot move to to create a list
            // of squares to the right which it can move to
            legalRightMoves ^= rightMoves[square];
            
            // If the right-most square in the set contains a white piece then remove it from the set
            legalRightMoves &= ~squaresContainingWhitePieces;
            
            // Store the set of squares to the right which the piece can move to
            r |= legalRightMoves;
            
            // Create a set of squares to the left which the piece cannot move to
            long legalLeftMoves = leftMoves[square] & ~emptySquares;
            legalLeftMoves = (legalLeftMoves >> 1) | (legalLeftMoves >> 2) | (legalLeftMoves >> 3) |
                                (legalLeftMoves >> 4) | (legalLeftMoves >> 5) | (legalLeftMoves >> 6);
            legalLeftMoves &= leftMoves[square];

            // Use the list of squares to the left which the piece cannot move to to create a list
            // of squares to the left which it can move to
            legalLeftMoves ^= leftMoves[square];

            // If the left-most square in the set contains a white piece then remove it from the set
            legalLeftMoves &= ~squaresContainingWhitePieces;

            // Store the set of squares to the left which the piece can move to
            r |= legalLeftMoves;

            // Create a set of squares below this one which the piece cannot move to
            long legalDownMoves = downMoves[square] & ~emptySquares;
            legalDownMoves = (legalDownMoves >> 8) | (legalDownMoves >> 16) | (legalDownMoves >> 24) |
                                (legalDownMoves >> 32) | (legalDownMoves >> 40) | (legalDownMoves >> 48);
            legalDownMoves &= downMoves[square];

            // Use the list of squares below this one which the piece cannot move to to create a list
            // of squares below it which it can move to
            legalDownMoves ^= downMoves[square];

            // If the bottom-most square in the set contains a white piece then remove it from the set
            legalDownMoves &= ~squaresContainingWhitePieces;

            // Store the set of squares below this one which the piece can move to
            r |= legalDownMoves;
            
            // Create a set of squares above this one which the piece cannot move to
            long legalUpMoves = upMoves[square] & ~emptySquares;
            legalUpMoves = (legalUpMoves << 8) | (legalUpMoves << 16) | (legalUpMoves << 24) |
                            (legalUpMoves << 32) | (legalUpMoves << 40) | (legalUpMoves << 48);
            legalUpMoves &= upMoves[square];

            // Use the list of squares above this one which the piece cannot move to to create a list
            // of squares above it which it can move to
            legalUpMoves ^= upMoves[square];

            // If the top-most square in the set contains a white piece then remove it from the set
            legalUpMoves &= ~squaresContainingWhitePieces;

            // Store the set of squares above this one which the piece can move to
            r |= legalUpMoves;
        }

        if((whiteBishops & a) != 0 || (whiteQueens & a) != 0)
        {
            // Create a set of squares up-left of this one which the piece cannot move to
            long legalUpLeftMoves = diagonalUpLeftMoves[square] & ~emptySquares;
            legalUpLeftMoves = (legalUpLeftMoves >> 7) | (legalUpLeftMoves >> 14) | (legalUpLeftMoves >> 21) |
                                (legalUpLeftMoves >> 28) | (legalUpLeftMoves >> 35) | (legalUpLeftMoves >> 42);
            legalUpLeftMoves &= diagonalUpLeftMoves[square];
            
            // Use the list of squares up-left of this one which the piece cannot move to to create a list
            // of squares up-left of it which it can move to
            legalUpLeftMoves ^= diagonalUpLeftMoves[square];
            
            // If the top-left-most square in the set contains a white piece then remove it from the set
            legalUpLeftMoves &= ~squaresContainingWhitePieces;
            
            // Store the set of squares up-left of this one which the piece can move to
            r |= legalUpLeftMoves;
            
            // Create a set of squares up-right of this one which the piece cannot move to
            long legalUpRightMoves = diagonalUpRightMoves[square] & ~emptySquares;
            legalUpRightMoves = (legalUpRightMoves >> 9) | (legalUpRightMoves >> 18) | (legalUpRightMoves >> 27) |
                                (legalUpRightMoves >> 36) | (legalUpRightMoves >> 45) | (legalUpRightMoves >> 54);
            legalUpRightMoves &= diagonalUpRightMoves[square];
            
            // Use the list of squares up-right of this one which the piece cannot move to to create a list
            // of squares up-right of it which it can move to
            legalUpRightMoves ^= diagonalUpRightMoves[square];

            // If the top-right most square in the set contains a white piece then remove it from the set
            legalUpRightMoves &= ~squaresContainingWhitePieces;

            // Store the set of squares up-right of this one which the piece can move to
            r |= legalUpRightMoves;
            
            // Create a set of squares down-left of this one which the piece cannot move to
            long legalDownLeftMoves = diagonalDownLeftMoves[square] & ~emptySquares;
            legalDownLeftMoves = (legalDownLeftMoves << 9) | (legalDownLeftMoves << 18) | (legalDownLeftMoves << 27) |
                                    (legalDownLeftMoves << 36) | (legalDownLeftMoves << 45) | (legalDownLeftMoves << 54);
            legalDownLeftMoves &= diagonalDownLeftMoves[square];

            // Use the list of squares down-left of this one which the piece cannot move to to create a list
            // of squares down-left of it which it can move to
            legalDownLeftMoves ^= diagonalDownLeftMoves[square];
            
            // If the bottom-left square in the set contains a white piece then remove it from the set
            legalDownLeftMoves &= ~squaresContainingWhitePieces;
            
            // Store the set of squares down-left of this one which the piece can move to
            r |= legalDownLeftMoves;
            
            // Create a set of squares down-right of this one which the piece cannot move to
            long legalDownRightMoves = diagonalDownRightMoves[square] & ~emptySquares;
            legalDownRightMoves = (legalDownRightMoves << 7) | (legalDownRightMoves << 14) | (legalDownRightMoves << 21) |
                                    (legalDownRightMoves << 28) | (legalDownRightMoves << 35) | (legalDownRightMoves << 42);
            legalDownLeftMoves &= diagonalDownLeftMoves[square];

            // Use the list of squares down-left of this one which the piece cannot move to to create a list
            // of squares down-left of it which it can move to
            legalDownRightMoves ^= diagonalDownRightMoves[square];
            
            // If the bottom-left square in the set contains a white piece then remove it from the set
            legalDownRightMoves &= ~squaresContainingWhitePieces;
            
            // Store the set of squares down-left of this one which the piece can move to
            r |= legalDownRightMoves;
        }

        return r;
    }
    
    public long legalBlackMoves(int square)
    {
        long squaresContainingWhitePieces = squaresContainingWhitePieces();
        long squaresContainingBlackPieces = squaresContainingBlackPieces();
        long emptySquares                 = ~squaresContainingWhitePieces & ~squaresContainingBlackPieces;
        long a = 1L << square, r = 0;
        
        // If this square contains a Black pawn then store the legal Black pawn moves from this square
        if((blackPawns & a) != 0)
        {
            r = blackPawnAdvances[square] & emptySquares;
            r |= squaresAttackedByBlackPawns[square] & squaresContainingWhitePieces;

            // Allow pawns to move forward two squares if they are still on the second row
            if(square >= 8 && square < 16 && (emptySquares & (1L << (square + 8))) != 0)
            {
                if((emptySquares & (1L << (square + 16))) != 0)
                r |= 1L << (square + 16);
            }
            
            return r;
        }
        
        // If this square contains a Black knight then store the legal Black knight moves from this square
        if((blackKnights & a) != 0)
        {
            return squaresAttackedByKnights[square] & ~squaresContainingBlackPieces;
        }
        
        // If this square contains a Black king then store the legal Black king moves from this square
        if((blackKings & a) != 0)
        {
            return squaresAttackedByKings[square] & ~squaresContainingBlackPieces;
        }

        // If this square contains a Black rook or a Black queen then store all the legal Black rook
        // moves from this square (since Black queens can make every move a Black rook can make)
        if((blackRooks & a) != 0 || (blackQueens & a) != 0)
        {
            // Create a set of squares to the right which the piece cannot move to
            long legalRightMoves = rightMoves[square] & ~emptySquares;
            legalRightMoves = (legalRightMoves << 1) | (legalRightMoves << 2) | (legalRightMoves << 3) |
                                (legalRightMoves << 4) | (legalRightMoves << 5) | (legalRightMoves << 6);
            legalRightMoves &= rightMoves[square];
            
            // Use the list of squares to the right which the piece cannot move to to create a list
            // of squares to the right which it can move to
            legalRightMoves ^= rightMoves[square];
            
            // If the right-most square in the set contains a Black piece then remove it from the set
            legalRightMoves &= ~squaresContainingBlackPieces;
            
            // Store the set of squares to the right which the piece can move to
            r |= legalRightMoves;
            
            // Create a set of squares to the left which the piece cannot move to
            long legalLeftMoves = leftMoves[square] & ~emptySquares;
            legalLeftMoves = (legalLeftMoves >> 1) | (legalLeftMoves >> 2) | (legalLeftMoves >> 3) |
                                (legalLeftMoves >> 4) | (legalLeftMoves >> 5) | (legalLeftMoves >> 6);
            legalLeftMoves &= leftMoves[square];

            // Use the list of squares to the left which the piece cannot move to to create a list
            // of squares to the left which it can move to
            legalLeftMoves ^= leftMoves[square];

            // If the left-most square in the set contains a Black piece then remove it from the set
            legalLeftMoves &= ~squaresContainingBlackPieces;

            // Store the set of squares to the left which the piece can move to
            r |= legalLeftMoves;

            // Create a set of squares below this one which the piece cannot move to
            long legalDownMoves = downMoves[square] & ~emptySquares;
            legalDownMoves = (legalDownMoves >> 8) | (legalDownMoves >> 16) | (legalDownMoves >> 24) |
                                (legalDownMoves >> 32) | (legalDownMoves >> 40) | (legalDownMoves >> 48);
            legalDownMoves &= downMoves[square];

            // Use the list of squares below this one which the piece cannot move to to create a list
            // of squares below it which it can move to
            legalDownMoves ^= downMoves[square];

            // If the bottom-most square in the set contains a Black piece then remove it from the set
            legalDownMoves &= ~squaresContainingBlackPieces;

            // Store the set of squares below this one which the piece can move to
            r |= legalDownMoves;
            
            // Create a set of squares above this one which the piece cannot move to
            long legalUpMoves = upMoves[square] & ~emptySquares;
            legalUpMoves = (legalUpMoves << 8) | (legalUpMoves << 16) | (legalUpMoves << 24) |
                            (legalUpMoves << 32) | (legalUpMoves << 40) | (legalUpMoves << 48);
            legalUpMoves &= upMoves[square];

            // Use the list of squares above this one which the piece cannot move to to create a list
            // of squares above it which it can move to
            legalUpMoves ^= upMoves[square];

            // If the top-most square in the set contains a Black piece then remove it from the set
            legalUpMoves &= ~squaresContainingBlackPieces;

            // Store the set of squares above this one which the piece can move to
            r |= legalUpMoves;
        }

        if((blackBishops & a) != 0 || (blackQueens & a) != 0)
        {
            // Create a set of squares up-left of this one which the piece cannot move to
            long legalUpLeftMoves = diagonalUpLeftMoves[square] & ~emptySquares;
            legalUpLeftMoves = (legalUpLeftMoves >> 7) | (legalUpLeftMoves >> 14) | (legalUpLeftMoves >> 21) |
                                (legalUpLeftMoves >> 28) | (legalUpLeftMoves >> 35) | (legalUpLeftMoves >> 42);
            legalUpLeftMoves &= diagonalUpLeftMoves[square];
            
            // Use the list of squares up-left of this one which the piece cannot move to to create a list
            // of squares up-left of it which it can move to
            legalUpLeftMoves ^= diagonalUpLeftMoves[square];
            
            // If the top-left-most square in the set contains a Black piece then remove it from the set
            legalUpLeftMoves &= ~squaresContainingBlackPieces;
            
            // Store the set of squares up-left of this one which the piece can move to
            r |= legalUpLeftMoves;
            
            // Create a set of squares up-right of this one which the piece cannot move to
            long legalUpRightMoves = diagonalUpRightMoves[square] & ~emptySquares;
            legalUpRightMoves = (legalUpRightMoves >> 9) | (legalUpRightMoves >> 18) | (legalUpRightMoves >> 27) |
                                (legalUpRightMoves >> 36) | (legalUpRightMoves >> 45) | (legalUpRightMoves >> 54);
            legalUpRightMoves &= diagonalUpRightMoves[square];
            
            // Use the list of squares up-right of this one which the piece cannot move to to create a list
            // of squares up-right of it which it can move to
            legalUpRightMoves ^= diagonalUpRightMoves[square];
            
            // If the top-right most square in the set contains a Black piece then remove it from the set
            legalUpRightMoves &= ~squaresContainingBlackPieces;

            // Store the set of squares up-right of this one which the piece can move to
            r |= legalUpRightMoves;
            
            // Create a set of squares down-left of this one which the piece cannot move to
            long legalDownLeftMoves = diagonalDownLeftMoves[square] & ~emptySquares;
            legalDownLeftMoves = (legalDownLeftMoves << 9) | (legalDownLeftMoves << 18) | (legalDownLeftMoves << 27) |
                                    (legalDownLeftMoves << 36) | (legalDownLeftMoves << 45) | (legalDownLeftMoves << 54);
            legalDownLeftMoves &= diagonalDownLeftMoves[square];

            // Use the list of squares down-left of this one which the piece cannot move to to create a list
            // of squares down-left of it which it can move to
            legalDownLeftMoves ^= diagonalDownLeftMoves[square];
            
            // If the bottom-left square in the set contains a Black piece then remove it from the set
            legalDownLeftMoves &= ~squaresContainingBlackPieces;
            
            // Store the set of squares down-left of this one which the piece can move to
            r |= legalDownLeftMoves;
            
            // Create a set of squares down-right of this one which the piece cannot move to
            long legalDownRightMoves = diagonalDownRightMoves[square] & ~emptySquares;
            legalDownRightMoves = (legalDownRightMoves << 7) | (legalDownRightMoves << 14) | (legalDownRightMoves << 21) |
                                    (legalDownRightMoves << 28) | (legalDownRightMoves << 35) | (legalDownRightMoves << 42);
            legalDownRightMoves &= diagonalDownRightMoves[square];

            // Use the list of squares down-left of this one which the piece cannot move to to create a list
            // of squares down-left of it which it can move to
            legalDownRightMoves ^= diagonalDownRightMoves[square];
            
            // If the bottom-left square in the set contains a Black piece then remove it from the set
            legalDownRightMoves &= ~squaresContainingBlackPieces;
            
            // Store the set of squares down-left of this one which the piece can move to
            r |= legalDownRightMoves;
        }

        return r;
    }

    private void resetPieces()
    {
        whitePawns = (1L << 48) | (1L << 49) | (1L << 50) | (1L << 51) | (1L << 52) |
                        (1L << 53) | (1L << 54) | (1L << 55);
        whiteRooks = (1L << 56) | (1L << 63);
        whiteKnights = (1L << 57) | (1L << 62);
        whiteBishops = (1L << 58) | (1L << 61);
        whiteKings = 1L << 59;
        whiteQueens = 1L << 60;
        whiteCanShortCastle = true;
        whiteCanLongCastle = true;
        blackPawns = (1L << 8) | (1L << 9) | (1L << 10) | (1L << 11) | (1L << 12) |
                        (1L << 13) | (1L << 14) | (1L << 15);
        blackRooks = (1L << 0) | (1L << 7);
        blackKnights = (1L << 1) | (1L << 6);
        blackBishops = (1L << 2) | (1L << 5);
        blackKings = 1L << 3;
        blackQueens = 1L << 4;
        blackCanShortCastle = true;
        blackCanLongCastle = true;
    }

    private void createAPrioriBitBoards()
    {
        createWhitePawnAttackBitBoards();
        createWhitePawnAdvances();
        createBlackPawnAttackBitBoards();
        createBlackPawnAdvances();
        createKnightAttackBitBoard();
        createKingAttackBitBoard();
        createUpMoves();
        createDownMoves();
        createLeftMoves();
        createRightMoves();
        createDiagonalUpLeftMoves();       
        createDiagonalUpRightMoves();
        createDiagonalDownRightMoves();
        createDiagonalDownLeftMoves();
    }

    private void createDiagonalDownLeftMoves()
    {
        long rowsToExclude = 0L;
        long filesToExclude;
        long row[] = new long[8];
        row[0] = row1;
        row[1] = row2;
        row[2] = row3;
        row[3] = row4;
        row[4] = row5;
        row[5] = row6;
        row[6] = row7;
        row[7] = row8;
        long file[] = new long[8];
        file[0] = fileA;
        file[1] = fileB;
        file[2] = fileC;
        file[3] = fileD;
        file[4] = fileE;
        file[5] = fileF;
        file[6] = fileG;
        file[7] = fileH;
        for(int i = 0; i < 8; i++)
        {
            int i8 = i * 8;
            filesToExclude = 0L;
            for(int j = 0; j < 8; j++)
            {
                int i8j = i8 + j;
                diagonalDownLeftMoves[i8j] = (1L << (i8j + 9)) | (1L << (i8j + 18)) | (1L << (i8j + 27)) | (1L << (i8j + 36)) |
                                                (1L << (i8j + 45)) | (1L << (i8j + 54)) | (1L << (i8j + 63));
                diagonalDownLeftMoves[i8j] &= ~rowsToExclude & ~filesToExclude;
                filesToExclude |= file[j];
            }
            rowsToExclude |= row[i];
        }
    }

    private void createDiagonalDownRightMoves()
    {
        long rowsToExclude = 0L;
        long filesToInclude;
        long row[] = new long[8];
        row[0] = row1;
        row[1] = row2;
        row[2] = row3;
        row[3] = row4;
        row[4] = row5;
        row[5] = row6;
        row[6] = row7;
        row[7] = row8;
        long file[] = new long[8];
        file[0] = fileA;
        file[1] = fileB;
        file[2] = fileC;
        file[3] = fileD;
        file[4] = fileE;
        file[5] = fileF;
        file[6] = fileG;
        file[7] = fileH;
        for(int i = 0; i < 8; i++)
        {
            int i8 = i * 8;
            filesToInclude = 0L;
            for(int j = 0; j < 8; j++)
            {
                int i8j = i8 + j;
                diagonalDownRightMoves[i8j] = (1L << (i8j + 7)) | (1L << (i8j + 14)) | (1L << (i8j + 21)) | (1L << (i8j + 28)) |
                                                (1L << (i8j + 35)) | (1L << (i8j + 42)) | (1L << (i8j + 49));
                diagonalDownRightMoves[i8j] &= ~rowsToExclude & filesToInclude;
                filesToInclude |= file[j];
            }
            rowsToExclude |= row[i];
        }
    }

    private void createDiagonalUpLeftMoves()
    {
        long rowsToInclude = 0L;
        long filesToExclude;
        long row[] = new long[8];
        row[0] = row1;
        row[1] = row2;
        row[2] = row3;
        row[3] = row4;
        row[4] = row5;
        row[5] = row6;
        row[6] = row7;
        row[7] = row8;
        long file[] = new long[8];
        file[0] = fileA;
        file[1] = fileB;
        file[2] = fileC;
        file[3] = fileD;
        file[4] = fileE;
        file[5] = fileF;
        file[6] = fileG;
        file[7] = fileH;
        for(int i = 0; i < 8; i++)
        {
            int i8 = i * 8;
            filesToExclude = 0L;
            for(int j = 0; j < 8; j++)
            {
                int i8j = i8 + j;
                diagonalUpLeftMoves[i8j] = (1L << (i8j - 7)) | (1L << (i8j - 14)) | (1L << (i8j - 21)) | (1L << (i8j - 28)) |
                                            (1L << (i8j - 35)) | (1L << (i8j - 42)) | (1L << (i8j - 49));
                diagonalUpLeftMoves[i8j] &= rowsToInclude & ~filesToExclude;
                filesToExclude |= file[j];
            }
            rowsToInclude |= row[i];
        }
    }

    private void createDiagonalUpRightMoves()
    {
        long rowsToInclude = 0L;
        long filesToInclude;
        long row[] = new long[8];
        row[0] = row1;
        row[1] = row2;
        row[2] = row3;
        row[3] = row4;
        row[4] = row5;
        row[5] = row6;
        row[6] = row7;
        row[7] = row8;
        long file[] = new long[8];
        file[0] = fileA;
        file[1] = fileB;
        file[2] = fileC;
        file[3] = fileD;
        file[4] = fileE;
        file[5] = fileF;
        file[6] = fileG;
        file[7] = fileH;
        for(int i = 0; i < 8; i++)
        {
            int i8 = i * 8;
            filesToInclude = 0L;
            for(int j = 0; j < 8; j++)
            {
                int i8j = i8 + j;
                diagonalUpRightMoves[i8j] = (1L << (i8j - 9)) | (1L << (i8j - 18)) | (1L << (i8j - 27)) |
                                            (1L << (i8j - 36)) | (1L << (i8j - 45)) | (1L << (i8j - 54)) | (1L << (i8j - 63));
                diagonalUpRightMoves[i8j] &= rowsToInclude & filesToInclude;
                filesToInclude |= file[j];
            }
            rowsToInclude |= row[i];
        }
    }
    
    private void createBlackPawnAdvances()
    {
        for(int i = 8; i < 56; i++)
            blackPawnAdvances[i] = 1L << (i + 8);
    }
    
    private void createWhitePawnAdvances()
    {
        for(int i = 8; i < 56; i++)
            whitePawnAdvances[i] = 1L << (i - 8);
    }
    
    private void createRightMoves()
    {
        long rowsLeft = 0L;
        long file[] = new long[8];
        file[0] = fileA;
        file[1] = fileB;
        file[2] = fileC;
        file[3] = fileD;
        file[4] = fileE;
        file[5] = fileF;
        file[6] = fileG;
        file[7] = fileH;
        for(int i = 0; i < 8; i++)
        {
            int j = i;
            rightMoves[j] = (row1 ^ (1L << j)) & ~rowsLeft;
            j += 8;
            rightMoves[j] = (row2 ^ (1L << j)) & ~rowsLeft;
            j += 8;
            rightMoves[j] = (row3 ^ (1L << j)) & ~rowsLeft;
            j += 8;
            rightMoves[j] = (row4 ^ (1L << j)) & ~rowsLeft;
            j += 8;
            rightMoves[j] = (row5 ^ (1L << j)) & ~rowsLeft;
            j += 8;
            rightMoves[j] = (row6 ^ (1L << j)) & ~rowsLeft;
            j += 8;
            rightMoves[j] = (row7 ^ (1L << j)) & ~rowsLeft;
            j += 8;
            rightMoves[j] = (row8 ^ (1L << j)) & ~rowsLeft;
            j += 8;
            rowsLeft |= file[i];
        }
    }

    private void createLeftMoves()
    {
        long rowsRight = 0L;
        long file[] = new long[8];
        file[0] = fileA;
        file[1] = fileB;
        file[2] = fileC;
        file[3] = fileD;
        file[4] = fileE;
        file[5] = fileF;
        file[6] = fileG;
        file[7] = fileH;
        for(int i = 7; i >= 0; i--)
        {
            int j = i;
            leftMoves[j] = (row1 ^ (1L << j)) & ~rowsRight;
            j += 8;
            leftMoves[j] = (row2 ^ (1L << j)) & ~rowsRight;
            j += 8;
            leftMoves[j] = (row3 ^ (1L << j)) & ~rowsRight;
            j += 8;
            leftMoves[j] = (row4 ^ (1L << j)) & ~rowsRight;
            j += 8;
            leftMoves[j] = (row5 ^ (1L << j)) & ~rowsRight;
            j += 8;
            leftMoves[j] = (row6 ^ (1L << j)) & ~rowsRight;
            j += 8;
            leftMoves[j] = (row7 ^ (1L << j)) & ~rowsRight;
            j += 8;
            leftMoves[j] = (row8 ^ (1L << j)) & ~rowsRight;
            j += 8;
            rowsRight |= file[i];
        }
    }
    
    private void createUpMoves()
    {
        long rowsBelow = 0L;
        long row[] = new long[8];
        row[0] = row1;
        row[1] = row2;
        row[2] = row3;
        row[3] = row4;
        row[4] = row5;
        row[5] = row6;
        row[6] = row7;
        row[7] = row8;
        for(int i = 0, j = 0; i < 8; i++)
        {
            upMoves[j] = (fileA ^ (1L << j)) & ~rowsBelow;
            j++;
            upMoves[j] = (fileB ^ (1L << j)) & ~rowsBelow;
            j++;
            upMoves[j] = (fileC ^ (1L << j)) & ~rowsBelow;
            j++;
            upMoves[j] = (fileD ^ (1L << j)) & ~rowsBelow;
            j++;
            upMoves[j] = (fileE ^ (1L << j)) & ~rowsBelow;
            j++;
            upMoves[j] = (fileF ^ (1L << j)) & ~rowsBelow;
            j++;
            upMoves[j] = (fileG ^ (1L << j)) & ~rowsBelow;
            j++;
            upMoves[j] = (fileH ^ (1L << j)) & ~rowsBelow;
            j++;
            rowsBelow |= row[i];
        }
    }
    
    private void createDownMoves()
    {
        long rowsAbove = 0L;
        long row[] = new long[8];
        row[0] = row8;
        row[1] = row7;
        row[2] = row6;
        row[3] = row5;
        row[4] = row4;
        row[5] = row3;
        row[6] = row2;
        row[7] = row1;
        for(int i = 0, j = 63; i < 8; i++)
        {
            downMoves[j] = (fileH ^ (1L << j)) & ~rowsAbove;
            j--;
            downMoves[j] = (fileG ^ (1L << j)) & ~rowsAbove;
            j--;
            downMoves[j] = (fileF ^ (1L << j)) & ~rowsAbove;
            j--;
            downMoves[j] = (fileE ^ (1L << j)) & ~rowsAbove;
            j--;
            downMoves[j] = (fileD ^ (1L << j)) & ~rowsAbove;
            j--;
            downMoves[j] = (fileC ^ (1L << j)) & ~rowsAbove;
            j--;
            downMoves[j] = (fileB ^ (1L << j)) & ~rowsAbove;
            j--;
            downMoves[j] = (fileA ^ (1L << j)) & ~rowsAbove;
            j--;
            rowsAbove |= row[i];
        }

    }
    
    private void createKingAttackBitBoard()
    {
        // Store all moves which are one square in any of the eight directions from this one
        for(int i = 0; i < 64; i++)
        {
            squaresAttackedByKings[i] = (1L << (i - 9)) | (1L << (i - 8)) | (1L << (i - 7)) | (1L << (i - 1)) |
                                            (1L << (i + 1)) | (1L << (i + 7)) | (1L << (i + 8)) | (1L << (i + 9));
        }
        
        // Remove moves which wrap round to the opposite side of the board
        for(int i = 0; i < 8; i++)
        {
            squaresAttackedByKings[i]      &= ~row8;
            squaresAttackedByKings[i + 56] &= ~row1;
            int i8 = i * 8;
            squaresAttackedByKings[i8]     &= ~fileH;
            squaresAttackedByKings[i8 + 7] &= ~fileA;
        }
    }
    
    private void createBlackPawnAttackBitBoards()
    {
        for(int i = 1; i < 7; i++)
        {
            int i8 = i * 8;
            squaresAttackedByBlackPawns[i8] = 1L << (i8 + 9);
            
            for(int j = 1; j < 7; j++)
            {
                int i8j = i8 + j;
                squaresAttackedByBlackPawns[i8j] = (1L << (i8j + 9)) | (1L << (i8j + 7));
            }
            
            squaresAttackedByBlackPawns[i8 + 7] = 1L << (i8 + 7 + 7);
        }
    }
    
    private void createWhitePawnAttackBitBoards()
    {
        for(int i = 1; i < 7; i++)
        {
            int i8 = i * 8;
            squaresAttackedByWhitePawns[i8] = 1L << (i8 - 7);

            for(int j = 1; j < 7; j++)
            {
                int i8j = i8 + j;
                squaresAttackedByWhitePawns[i8j] = (1L << (i8j - 7)) | (1L << (i8j - 9));
            }

            squaresAttackedByWhitePawns[i8 + 7] = 1L << (i8 + 7 - 9);
        }
    }
    
    private void createKnightAttackBitBoard()
    {
        // Create 64 bitboards; one for each square
        for(int i = 0; i < 8; i++)
            for(int j = 0; j < 8; j++)
            {
                // Calculate the index of this square
                int s = (i * 8) + j;
                
                // Store all L-shaped moves from this square
                squaresAttackedByKnights[s]  = 1L << (((i - 1) * 8) + (j - 2));
                squaresAttackedByKnights[s] |= 1L << (((i - 2) * 8) + (j - 1));
                squaresAttackedByKnights[s] |= 1L << (((i + 2) * 8) + (j - 1));
                squaresAttackedByKnights[s] |= 1L << (((i + 1) * 8) + (j - 2));
                squaresAttackedByKnights[s] |= 1L << (((i - 1) * 8) + (j + 2));
                squaresAttackedByKnights[s] |= 1L << (((i - 2) * 8) + (j + 1));
                squaresAttackedByKnights[s] |= 1L << (((i + 2) * 8) + (j + 1));
                squaresAttackedByKnights[s] |= 1L << (((i + 1) * 8) + (j + 2));
                    
                // Remove moves which wrap round to the opposite side of the board
                if(j < 2)
                {
                    squaresAttackedByKnights[s] &= ~fileH;
                    if(j == 0)
                    {
                        squaresAttackedByKnights[s] &= ~fileG;
                    }
                }
                else if(j > 5)
                {
                    squaresAttackedByKnights[s] &= ~fileA;
                    if(j == 7)
                    {
                        squaresAttackedByKnights[s] &= ~fileB;
                    }
                }
                if(i < 2)
                {
                    squaresAttackedByKnights[s] &= ~row8;
                    if(i == 0)
                    {
                        squaresAttackedByKnights[s] &= ~row7;
                    }
                }
                else if(i > 5)
                {
                    squaresAttackedByKnights[s] &= ~row1;
                    if(i == 7)
                    {
                        squaresAttackedByKnights[s] &= ~row2;
                    }
                }
            }
    }

    public LinkedList<Move> legalWhiteMoves()
    {
        LinkedList<Move> list = new LinkedList<Move>();
        for(int i = 0; i < 64; i++)
        {
            long legalMoves = legalWhiteMoves(i);
            for(int j = 0; j < 64; j++)
            {
                if((legalMoves & (1L << j)) != 0)
                {
                    list.add(new Move(i, j));
                }
            }
        }
        return list;
    }
    
    public LinkedList<Move> legalBlackMoves()
    {
        LinkedList<Move> list = new LinkedList<Move>();
        for(int i = 0; i < 64; i++)
        {
            long legalMoves = legalBlackMoves(i);
            for(int j = 0; j < 64; j++)
            {
                if((legalMoves & (1L << j)) != 0)
                {
                    list.add(new Move(i, j));
                }
            }
        }
        return list;
    }

    public LinkedList listAllLegalMoves()
    {
        // Create a list of all moves
        LinkedList<Move> allMoves = this.getPlayer() == Minimax.MAX_TURN ? this.legalWhiteMoves() : this.legalBlackMoves();

        // Iterate through all moves to see if any of them are taking moves
        LinkedList<Move> takingMoves = new LinkedList<Move>();
        for(Move move : allMoves)
        {
            if(this.isTakingMove(move))
            {
                takingMoves.add(move);
            }
        }

        return takingMoves.isEmpty() ? allMoves : takingMoves;
    }

    public boolean isTakingMove(Move move)
    {
        if((whitePawns & (1L << move.source)) != 0 ||
           (whiteRooks & (1L << move.source)) != 0 ||
           (whiteKnights & (1L << move.source)) != 0 ||
           (whiteBishops & (1L << move.source)) != 0 ||
           (whiteKings & (1L << move.source)) != 0 ||
           (whiteQueens & (1L << move.source)) != 0)
        {
            return ((blackPawns & (1L << move.dest)) != 0 ||
                    (blackRooks & (1L << move.dest)) != 0 ||
                    (blackKnights & (1L << move.dest)) != 0 ||
                    (blackBishops & (1L << move.dest)) != 0 ||
                    (blackKings & (1L << move.dest)) != 0 ||
                    (blackQueens & (1L << move.dest)) != 0);
        }
        else if((blackPawns & (1L << move.source)) != 0 ||
           (blackRooks & (1L << move.source)) != 0 ||
           (blackKnights & (1L << move.source)) != 0 ||
           (blackBishops & (1L << move.source)) != 0 ||
           (blackKings & (1L << move.source)) != 0 ||
           (blackQueens & (1L << move.source)) != 0)
        {
            return ((whitePawns & (1L << move.dest)) != 0 ||
                    (whiteRooks & (1L << move.dest)) != 0 ||
                    (whiteKnights & (1L << move.dest)) != 0 ||
                    (whiteBishops & (1L << move.dest)) != 0 ||
                    (whiteKings & (1L << move.dest)) != 0 ||
                    (whiteQueens & (1L << move.dest)) != 0);
        }

        return false;
    }

    public void moveAction(Object m)
    {
        if(m == null)
            return;
            
        Move move = (Move)m;
        
        if(this.isWhitesTurn())
        {
            lastWhiteMove = move;
        }
        else
        {
            lastBlackMove = move;
        }

        // Remove the piece that previously occupied this square if there was one
        whitePawns &= ~(1L << move.dest);
        whiteKnights &= ~(1L << move.dest);
        whiteBishops &= ~(1L << move.dest);
        whiteRooks &= ~(1L << move.dest);
        whiteQueens &= ~(1L << move.dest);
        whiteKings &= ~(1L << move.dest);
        blackPawns &= ~(1L << move.dest);
        blackKnights &= ~(1L << move.dest);
        blackBishops &= ~(1L << move.dest);
        blackRooks &= ~(1L << move.dest);
        blackQueens &= ~(1L << move.dest);
        blackKings &= ~(1L << move.dest);
        
        // Move the piece in the source square to the destination square
        if((whitePawns & (1L << move.source)) != 0)
        {
            whitePawns &= ~(1L << move.source);
            whitePawns |= 1L << move.dest;
        }
        else if((whiteKnights & (1L << move.source)) != 0)
        {
            whiteKnights &= ~(1L << move.source);
            whiteKnights |= 1L << move.dest;
        }
        else if((whiteBishops & (1L << move.source)) != 0)
        {
            whiteBishops &= ~(1L << move.source);
            whiteBishops |= 1L << move.dest;
        }
        else if((whiteRooks & (1L << move.source)) != 0)
        {
            whiteRooks &= ~(1L << move.source);
            whiteRooks |= 1L << move.dest;
        }
        else if((whiteQueens & (1L << move.source)) != 0)
        {
            whiteQueens &= ~(1L << move.source);
            whiteQueens |= 1L << move.dest;
        }
        else if((whiteKings & (1L << move.source)) != 0)
        {
            whiteKings &= ~(1L << move.source);
            whiteKings |= 1L << move.dest;
        }
        else if((blackPawns & (1L << move.source)) != 0)
        {
            blackPawns &= ~(1L << move.source);
            blackPawns |= 1L << move.dest;
        }
        else if((blackKnights & (1L << move.source)) != 0)
        {
            blackKnights &= ~(1L << move.source);
            blackKnights |= 1L << move.dest;
        }
        else if((blackBishops & (1L << move.source)) != 0)
        {
            blackBishops &= ~(1L << move.source);
            blackBishops |= 1L << move.dest;
        }
        else if((blackRooks & (1L << move.source)) != 0)
        {
            blackRooks &= ~(1L << move.source);
            blackRooks |= 1L << move.dest;
        }
        else if((blackQueens & (1L << move.source)) != 0)
        {
            blackQueens &= ~(1L << move.source);
            blackQueens |= 1L << move.dest;
        }
        else if((blackKings & (1L << move.source)) != 0)
        {
            blackKings &= ~(1L << move.source);
            blackKings |= 1L << move.dest;
        }
        
        // Promote white pawns which have reached row 8
        for(int i = 0; i < 8; i++)
        {
            if((whitePawns & (1L << i)) != 0)
            {
                whitePawns &= ~(1L << i);
                whiteQueens |= 1L << i;
            }
        }
        
        // Promote black pawns which have reached row 1
        for(int i = 56; i < 64; i++)
        {
            if((blackPawns & (1L << i)) != 0)
            {
                blackPawns &= ~(1L << i);
                blackQueens |= 1L << i;
            }
        }
    }

    public void draw(Graphics g, int selectedSquare, JApplet applet)
    {
        g.setColor(Color.WHITE);
        g.fillRect(1, 1, 500, 500);
        boolean whiteSquare = true;
        LinkedList legalMoves = this.listAllLegalMoves();
        for(int j = 0, square = 0; j < 8; j++)
        {
            whiteSquare = !whiteSquare;
            for(int i = 0; i < 8; i++)
            {
                whiteSquare = !whiteSquare;
                g.setColor(whiteSquare ? Color.WHITE : Color.BLACK);
                g.fillRect(i * 50, j * 50, 50, 50);

                if(!this.isWhitesTurn())
                {
                    if(this.lastWhiteMove != null && (square == this.lastWhiteMove.dest || square == this.lastWhiteMove.source))
                    {
                        g.setColor(Color.RED);
                        g.drawRect((i * 50), (j * 50), 48, 48);
                        g.drawRect((i * 50) + 1, (j * 50) + 2, 47, 47);
                        g.drawRect((i * 50) + 1, (j * 50) + 2, 46, 46);
                    }
                    else if(this.lastBlackMove != null && (square == this.lastBlackMove.dest || square == this.lastBlackMove.source))
                    {
                        g.setColor(Color.BLUE);
                        g.drawRect((i * 50), (j * 50), 48, 48);
                        g.drawRect((i * 50) + 1, (j * 50) + 2, 47, 47);
                        g.drawRect((i * 50) + 1, (j * 50) + 2, 46, 46);
                    }
                }
                else
                {
                    if(this.lastBlackMove != null && (square == this.lastBlackMove.dest || square == this.lastBlackMove.source))
                    {
                        g.setColor(Color.BLUE);
                        g.drawRect((i * 50), (j * 50), 48, 48);
                        g.drawRect((i * 50) + 1, (j * 50) + 2, 47, 47);
                        g.drawRect((i * 50) + 1, (j * 50) + 2, 46, 46);
                    }
                    else if(this.lastWhiteMove != null && (square == this.lastWhiteMove.dest || square == this.lastWhiteMove.source))
                    {
                        g.setColor(Color.RED);
                        g.drawRect((i * 50), (j * 50), 48, 48);
                        g.drawRect((i * 50) + 1, (j * 50) + 2, 47, 47);
                        g.drawRect((i * 50) + 1, (j * 50) + 2, 46, 46);
                    }
                }
                
                if(square == selectedSquare)
                {
                    g.setColor(Color.YELLOW);
                    g.drawRect((i * 50), (j * 50), 48, 48);
                    g.drawRect((i * 50) + 1, (j * 50) + 2, 47, 47);
                    g.drawRect((i * 50) + 1, (j * 50) + 2, 46, 46);
                }
                /*else if(this.lastWhiteMove != null && (square == this.lastWhiteMove.dest || square == this.lastWhiteMove.source))
                {
                    g.setColor(Color.RED);
                    g.drawRect((i * 50), (j * 50), 48, 48);
                    g.drawRect((i * 50) + 1, (j * 50) + 2, 47, 47);
                    g.drawRect((i * 50) + 1, (j * 50) + 2, 46, 46);
                }
                else if(this.lastBlackMove != null && (square == this.lastBlackMove.dest || square == this.lastBlackMove.source))
                {
                    g.setColor(Color.BLUE);
                    g.drawRect((i * 50), (j * 50), 48, 48);
                    g.drawRect((i * 50) + 1, (j * 50) + 2, 47, 47);
                    g.drawRect((i * 50) + 1, (j * 50) + 2, 46, 46);
                }*/
                // Crude way of highlighting all legal moves for the currently selected piece
                Move m = new Move(selectedSquare, square);
                if(legalMoves.contains(m))
                {
                    g.setColor(Color.GREEN);
                    g.drawRect((i * 50), (j * 50), 48, 48);
                    g.drawRect((i * 50) + 1, (j * 50) + 2, 47, 47);
                    g.drawRect((i * 50) + 1, (j * 50) + 2, 46, 46);
                }

                Image image = null;
                long l = (1L << square);
                if((whitePawns & l) != 0)
                    image = Icons.whitePawn;
                else if((whiteRooks & l) != 0)
                    image = Icons.whiteRook;
                else if((whiteKnights & l) != 0)
                    image = Icons.whiteKnight;
                else if((whiteBishops & l) != 0)
                    image = Icons.whiteBishop;
                else if((whiteKings & l) != 0)
                    image = Icons.whiteKing;
                else if((whiteQueens & l) != 0)
                    image = Icons.whiteQueen;
                else if((blackPawns & l) != 0)
                    image = Icons.blackPawn;
                else if((blackRooks & l) != 0)
                    image = Icons.blackRook;
                else if((blackKnights & l) != 0)
                    image = Icons.blackKnight;
                else if((blackBishops & l) != 0)
                    image = Icons.blackBishop;
                else if((blackKings & l) != 0)
                    image = Icons.blackKing;
                else if((blackQueens & l) != 0)
                    image = Icons.blackQueen;

                if(image != null)
                {
                    g.drawImage(image, i * 50 + 9, j * 50 + 9, applet);
                }
                square++;
            }
        }

        /*for(int i = 0; i < 8; i++)
        {
            for(int j = 0; j < 8; j++)
            {
                //squaresAttackedByKnights[27] = 1 << 2;
                //squaresAttackedByKnights[((i * 8) + j)] = 1L << ((i - 1) * 8);
                long l = legalBlackMoves(5) & (long)(1L << ((j * 8) + i));
                g.setColor(l != 0 ? Color.BLACK : Color.GREEN);
                g.setColor(Color.BLUE);
                if(l != 0)
                    g.drawString("" + ((j * 8) + i), (j + 1) * 50, (i + 1) * 50);
            }
        }*/

    }

    public int getCurrentScore()
    {
        if(whitePawns == 0 && whiteRooks == 0 && whiteKnights == 0 && whiteBishops == 0 &&
           whiteKings == 0 && whiteQueens == 0)
        {
            return Minimax.MAX_HAS_WON;
        }

        if(blackPawns == 0 && blackRooks == 0 && blackKnights == 0 && blackBishops == 0 &&
           blackKings == 0 && blackQueens == 0)
        {
            return Minimax.MINI_HAS_WON;
        }

        int score = Minimax.STALE_MATE;

        for(int i = 0; i < 64; i++)
        {
            long a = 1L << i;
            if((whitePawns & a) != 0) { score--; }
            if((whiteRooks & a) != 0) { score -= 5; }
            if((whiteKnights & a) != 0) { score -= 3; }
            if((whiteBishops & a) != 0) { score -= 3; }
            if((whiteKings & a) != 0) { score -= 2; }
            if((whiteQueens & a) != 0) { score -= 9; }
            if((blackPawns & a) != 0) { score++; }
            if((blackRooks & a) != 0) { score += 5; }
            if((blackKnights & a) != 0) { score += 3; }
            if((blackBishops & a) != 0) { score += 3; }
            if((blackKings & a) != 0) { score += 2; }
            if((blackQueens & a) != 0) { score += 9; }
        }
        return score;
    }
    public void staleMate(){}
}

