Πέμπτη 24 Μαρτίου 2022

Chess java JChessPanel for learning kids opensource

1 week work....about 3000 lines of code (without comments)
jar and code updated 29 March

No AutoPlaying, Not playing over network

just exersize home or play with a friend on same computer  


download the JChessGame.jar from

(builded on ubuntu)

https://drive.google.com/file/d/1FzCoaqXV794lFSjaSy-gUk3O18wHj7X1/view?usp=sharing 

(updated 19 April to run also in ubuntu because line par.validate
was provoking crashing on ubuntu even if in windows was ok)
If you have Ubuntu then ensure perimissions before executing the .jar
by right click-properties-permissions
and check the 'allow executing File as program'

 

 ---older versions----

(  builded on win 7
Second link untested version with same board splitting in two chess boards for playong with a friend
From menu Opts->split (or not split)!!  5 April +~20 lines of code
https://drive.google.com/file/d/156jK7qQHwaSxFxNQ45s5Oixc0gWPgzPr/view?usp=sharing
)

If you dont have java installed ,from https://www.java.com/en/

,,then this .jar File will be opened ONLY as ZIP (and not as java executable)

so install java if you want just to test it.

Inside this 'zip' you can find the code ( 6 .java Files) as it is opensource.




If you find a critical bug
 (on chess algorythm)
please....
give me a comment.




------------------

Next : for programmers only.

The following code is 6 classes in one File ready to be compiled and run!!!

I will update it with some corrections,updates,and critical code comments

Some comments are out of date (meaning i was thinking that i will do the things
in a specific manner but this manner changed a little on the way)...but i will update a little.

Just that I hope the flow of the java code to be enough and easy to understand the program.

Tryed to write an excellent code for the core class that is: ChessBoard.java

If you read the code below and if you like ...please give me a grade on comments.

19 April
updated 1 line of code (par.validate())
that makes jar to crash when executing in ubuntu 20.04
But i am not changing the below code...
its only 2 lines....in the new link for open source .jar.
 //validates after some millis to fix the JSplitPanes nice
        Thread thrValidaterOneJobOnly=new Thread(){
            public void run(){
                try{Thread.sleep(123);}catch(InterruptedException inter){}
                Container par=getParent();
                JFrame jfr=null;
                while(par!=null){
                    //par.validate();//THIS VALIDATE crashes on UBUNTU

---------------------------------

/*

 * To change this license header, choose License Headers in Project Properties.

 * To change this template file, choose Tools | Templates

 * and open the template in the editor.

 */

package jchessgame;


import java.awt.BasicStroke;

import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.Component;

import java.awt.Container;

import java.awt.Dimension;

import java.awt.Font;

import java.awt.FontMetrics;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.GridLayout;

import java.awt.Image;

import java.awt.Insets;

import java.awt.Point;

import java.awt.Toolkit;

import java.awt.datatransfer.Clipboard;

import java.awt.datatransfer.ClipboardOwner;

import java.awt.datatransfer.DataFlavor;

import java.awt.datatransfer.Transferable;

import java.awt.datatransfer.UnsupportedFlavorException;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.ComponentEvent;

import java.awt.event.ComponentListener;

import java.awt.event.KeyEvent;

import java.awt.event.KeyListener;

import java.awt.event.MouseEvent;

import java.awt.event.MouseListener;

import java.awt.event.MouseMotionListener;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.IOException;

import java.util.Random;

import java.util.StringTokenizer;

import java.util.Vector;

import javax.imageio.ImageIO;

import javax.swing.AbstractButton;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JList;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

import javax.swing.JMenuItem;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JRadioButton;

import javax.swing.JScrollPane;

import javax.swing.JSlider;

import javax.swing.JSplitPane;

import javax.swing.JTabbedPane;

import javax.swing.JTextField;

import javax.swing.JToggleButton;

import javax.swing.SwingConstants;


/**

 *

 * @author jimis

 * 

 * This game matrix is NOT for RAM !!!!!!

 * Is for swing JChessGame assosiation 

 * 

 * and to avoid some possible inheritage problems

 * method :resetGame() must be called AFTER creation by the user

 * -else no public internal methods has been called

 */

public class ChessBoard {

    public static void main(String[] args) {

        JChessGame.main(args); 


    }

    

    /**

     * a1 c3 will fill 1 square (b2)

     * @param s1 like "a1"

     * @param v

     * @param s2 like "c3" 

     * @return how many squares (encoded as pos64=col*8 +row filled on Vector

     */

    public static int fillBetweenSquares(String s1,Vector<Byte> v,String s2){

        int p1=parsePos64(s1);

        int p2=parsePos64(s2);

        return fillBetweenSquares(p1/8,p1%8, v, p2/8,p2%8);

    }

    public static int fillBetweenSquares(int x1,int y1,Vector<Byte> v,int x2,int y2){

        

        int counts=0;

        int xdif=x2-x1;

        int ydif=y2-y1;

        int xdabs=Math.abs(xdif);

        int ydabs=Math.abs(ydif);

        int xdir=0;

        int ydir=0;

        boolean starts=false;

        if(xdif==0){

            if(ydabs>1){//like castle or queen

                starts=true;

                ydir=ydif/ydabs;

            }

        }

        else if(ydif==0){

            if(xdabs>1){//like castle or queen

                starts=true;

                xdir=xdif/xdabs;

            }

        }

        else if(xdabs==ydabs && xdabs>1){//like bishop or queen

            starts=true;

            xdir=xdif/xdabs;

            ydir=ydif/ydabs;

        }

        if(starts){

            int x=x1+xdir,y=y1+ydir;        

            while( ! (x==x2 && y==y2)){

                v.add((byte)x);

                v.add((byte)y);

                x+=xdir;

                y+=ydir;

                ++counts;

            }

        }

        return counts;

    }

    

    

    

    public static final int white=0;

    public static final int black=1;

    public static final int pawnFinalRow[]={7,0};

    public static final int pawnStartingRow[]={1,6};

    public static final int pawnRowDirection[]={1,-1};

    public static final int pawnRowToCheckAnpasan[]={4,3};

    public static String queenOrHorseString[]={"Queen","Horse"};

    public static final int queensColRowDirections[]={ 1,0,-1, 0, 0,1, 0,-1    ,1,1,1,-1,-1,1,-1,-1}; 

    public static final int bishopsColRowDirections[]={1,1, 1,-1,-1,1,-1,-1}; 

    public static final int castlesColRowDirections[]={1,0,-1, 0, 0,1, 0,-1}; 

    public static final int horsesColRowDirections[]={ 2,1,1,2,2,-1,-1,2,  -2,1,1,-2,-2,-1,-1,-2}; 

    

    public static char[] colchars={'a','b','c','d','e','f','g','h'};

    public static char[] rowchars={'1','2','3','4','5','6','7','8'};

    public static String square(int x,int y){

        return colchars[x]+""+rowchars[y];

    }

    

    public static final String officialInitialPositionsString=

            "e1,e8,d1,d8,f1,f8,c1,c8,g1,g8,b1,b8,h1,h8,a1,a8"+

            ",e2,e7,d2,d7,f2,f7,c2,c7,g2,g7,b2,b7,h2,h7,a2,a7";

    

    /**

     * 

     * @param abcdefgh12345678 must be of length 2 and [A,H]+[1,8]

     * @return encoded square as col*8+row

     */

    public static byte parsePos64(String abcdefgh12345678){

        char chcol=Character.toUpperCase(abcdefgh12345678.charAt(0));

        char chrow=abcdefgh12345678.charAt(1);

        chcol-='A';

        chrow-='1';

        return (byte)(chcol*8+chrow);

    }

    public static byte toPos64(int i,int j){

        return (byte)(i*8+j);

    }

    public static boolean isValidPos64(int somepos){

        return somepos>-1 && somepos<64;

    }

    public static boolean isValidSquare(int somecol ,int somerow){

        return somecol>-1 && somecol<8 && somerow>-1 && somerow<8 ;

    }

    /**

     * used from swing classes 

     * @param p

     * @return 

     */

    public static boolean isValidSquare(Point p){

        return p.x>-1 && p.x<8 && p.y>-1 && p.y<8 ;

    }

    


    /**

     * Every pc has a code [0,31]

     * Because processors are most propably more quicker if using byte(8-bit)

     * instead of ints

     * but because we need easy and clear code

     * we can use int that has 4 bytes

     * and have it like this

     * a)1st byte (most right-low significant) for the piece code

     * b)2nd byte for current postion 2^3+2^3=2^6 remaining 2 bits

     * c)3rd byte for initial postion 2^3+2^3=2^6 remaining 2 bits

     * d)4th byte remaining unused....

     * 

     * but this version is using 2 bytes for col and row of every piece

     * 

     */

    public static final int pieces=32;

    public static final int indexKingsStart=0;

    public static final int indexKingsLength=2;

    public static final int indexQueensStart=2;

    public static final int indexQueensLength=2;

    public static final int indexBishopsStart=4;

    public static final int indexBishopsLength=4;

    public static final int indexHorsesStart=8;

    public static final int indexHorsesLength=4;

    public static final int indexRooksStart=12;

    public static final int indexRooksLength=4;

    public static final int indexPawnsStart=16;

    public static final int indexPawnsLength=16;


    protected byte pccol[]=new byte[32];//for quick access

    protected byte pcrow[]=new byte[32];  

    public void getPoint(int code32,Point p){

        p.x=pccol[code32];

        p.y=pcrow[code32];

    }

    public int getColOf(int code32){

        return pccol[code32];

    }

    public int getRowOf(int code32){

        return pcrow[code32];

    }

    public int getPosOf(int code32){

        return pccol[code32]*8+pcrow[code32];

    }

    public String getPieceString(int code32){

        return ""+ChessMove.umap32[getSameOrTransformedToWhat(code32)];

    }


    

    /**

     * contains the [0-31] piece code being to.. or -1 for empty

     * Warning..Transfoprmed pawns are not visible in this array....

     */

    protected byte sq[][]=new byte[8][8];

    public int getPieceAt(Point p){

        return sq[p.x][p.y];

    }

    public int getPieceAt(int col,int row){

        return sq[col][row];

    }

    

    public static final int maxMovesOfSixPieceTypes[]={8,28,14,8,14,4};

    public static int maxMovesFor(int code32){

        code32%=32;

        if(code32<2){return 8;}//kings

        else if(code32<4){return 28;}//queens

        else if(code32<8){return 14;}//bishops

        else if(code32<12){return 8;}//horses

        else if(code32<16){return 14;}//rooks

        return 4;//pawns

    }

    

    /**

     * The game is for sure finished if current player has 0 (zero) available moves

     * will be cleared on every resetGame() and applyChessMove()

     */

    protected short totalAvailableMoves[]=new short[2];

    

    /**

     * On each game roll(move of some player) vectors are being cleared and

     * and when finding available movements 

     * each piece (from 32) will add their self(their index)

     * if they target some square

     * because we need this 

     * when we ask to solve if is mat.........

     * 

     * In some first version we only need 

     * to see if some square that some king can go

     * is being targeted by enemy.

     * 

     * In some second version we need to know how mach enemies

     * targeting some square ..just to know if roua-sax is doubled...by 2 or more? pieces

     * 

     * Because if doubled  roua-sax then to avoid mat we can only move king

     * But if just one enemy targeting(roua-sax) the king

     * then to avoid mat we have 3 conditions

     * 

     * a)move king

     * b)eat the enemy (only if is one enemy-thats why 2nd version)

     * c)put something in the line between in case of the enemy 

     * ca)is only one

     * cb)is like queen,rook,bishop (not horse or pawn ..or king)

     * 

     * And thats why this 3rd version (heavy on ram)

     * to easy know (after the available moves research)

     * WHITCH enemy is targeting roua 

     * and answer quickly if we can search to put some between....

     * 

     * Using Vector in this first version but may better 

     * to use some byte [8][8][1+16?]array.

     * 1 for length and ...how many possible pieces of same team can target a square?

     * i think 8 horses +4 bishops +4 castles...so 16 +1 17 

     * so byte[8][8][2][17] ???[2] for each team in this case? 

     * instead of allocating vectors may be better

     * Anyway....

     */

    public Vector<Byte>[][][] sqTargetedBy=new Vector[8][8][2];

    

    /**

     * king max moves =8 *2(suppose starting square is on edge as about castling...)

     * queen max moves =28 *2

     * bishop max moves =14 *4

     * horse max moves = 8*4

     * rook max moves = 14 *4

     * pawn max moves=4 *16

     * -----------------

     * total allocated bytes = 360 (without pawn transformation)

     * (and without the array internal indexing...)

     * +32 bytes of how many available moves found for each piece..=392 bytes!

     * 

     * This is critical to save ram....

     * Just that if some pawn is being transform we must increase the array length

     * 

     * vailableMoves64Coded[0][0] contains how many available moves we found for white king

     * 

     * In the first position [0] we put the sum of available moves of each piece

     * meaning starting from [1] to put the encoded squares 

     * C4= col(2) row(3) so encoded will be 2*8+3=19

     * 

     * will be initialised on constructor

     * 

     */

    protected byte availableMoves64Coded[][]=new byte[32][];

    

    

    

    protected void addAvailableSquareMoveForPiece(int code32,int colsq,int rowsq){

        addAvailableSquareMoveForPiece(code32, colsq, rowsq,true);

    }

    protected void addAvailableSquareMoveForPiece(int code32,int colsq,int rowsq,boolean mark){

        int team=code32%2;

        int pos64=colsq*8+rowsq;

        int currsize=availableMoves64Coded[code32][0];

        int indexwriting=currsize+1;

        availableMoves64Coded[code32][0]++;

        availableMoves64Coded[code32][indexwriting]=(byte)pos64; 

        totalAvailableMoves[team]++;

    }


    public int getAvailableMoveCount(int code32){

        return availableMoves64Coded[code32][0];

    }

    /**

     * @param code32

     * @param index

     * @return int=col*8+row  

     */

    public int getAvailableMove(int code32,int index){

        return availableMoves64Coded[code32][1+index];

    }

    public void getAvailableMove(int code32,int index,Point p){

        int pos64=availableMoves64Coded[code32][1+index];

        p.x=pos64/8;

        p.y=pos64%8;

    }

    public boolean isAvailableMove(int code32,int x,int y){

        int l=availableMoves64Coded[code32][0];

        int pos64;

        int i=1;

        l++;

        while(i<l){

            pos64=availableMoves64Coded[code32][i];

            if(pos64/8==x && pos64%8==y){

                return true;

            }

            ++i;

        }

        return false;

    }

    

    

    

    

    


    /**

     * Resgister for in or out of chessboard status

     */

    protected int instatusregister=-1;//all ones means all in

    public boolean isInFlag(int pc32){

        return (instatusregister & (1<<pc32) )!=0;

    }

    public boolean isOutFlag(int pc32){

        int status=instatusregister;

        status>>=pc32;

        return status%2==0;

    }

    public void setInFlag(int pc32){

        instatusregister |= 1 << pc32;

    }

    public void setOutFlag(int pc32){

        instatusregister &= ~(1 << pc32);

    }

    public void setAllInFlag(){

        instatusregister=-1;

    }

    public void setAllOutFlag(){

        instatusregister=0;

    }

    

    /**

     * Register for if pawn is transformed

     * first 16 bits are unused

     */

    protected int transformedregister=0;//all zeros means all untransformed

    public boolean isTransformedFlag(int pc32){

        return (transformedregister & (1<<pc32) )!=0;

    }

    public boolean isNotTransformedFlag(int pc32){

        int status=transformedregister;

        status>>=pc32;

        return status%2==0;

    }

    protected void setTransformedFlag(int pc32){

        transformedregister |= 1 << pc32;

    }

    protected void setNotTransformedFlag(int pc32){

        transformedregister &= ~(1 << pc32);

    }

    protected void setAllTransformedFlag(){

        transformedregister=-1;

    }

    protected void setAllNotTransformedFlag(){

        transformedregister=0;

    }

    

    /**

     * Register for if pawn is transformed to horse (1) or queen(0)

     * first 16 bits are unused

     */

    protected int horsenotqueenregister=0;//all zeros means all queens if transformed

    public boolean isHorseFlag(int pc32){

        return (horsenotqueenregister & (1<<pc32) )!=0;

    }

    public boolean isNotHorseFlag(int pc32){

        int status=horsenotqueenregister;

        status>>=pc32;

        return status%2==0;

    }

    protected void setHorseFlag(int pc32){

        horsenotqueenregister |= 1 << pc32;

    }

    protected void setNotHorseFlag(int pc32){

        horsenotqueenregister &= ~(1 << pc32);

    }

    protected void setAllHorseFlag(){

        horsenotqueenregister=-1;

    }

    protected void setAllNotHorseFlag(){

        horsenotqueenregister=0;

    }

    



    public boolean isPawn(int code32){

        return code32>=16;

    }

    protected void setPawnNormal(int code32){

        setNotTransformedFlag(code32);

        //not earning some bytes....back in case we use this function

        //availableMoves64Coded[code32]=new byte[1+maxMovesFor(code32)];

    }

    protected void setPawnQueen(int code32){

        setTransformedFlag(code32);

        setNotHorseFlag(code32);

        //increase how much available moves now the transformed pawn can have instead of 4

        availableMoves64Coded[code32]=new byte[1+maxMovesFor(indexQueensStart+code32%2)];//no need for +code32%2

    }

    protected void setPawnHorse(int code32){

        setTransformedFlag(code32);

        setHorseFlag(code32);

        availableMoves64Coded[code32]=new byte[1+maxMovesFor(indexHorsesStart+code32%2)];

    }



    /**

     * 

     * @param code32

     * @return same or if is transformed pawn then 

     * to what (queen|horse of the same team)to be easy to print 

     */

    public int getSameOrTransformedToWhat(int code32){

        int out=code32;

        if(isPawn(code32)){

            if(isTransformedFlag(code32)){

                if(isHorseFlag(code32)){

                    out=8+code32%2;

                }

                else{

                    out=2+code32%2;

                }

            }

        }

        return out;

        

    }

    

    public static final int FREE=0;

    public static final int NORMAL=1;

    

    /**

     * May need this in case we want some kind of freedom movement

     * arranging as an example the pieces on board

     * Meaning can move pieces where ever and if passing on others just put them out....

     * In such scenario we stiil need to find after every move 

     * the available moves...!!!!

     * This project is for kids........to easy understand the available movements 

     */

    protected int gameTypeFree=NORMAL;

    public boolean isGameFree(){

        return gameTypeFree==FREE;

    }

    public boolean isGameTypeNormal(){

        return gameTypeFree==NORMAL;

    }

    public void setGameFree(){

        gameTypeFree=FREE;

    }

    public void setGameNormal(){

        gameTypeFree=NORMAL;

    }

    public void setGameFree(boolean free){

        if(free){

            gameTypeFree=FREE;

        }

        else{

            gameTypeFree=NORMAL;

        }

    }

    

    

    /**

     * ......more job for programmer !!!!

     */

    protected long timeStarted;//,timeFinished;

    public long timePlaying(){

        return System.currentTimeMillis()-timeStarted;

    }

    

    /**

     * Those will be for all games (not reseting when resetGame()...just for see..temp!)

     */

    protected long timesSearchedAvailableMoves=1;

    protected long timeFindMovesAverage=10,timeFindMovesMin=Long.MAX_VALUE,timeFindMovesMax=-1;

    

    

    /**

     * final link?....

     */

    public final ChessGame movesPlayed=new ChessGame();


    public int whoPlays(){

        return movesPlayed.size()%2;

    }

    public int whoPlaysEnemy(){

        return (1+movesPlayed.size())%2;

    }

    

    

    

    /**

     * Allocates the arrays

     * you must call resetGame() after

     */

    public ChessBoard(){

        int i=0,j;

        while(i<32){

            availableMoves64Coded[i]=new byte[1+maxMovesFor(i)];

            ++i;

        }

        i=0;

        while(i<8){

            j=0;

            while(j<8){

                sqTargetedBy[i][j][0]=new Vector<Byte>();

                sqTargetedBy[i][j][1]=new Vector<Byte>();

                ++j;

            }

            ++i;

        }

    }  

    

    

    /**

     * Used for setting chess exercises methods below.

     * a little stupid function to just have some static arrays for following setPOSXXX()

     * all this because i dont want to write a setInAtInitial(int some piece)..

     * because my clearToInitialPositionsRequire exactly 32 length of the coded squares 

     * and i dont want to change it...for some reason relative to possible random positions

     * @param toLeaveOnlyIndexes 

     */

    public void setAllNotKingsOut(int toLeaveOnlyIndexes[]){

        resetGame();

        int i=2,j;

        boolean found;

        while(i<32){

            j=0;

            found=false;

            while(j<toLeaveOnlyIndexes.length){

                if(i==toLeaveOnlyIndexes[j]){

                    found=true;

                    j=toLeaveOnlyIndexes.length;

                }

                ++j;

            }

            if(!found){

                setOut(i);

            }

            ++i;

        }

        searchAllAvailableMoves();

        //System.out.println("setAllNotKingsOut(except["+toLeaveOnlyIndexes.length+"])");

    }

    public void setAllPawnsOut(){

        resetGame();

        int i=16;

        while(i<32){

            setOut(i);

            ++i;

        }

        searchAllAvailableMoves();

        //System.out.println("setAllPawnsOut()");

    }

    public void setAllNotPawnsOut(){

        resetGame();

        int i=2;

        while(i<16){

            setOut(i);

            ++i;

        }

        searchAllAvailableMoves();

        //System.out.println("setAllNotPawnsOut()");

    }

    public static final int[]onlyWhiteQueen(){return new int[]{2};}

    public void setPosMatQueen(){

        setAllNotKingsOut(onlyWhiteQueen());

        setNewPos(1, 4, 2);

        searchAllAvailableMoves();

        //System.out.println("setPosMatQueen()");

    }

    public static final int[]onlyWhiteQueens(){return new int[]{2,3};}

    public void setPosMatQueens(){

        setAllNotKingsOut(onlyWhiteQueens());

        setNewPos(2, 0, 0);

        searchAllAvailableMoves();

        //System.out.println("setPosMatQueens()");

    }

    public static final int[]onlyWhiteRook(){return new int[]{12};}

    public void setPosMatRook(){

        setAllNotKingsOut(onlyWhiteRook());

        setNewPos(1, 4, 2);

        searchAllAvailableMoves();

        //System.out.println("setPosMatRook()");

    }

    public static final int[]onlyWhiteRooks(){return new int[]{12,14};}

    public void setPosMatRooks(){

        setAllNotKingsOut(onlyWhiteRooks());

        setNewPos(1, 4, 2);

        searchAllAvailableMoves();

        //System.out.println("setPosMatRook()");

    }

    public static final int[]onlyWhiteBishops(){return new int[]{4,6};}

    public void setPosMatBishops(){

        setAllNotKingsOut(onlyWhiteBishops());

        //System.out.println("setPosMatBishops()");

    }

    public static final int[]onlyWhiteBishopsAndHorses(){return new int[]{4,6,8,10};}

    public void setPosMatHorseAndBishop(){

        setAllNotKingsOut(onlyWhiteBishopsAndHorses());

        //System.out.println("setPosMatHorseAndBishop()");

    }

    

    

    /**

     * used from setPosRandom()

     * @return 

     */

    protected int countAllInPieces_TargetedByCounts(){

        int out=0;

        int i=0;

        while(i<32){

            if(isInFlag(i)){

                out+=sqTargetedBy[pccol[i]][pcrow[i]][(i+1)%2].size();

            }

            ++i;

        }

        //System.out.println("out="+out);

        return out;

    }

    

    /**

     * 1st version of this method....so most propably not perfect

     * override ...in case

     */

    public void setPosRandom(){

        resetGame();

        Random r=new Random();

        int i=0;

        int t,p,x,y,tt,xx,yy,pp=0,normalIn;

        while(i<32){

            setOut(i);

            ++i;

        }

        Vector<Integer> squaresAVailable=new Vector<>();

        i=0;

        while(i<64){

            squaresAVailable.add(i);

            ++i;

        }

        

        Vector<Integer> normalsIn=new Vector<>();

        Vector<Integer> available=new Vector<>();

        Vector<Integer> temp;

        available.add(2);

        available.add(4);

        available.add(6);

        available.add(8);

        available.add(10);

        available.add(12);

        available.add(14);

        normalIn=1+r.nextInt(available.size());

        //normalIn=7;

        System.out.println("normal whites in : "+normalIn);

        i=0;

        while(i<normalIn){

            t=available.remove(r.nextInt(available.size()));

            normalsIn.add(t);

            ++i;

            

        }


        available.clear();

        available.add(2+1);

        available.add(4+1);

        available.add(6+1);

        available.add(8+1);

        available.add(10+1);

        available.add(12+1);

        available.add(14+1);

        normalIn=1+r.nextInt(available.size());

        //normalIn=7;

        System.out.println("normal blacks in : "+normalIn);

        i=0;

        while(i<normalIn){

            t=available.remove(r.nextInt(available.size()));

            normalsIn.add(t);

            ++i;            

        }

        //System.out.println(""+normalsIn);

        available.clear();

        i=0;

        t=normalsIn.size();

        while(i<t){

            available.add(normalsIn.remove(r.nextInt(normalsIn.size())));

            ++i;

        }

        temp=available;

        available=normalsIn;

        normalsIn=temp;

        //System.out.println(""+normalsIn);

        

        i=0;

        int maxtries=100;

        boolean isOk;

        int allowsTargetByTotalCount=r.nextInt(5);

        //System.out.println("allowsTargetBy "+allowsTargetByTotalCount);

        int tries=0;

        while(i<normalsIn.size()){

            t=normalsIn.get(i);

            tt=(t+1)%2;

            

            isOk=false;

            tries=0;

            while(!isOk  && tries<maxtries){

                ++tries;

                pp=r.nextInt(squaresAVailable.size());

                p=squaresAVailable.get(pp);

                x=p/8;

                y=p%8;

                setPos0(t, x, y);

                searchAllAvailableMoves();

                if(countAllInPieces_TargetedByCounts()<=allowsTargetByTotalCount){

                    isOk=true;

                    

                }else{

                    setOut(t);

                }

            }

            squaresAVailable.remove(pp);

            ++i;

        }

        if(tries==maxtries){

            System.out.println("broked from maxtries "+maxtries);

        }

        System.out.println("Total targets: "+countAllInPieces_TargetedByCounts());


        tries=0;

        while(tries<maxtries){

            pp=r.nextInt(squaresAVailable.size());

            p=squaresAVailable.get(pp);

            x=p/8;

            y=p%8;

            if(sqTargetedBy[x][y][1].size()==0){

                setPos0(0, x, y);

                squaresAVailable.remove(pp);

                break;

            }

            //System.out.println(square(x, y)+" is targeted from "+sqTargetedByEnemy[x][y][1].size()+" white kings enemies");

            ++tries;

        }

        if(tries==maxtries){

            //System.out.println("white king Broked by max tries");

            pp=r.nextInt(squaresAVailable.size());

            p=squaresAVailable.remove(pp);

            x=p/8;

            y=p%8;

            setPos0(0, x, y);

        }


        searchAllAvailableMoves();

        


        

        t=1;

        isOk=false;

        tries=0;

        while(!isOk  && tries<maxtries){

            ++tries;

            pp=r.nextInt(squaresAVailable.size());

            p=squaresAVailable.get(pp);

            x=p/8;

            y=p%8;

            if(!(Math.abs(x-pccol[0])<2 && Math.abs(y-pcrow[0])<2)){

                setPos0(t, x, y);

                searchAllAvailableMoves();

                if(sqTargetedBy[x][y][0].size()==0){

                    isOk=true;


                }else{

                    setOut(t);

                } 

            }

            //else{System.out.println("Blacking king near white king cancelled");}

        }

        squaresAVailable.remove(pp);


        searchAllAvailableMoves();

        System.out.println("setPosRandom()");

    }

    

    /**

     * used in free mode to just put inside some piece 

     * If lets say you need a queen ..then pressing the order queen button

     * will place the real queen inside or

     * if is already in will try to transform some pawn (if not inside)

     * 

     * The square will be put it...will try to be the initial square 

     * or if is occupied ..some random free square

     * @param code12 as 0 wk ,1 bk ,,,,see Chessmove.u12

     * @return the code32 that added or -1 

     */

    public int putOnBoardSomeOfThe12TypesOfPieces(int code12){

        int reputedInside=-1;

        if(isGameFree()){

            

            vHelpAvoidingNew.clear();

            int code6=code12/2;

            int blackdif=code12%2;

            boolean toTransformToQueen=false;

            boolean toTransformToHorse=false;

            int i,l,p,pos,x,y;

            

            if(code6<1){

                vHelpAvoidingNew.add((byte)(0+blackdif));//king

            }

            else if(code6<2){

                vHelpAvoidingNew.add((byte)(2+blackdif));//queen

                i=16+blackdif;

                while(i<32){

                    vHelpAvoidingNew.add((byte)i);

                    i+=2;

                }

                toTransformToQueen=true;

            }

            else if(code6<3){

                vHelpAvoidingNew.add((byte)(4+blackdif));//bishops

                vHelpAvoidingNew.add((byte)(6+blackdif));

            }

            else if(code6<4){

                vHelpAvoidingNew.add((byte)(8+blackdif));//horses

                vHelpAvoidingNew.add((byte)(10+blackdif));

                i=16+blackdif;

                while(i<32){

                    vHelpAvoidingNew.add((byte)i);

                    i+=2;

                }

                toTransformToQueen=true;

                toTransformToHorse=true;

            }

            else if(code6<5){

                vHelpAvoidingNew.add((byte)(12+blackdif));//rooks

                vHelpAvoidingNew.add((byte)(14+blackdif));

            }

            else{

                i=16+blackdif;

                while(i<32){

                    vHelpAvoidingNew.add((byte)i);

                    i+=2;

                }                

            }

            

            i=0;

            l=vHelpAvoidingNew.size();

            while(i<l){

                p=vHelpAvoidingNew.get(i);

                if(!isInFlag(p)){

                    //System.out.println("we found the first available");

                    pos=movesPlayed.pos64Initial[p];

                    x=pos/8;

                    y=pos%8;

                    if(sq[x][y]>-1){//just find the forsi empty 

                        int xx=0,yy;

                        while(xx<8){

                            yy=0;

                            while(yy<8){

                                if(sq[xx][yy]<0){

                                    x=xx;//we found some free pos

                                    y=yy;

                                    xx=8;//break

                                    yy=8;

                                }

                                ++yy;

                            }

                            ++xx;

                        }

                    }

                    reputedInside=p;

                    setPos0(reputedInside, x, y);

                    if(isPawn(reputedInside)){

                        setPawnNormal(reputedInside);//maybe from previus was transformed

                        if(toTransformToQueen){

                            if(toTransformToHorse){

                                setPawnHorse(reputedInside);

                            }

                            else{

                                setPawnQueen(reputedInside);

                            }

                        }

                    }

                    searchAllAvailableMoves();

                    break;

                }

                ++i;

            }   

        }

        return reputedInside;

    }

    

    

    

    

    

    

    

    

    


    public void resetGame(){

        

        movesPlayed.clear();

        

        setAllNotTransformedFlag();

        setAllNotHorseFlag();

        

        clearSquares();

        clearToInitialPositionsAndUpdateSqArrayAndInFlag();//must be called after clearing squares

        

        notEatCounter=0;

        timeStarted=System.currentTimeMillis();

        //timeFinished=timeStarted;

        

        searchAllAvailableMoves();

        

        

    }

    protected void clearSquares(){

        int i=0,j;

        while(i<8){

            j=0;

            while(j<8){

                sq[i][j]=-1;

                ++j;

            }

            ++i;

        }

    }

    

    /**

     * called also after every move

     */

    protected void clearTargetedByEnemy(){

        int i=0,j;

        while(i<8){

            j=0;

            while(j<8){

                sqTargetedBy[i][j][0].clear();

                sqTargetedBy[i][j][1].clear();

                ++j;

            }

            ++i;

        }

    }


    

    /**

     * clears also total available sum counters

     */

    protected void clearAvailableMoves(){

        totalAvailableMoves[0]=0;

        totalAvailableMoves[1]=0;

        int i=0;

        while(i<32){

            availableMoves64Coded[i][0]=0;//indicates that this chesspiece has not moves installed

            ++i;

        }

    }

    /**

     * Must avoid game with no kings????

     */

    protected void clearToInitialPositionsAndUpdateSqArrayAndInFlag(){

        int i=0;

        while(i<32){

            if(movesPlayed.pos64Initial[i]>-1){

                pccol[i]=(byte)(movesPlayed.pos64Initial[i]/8);

                pcrow[i]=(byte)(movesPlayed.pos64Initial[i]%8);

                sq[pccol[i]][pcrow[i]]=(byte)i;

                setInFlag(i);

            }

            else{

                pccol[i]=-1;

                pcrow[i]=-1;

                setOutFlag(i);

            }

            ++i;

        }    

    }

    

    public String getChessboardString(){

        String out="";

        int i=0,j,pc;

        while(i<8){

            j=0;

            while(j<8){

                pc=sq[i][j];

                if(pc>-1){

                    out+=ChessMove.umap32[getSameOrTransformedToWhat(pc)];

                }

                else{

                    out+="_";

                }

                ++j;

            }

            out+="\n";

            ++i;

        }

        return out;

    }

    

    

    /**

     * Called on resetGame() and on applyChessMove()

     * ...we must know all pieces available moves..not only of the current playing!

     */

    protected void searchAllAvailableMoves(){

        

        long ts=System.currentTimeMillis();

        clearTargetedByEnemy();

        clearAvailableMoves();

        searchingAllAvailableMoves();

        long te=System.currentTimeMillis();

        te-=ts;

        ++timesSearchedAvailableMoves;

        timeFindMovesAverage+=te;

        timeFindMovesAverage/=2;//??!!!

        if(te>timeFindMovesMax){

            timeFindMovesMax=te;

        }

        if(te<timeFindMovesMin){

            timeFindMovesMin=te;

        }

        

        System.out.println("WB_AvMoves:( "+totalAvailableMoves[0]+" , "+totalAvailableMoves[1]+" ),"+"Millis Tooked : "+te+" , Av( "+timeFindMovesAverage+") min( "+timeFindMovesMin+" ) , max( "+timeFindMovesMax+" )");

    }

    

    /**

     * override this in case....

     * available moves and targeted by enemy arrays have been cleared before calling this

     * Kings must be searched last !!!!

     * And after kings we must 

     * first cancel moves of nailed(locked) pieces

     * and after...decide sax,mat,draw status

     * At the end of this method we must know also

     * the states of 

     * a)sax/roua

     * b)sax/roua AND MAT 

     * c)draw by repeating 3 same movements

     * d)draw by not eating on last 50 movements !!!

     */

    public void searchingAllAvailableMoves(){

        searchingAllAvailableMovesOfQueens();

        searchingAllAvailableMovesOfBishops();

        searchingAllAvailableMovesOfHorses();

        searchingAllAvailableMovesOfRooks();

        searchingAllAvailableMovesOfPawns();

        searchingAllAvailableMovesOfKings();


        searchingAndCancelingMovesOfNailedPiecesLeavingOnlyEatNailingSource();

        

        searchingForSaxOrMatOrDrawStatus();

    }

    public void searchingAllAvailableMovesOfQueens(){

        int i=indexQueensStart,l=i+indexQueensLength;

        while(i<l){

            if(isInFlag(i)){searchingAvailableMovesLikeQueen(i);}

            ++i;

        }

    }

    public void searchingAvailableMovesLikeQueen(int code32){

        int i=0;

        while(i<queensColRowDirections.length){

            checkToAddMoveOnDifsContiniuslly(code32,queensColRowDirections[i], queensColRowDirections[i+1]);

            i+=2;

        }

        //System.out.println(code32+" queen : "+availableMoves64Coded[code32][0]);

    }

    public void searchingAllAvailableMovesOfBishops(){

        int i=indexBishopsStart,l=i+indexBishopsLength;

        while(i<l){

            if(isInFlag(i)){searchingAvailableMovesLikeBishop(i);}

            ++i;

        }

    }

    public void searchingAvailableMovesLikeBishop(int code32){

        int i=0;

        while(i<bishopsColRowDirections.length){

            checkToAddMoveOnDifsContiniuslly(code32,bishopsColRowDirections[i], bishopsColRowDirections[i+1]);

            i+=2;

        }

        //System.out.println(code32+" bishop : "+availableMoves64Coded[code32][0]);

    }

    public void searchingAllAvailableMovesOfHorses(){

        int i=indexHorsesStart,l=i+indexHorsesLength;

        while(i<l){

            if(isInFlag(i)){searchingAvailableMovesLikeHorse(i);}

            ++i;

        }        

    }

    public void searchingAvailableMovesLikeHorse(int code32){

        int i=0;

        while(i<horsesColRowDirections.length){

            checkToAddMoveOnDifs(code32,horsesColRowDirections[i], horsesColRowDirections[i+1]);

            i+=2;

        }

        //System.out.println(code32+" horse : "+availableMoves64Coded[code32][0]);

    }

    public void searchingAllAvailableMovesOfRooks(){

        int i=indexRooksStart,l=i+indexRooksLength;

        while(i<l){

            if(isInFlag(i)){searchingAvailableMovesLikeRook(i);}

            ++i;

        }        

    }

    public void searchingAvailableMovesLikeRook(int code32){

        int i=0;

        while(i<castlesColRowDirections.length){

            checkToAddMoveOnDifsContiniuslly(code32,castlesColRowDirections[i], castlesColRowDirections[i+1]);

            i+=2;

        }

        //System.out.println(code32+" rook : "+availableMoves64Coded[code32][0]);

    }

    public void searchingAllAvailableMovesOfPawns(){

        int i=indexPawnsStart,l=i+indexPawnsLength;

        while(i<l){

            if(isInFlag(i)){

                if(isTransformedFlag(i)){

                    if(isHorseFlag(i)){

                        searchingAvailableMovesLikeHorse(i);

                    }

                    else{

                        searchingAvailableMovesLikeQueen(i);

                    }

                }

                else{

                    searchingAvailableMovesLikePawn(i);

                }

            }

            ++i;

        }

    }

    

    public void searchingAllAvailableMovesOfKings(){

        int i=indexKingsStart,l=i+indexKingsLength;

        while(i<l){

            if(isInFlag(i)){searchingAvailableMovesLikeKing(i);}

            ++i;

        } 

    }

    

    /**

     * Those 2 Vectors dangerous in case of further use of this project

     * or multithread...but some king of avoiding creating new Vectors

     * 

     * from here down ,,,the code needs a little more buetiness..(28 March)

     */

    protected Vector<Byte> vHelpAvoidingNew=new Vector<>();

    protected Vector<Byte> vHelpCancellingMoves=new Vector<>();

    

    protected void cancelMovesThatAreNotInColRowVector(int code32,Vector<Byte>v){

        int l=getAvailableMoveCount(code32);//availableMoves64Coded[code32][0];

        int vl=v.size();

        if(l>0 && vl>0){

            int i=0,j,resl;

            byte xam,yam,xv,yv;

            vHelpCancellingMoves.clear();

            byte pos;

            while(i<l){

                pos=availableMoves64Coded[code32][i+1];

                xam=(byte)(pos/8);

                yam=(byte)(pos%8);

                

                j=0;

                while(j<vl){

                    xv=v.get(j);

                    ++j;

                    yv=v.get(j);

                    ++j;

                    

                    if(xv==xam && yv==yam){

                        vHelpCancellingMoves.add(pos);

                        break;

                    }

                } 

                

                ++i;

            }

            

            resl=vHelpCancellingMoves.size();

            availableMoves64Coded[code32][0]=(byte)resl;

            totalAvailableMoves[code32%2]-=(l-resl);

            

            System.out.println("piece: "+code32+" had "+l+" moves but now have only "+resl+" available moves");

            i=0;

            while(i<resl){

                availableMoves64Coded[code32][i+1]=vHelpCancellingMoves.get(i);

                ++i;

            }            

        }

    }

    

    

    /**

     * using on searching nailing

     * @param code32

     * @return 0 if its not like q,b,r

     * 1 if is like queen

     * 2 if is like bishop

     * 3 if is like rook

     */

    public int isLikeQueenBishopRook(int code32){

        if(code32<2){

            return 0;//king

        }

        else if(code32>=2 && code32<4){

            return 1;//queen

        }

        else if(code32>=4 && code32<8){

            return 2;//bishop

        }

        else if(code32>=8 && code32<12){

            return 0;//horse

        }

        else if(code32>=12 && code32<16){

            return 3;//rook

        }

        else {//if(code32>=16){

            if(isTransformedFlag(code32) && isNotHorseFlag(code32)){

                return 1;//queen

            }

            else{

                return 0;//normal or horse

            }

        }


    }

    /**

     * array just for painting/inform ...we can ignore if want ram smallest possible

     */

    public byte nailedPieces[]=new byte[2];

    

    void searchingAndCancelingMovesOfNailedPiecesLeavingOnlyEatNailingSource(){

        nailedPieces[0]=0;

        nailedPieces[1]=0;

        if(isInFlag(0) && isInFlag(1)){

            int kingChecking=0;//comments to not confuse as checking white (0) king

            while(kingChecking<2){

                int kingOpposite=(kingChecking+1)%2;//we will search all whites that same line with black king

                int xking=pccol[kingOpposite];

                int yking=pcrow[kingOpposite];

                int i=kingChecking+2;

                int xpc,ypc,piecetype;

                while(i<32){

                    if(isInFlag(i)){

                        piecetype=isLikeQueenBishopRook(i);

                        if(piecetype>0){

                            //System.out.println("checkNailing of "+i);//check if this white lets say queen is inline with black king

                            xpc=pccol[i];

                            ypc=pcrow[i];

                            int xdif=xking-xpc;

                            int ydif=yking-ypc;

                            int xdabs=Math.abs(xdif);

                            int ydabs=Math.abs(ydif);

                            int xdir=0;

                            int ydir=0;

                            boolean starts=false;

                            if(xdif==0){

                                if(ydabs>1){

                                    starts=piecetype!=2;//not bishop (queen 1 or rook 3)

                                    ydir=ydif/ydabs;

                                }

                            }

                            else if(ydif==0){

                                if(xdabs>1){

                                    starts=piecetype!=2;//not bishop (queen 1 or rook 3)

                                    xdir=xdif/xdabs;

                                }

                            }

                            else if(xdabs==ydabs && xdabs>1){

                                starts=piecetype!=3;//not rook (queen 1 or bishop 2)

                                xdir=xdif/xdabs;

                                ydir=ydif/ydabs;

                            }

                            if(starts){//then this 'white queen' is inline with black king

                                System.out.println("piece at "+square(xpc,ypc)+" directions: ("+xdir+","+ydir+")");

                                vHelpCancellingMoves.clear();

                                vHelpAvoidingNew.clear();

                                int x=xpc+xdir,y=ypc+ydir,pcatxy;        

                                while( ! (x==xking && y==yking)){//this condition is dangerous!!!!(hope not here!)

                                    System.out.println("sq "+x+" , "+y);

                                    pcatxy=sq[x][y];

                                    if(pcatxy>-1){

                                        if(pcatxy%2==kingOpposite){//meaning this white queen is inline with black king but between there is a black piece

                                            vHelpCancellingMoves.add((byte)pcatxy);

                                        }

                                        else{

                                            vHelpCancellingMoves.clear();//no nailing

                                            //this breaking will create a crash at pcatxy=sq[x][y] crash the while!!!!x=xking,y=yking;

                                            break;

                                        }

                                    }else{//else on empty square add this square to possible available moves so that can continue nailing..in case we found nail

                                        vHelpAvoidingNew.add((byte)x);

                                        vHelpAvoidingNew.add((byte)y);      

                                    }

                                    x+=xdir;

                                    y+=ydir;

                                }

                                if(vHelpCancellingMoves.size()==1){

                                    pcatxy=vHelpCancellingMoves.get(0);

                                    ++nailedPieces[kingOpposite];

                                    System.out.println("This is a nailed piece "+pcatxy+" from "+square(xpc,ypc)+" directions: ("+xdir+","+ydir+")");///so this black piece is NAILED by some white queen!!!


                                    vHelpAvoidingNew.add((byte)xpc);

                                    vHelpAvoidingNew.add((byte)ypc);

                                    //this function will use vector vHelpCancellingMoves but i dont care now...SOS

                                    //also i wnat to check only 1 square here (xpc,ypc) but this method is designed to 

                                    //check all vector on parameter (2 objects are 1 point)but its ok...just to avoid further coding and methods

                                    cancelMovesThatAreNotInColRowVector(pcatxy, vHelpAvoidingNew);

                                }



                            }//end starts

                        }//end if is like q,b,r

                    }//end if is in

                    i+=2;

                }

                ++kingChecking;

            }

        

        }

    }


    

    

    

    

    protected boolean sax,mat;

    protected byte pat;

    public void sax(){

        System.out.println("sax");

        JChessGame.beep();

    }

    public boolean isSax(){

        return sax;

    }

    public void mat(){

        System.out.println("MAT");

        JChessGame.beep(5, 100,500);

    }

    public boolean isMat(){

        return mat;

    }

    public static final int PAT_MISTAKE=1;

    public static final int PAT_REPETITION=2;

    public static final int PAT_50_MOVES=3;

    public static String patType[]={"NAN","PAT_MISTAKE","PAT_REPETITION","PAT_50_MOVES",""};

    public String getPatString(){

        return patType[pat];

    }

    public void pat(int patType){

        pat=(byte)(patType);

        System.out.println("pat :  "+pat);

        JChessGame.beep(2, 800,800);

    }

    public boolean isPat(){

        return pat>0;

    }

    public void searchingForSaxOrMatOrDrawStatus(){

        sax=false;

        mat=false;

        pat=0;

        int king=whoPlays();

        if(isInFlag(king)){//in case of free game

            int xofking=pccol[king];

            int yofking=pcrow[king];

            int enemyking=(king+1)%2;

            int enemiesTargetingToKing=sqTargetedBy[xofking][yofking][enemyking].size();

            if(enemiesTargetingToKing>0){

                

                sax=true;

                sax();

                int kingAvailableMoves=getAvailableMoveCount(king);

                int avoidanceOfMatAvailableMoves=kingAvailableMoves;

                

                //if is only one enemies check if can

                //a)eat this enemy with something 

                //b)put something between only if enemy is like queen,bishop,rook and distance>1

                //else if more than 1 enemy then only can move king to avoid mat

                

                if(enemiesTargetingToKing==1){

                    int pcTargetingTheKing=sqTargetedBy[xofking][yofking][enemyking].get(0);

                    //we must find who can eat this square

                    //byte colTargetingKing=pccol[pcTargetingTheKing];

                    //byte rowTargetingKing=pcrow[pcTargetingTheKing];  

                    vHelpAvoidingNew.clear();

                    vHelpAvoidingNew.add(pccol[pcTargetingTheKing]);

                    vHelpAvoidingNew.add(pcrow[pcTargetingTheKing]);

                    boolean isLikeHorseOrUntransformedPawn=false;

                    if(isPawn(pcTargetingTheKing)){

                        if(isTransformedFlag(pcTargetingTheKing) && isHorseFlag(pcTargetingTheKing)){

                            isLikeHorseOrUntransformedPawn=true;

                        }

                    }

                    else if(pcTargetingTheKing>=indexHorsesStart && pcTargetingTheKing<(indexHorsesStart+indexHorsesLength)){

                        isLikeHorseOrUntransformedPawn=true;

                    }

                    if( ! isLikeHorseOrUntransformedPawn){

                        //gather all betweensqares and if any

                        fillBetweenSquares(xofking, yofking, vHelpAvoidingNew, pccol[pcTargetingTheKing],pcrow[pcTargetingTheKing]);

                        

                    }

                    //and find who can move to those squares

                    int squaresSearching=vHelpAvoidingNew.size()/2;

                    System.out.println("Searching "+squaresSearching+" squares for if some enemy can move there else we cancel their available moves");

                    //we could just search only to squares but i want to CANCEL every other movement in sax king team

                    

                    

                    int pcSearching=king+2;

                    while(pcSearching<32){

                        if(isInFlag(pcSearching)){

                            cancelMovesThatAreNotInColRowVector(pcSearching, vHelpAvoidingNew);

                        }

                        pcSearching+=2;

                    }

                }

                else{

                    System.out.println("Only king can move (revealing sax)");

                    int i=king+2;

                    while(i<32){

                        availableMoves64Coded[i][0]=0;

                        i+=2;

                    }

                    totalAvailableMoves[king]=availableMoves64Coded[king][0];

                }


                System.out.println("Can avoid MAT with "+totalAvailableMoves[king]+" moves");

                if(totalAvailableMoves[king]==0){

                    mat=true;

                    mat();

                }

                

            }

            else{

                if(totalAvailableMoves[king]==0){

                    System.out.println("draw-pat : Someone made mistake");

                    pat(PAT_MISTAKE);

                }

                

            }

        }

        if((!sax)&&(!mat)&&(!isPat())&&(!isGameFree())){

            int l=movesPlayed.size();

            

            if(l>7){

                ChessMove cm1=movesPlayed.get(l-1);

                ChessMove cm5=movesPlayed.get(l-5);

                boolean b0=cm1.equals(cm5);

                //System.out.println(cm1.equals(cm5)+" : "+cm1+" ? "+cm5);

                if(b0){

                    ChessMove cm3=movesPlayed.get(l-3);

                    ChessMove cm7=movesPlayed.get(l-7);

                    boolean b1=cm3.equals(cm7);

                    //System.out.println(cm3.equals(cm7)+" : "+cm3+" ? "+cm7);

                    

                    if(b1){

                        ChessMove cm2=movesPlayed.get(l-2);

                        ChessMove cm6=movesPlayed.get(l-6);

                        boolean b2=cm2.equals(cm6);

                        //System.out.println(cm2.equals(cm6)+" : "+cm2+" ? "+cm6);

                        if(b1){

                            ChessMove cm4=movesPlayed.get(l-4);

                            ChessMove cm8=movesPlayed.get(l-8);

                            boolean b4=cm4.equals(cm8);

                            //System.out.println(cm4.equals(cm8)+" : "+cm4+" ? "+cm8);

                            if(b4){

                                System.out.println("draw-pat : Threefold Repetition");

                                pat(PAT_REPETITION);

                            }

                        }


                    }

                }

                

                if(!isPat()){

                    

                    if(notEatCounter>48){//...!!!

                        System.out.println("draw-pat : 50-Move Rule");

                        pat(PAT_50_MOVES);

                    }

                }

            }

        }

    }

    

    


    /**

     * addMove if valid and empty or enemy

     * mark square if valid 

     * and return valid and empty 

     * in order to continue adding difs just for minimize code

     * @param code32

     * @param colDif

     * @param rowDif

     * @return 

     */

    public boolean checkToAddMoveAt(int code32,int newcol,int newrow){

        boolean validAndEmpty=isValidSquare(newcol, newrow);

        if(validAndEmpty){

            //System.out.println("checkToAddMoveOnDifs "+square(newcol,newrow));

            int team=code32%2;

            sqTargetedBy[newcol][newrow][team].add((byte)code32);

            int occupiedBy=sq[newcol][newrow];

            if(occupiedBy>-1){

                validAndEmpty=false;

                if(occupiedBy%2!=team){

                    addAvailableSquareMoveForPiece(code32, newcol,newrow);//eating

                }

            }

            else{

                addAvailableSquareMoveForPiece(code32, newcol,newrow);

            }

        }


        return  validAndEmpty;

    }

    

    public boolean checkToAddMoveOnDifs(int code32,int colDif,int rowDif){

        return checkToAddMoveAt(code32, pccol[code32]+colDif,pcrow[code32]+rowDif);

    }

    public void checkToAddMoveOnDifsContiniuslly(int code32,int colDif,int rowDif){

        int times=0;

        int newcol=pccol[code32]+colDif;

        int newrow=pcrow[code32]+rowDif;

        int team=code32%2;

        while(isValidSquare(newcol, newrow)){

            ++times;

            sqTargetedBy[newcol][newrow][team].add((byte)code32);

            int occupiedBy=sq[newcol][newrow];

            if(occupiedBy>-1){

                if(occupiedBy%2!=team){

                    addAvailableSquareMoveForPiece(code32, newcol,newrow);//eating

                }

                

                if(occupiedBy==(team+1)%2){//occupied by the enemy king

                    //this if tests to mark as targeted some square near the king

                    //lets say a row have 

                    //white queen___(spaces)__black king___SOME SQUARE EMPTY OR WITH SOME WHITE PIECE

                    //then the first square BEHIND king (looking from queen)

                    //must be marked also as targeted by this queen

                    //because we will break(see 10 lines below) this while now that we found some piece!!!

                    //System.out.println("is enemy KING");

                    newcol+=colDif;

                    newrow+=rowDif;

                    if(isValidSquare(newcol, newrow)){//ok...next to the direction we are following is valid

                        //System.out.println("next is valid");

                        int nextocuupied=sq[newcol][newrow];

                        if(nextocuupied<0 || nextocuupied%2==team){//empty or some piece that the enemy king could eat otherwise

                            //System.out.println("MARKING");

                            sqTargetedBy[newcol][newrow][team].add((byte)code32);

                            //...........this marked square is not really marked.....!?!

                        }

                    }

                }

                

                break;//this break is breaking on the first not empty square.see above explanation

            }

            else{

                addAvailableSquareMoveForPiece(code32, newcol,newrow);

            }

            newcol+=colDif;

            newrow+=rowDif;

            

        }

        

        

    }

    

    

    

    public void searchingAvailableMovesLikePawn(int code32){

        int team=code32%2;

        int i=pccol[code32];

        int j=pcrow[code32];

        int in,jn;

        

        if(j!=pawnFinalRow[team]){

            jn=j+pawnRowDirection[team];

            if(i>0){//if 'left' column valid

                in=i-1;

                sqTargetedBy[in][jn][team].add((byte)code32);

                if(sq[in][jn]<0){

                    //check an pasan left

                    if(j==pawnRowToCheckAnpasan[team] && isLastMovePawnDoubleForwardOnColumn(in)){

                        //System.out.println("Pawn "+code32+" can anpasan left-negative");

                        addAvailableSquareMoveForPiece(code32, in,jn,false );

                    }

                }

                else if(sq[in][jn]%2!=team){

                    addAvailableSquareMoveForPiece(code32, in,jn,false );

                }

            }

            if(i<7){//if 'right' column valid

                in=i+1;

                sqTargetedBy[in][jn][team].add((byte)code32);

                if(sq[in][jn]<0){

                    //check an pasan right

                    if(j==pawnRowToCheckAnpasan[team] && isLastMovePawnDoubleForwardOnColumn(in)){

                        //System.out.println("Pawn "+code32+" can anpasan right-positive");

                        addAvailableSquareMoveForPiece(code32, in,jn,false );

                    }

                }

                else if(sq[in][jn]%2!=team){

                    addAvailableSquareMoveForPiece(code32, in,jn);

                }

            }

            if(sq[i][jn]<0){//check norma forward 1 square

                addAvailableSquareMoveForPiece(code32, i,jn,false);

                if(j==pawnStartingRow[team]){//and previus was empty 

                    jn+=pawnRowDirection[team];//check the double forward

                    if(sq[i][jn]<0){

                        addAvailableSquareMoveForPiece(code32, i,jn,false);

                    }

                }

            }

        }

        

        //System.out.println(code32+" pawns : "+availableMoves64Coded[code32][0]);

    }

    boolean isLastMovePawnDoubleForwardOnColumn(int i){

        boolean out=false;

        int l=movesPlayed.size();

        if(l>0){

            ChessMove last=movesPlayed.get(l-1);

            if(last.colfrom==i && last.colto==i){

                if(Math.abs(last.rowfrom-last.rowto)==2){

                    if(isPawn(last.pcfrom)){

                        out=true;

                    }

                }

            }

        }

        return out;

    }

    

    static final int kingdifs[]={

        1,0,

        1,1,

        0,1,

        -1,1,

        -1,0,

        -1,-1,

        0,-1,

        1,-1

    

    };

    boolean isSquareValidAndNotNearKing(int king,int x,int y){

        boolean out=isValidSquare(x, y);

        

        if(out){

            if(isInFlag(king)){

                out=!(Math.abs(x-pccol[king])<2 && Math.abs(y-pcrow[king])<2);

            }

        }

        return out;

    }

    /**

     * a little more code just to not overheat other functions just checking every time if is king

     * @param code32 

     */

    public void searchingAvailableMovesLikeKing(int code32){

        int team=code32%2;

        int enemyTeam=(team+1)%2;

        int colsq=pccol[code32];

        int rowsq=pcrow[code32];

        int i=0,newcol,newrow;

        while(i<16){

            newcol=colsq+kingdifs[i];

            ++i;

            newrow=rowsq+kingdifs[i];

            ++i;

            if(isSquareValidAndNotNearKing(enemyTeam,newcol, newrow) && sqTargetedBy[newcol][newrow][enemyTeam].size()==0){

                sqTargetedBy[newcol][newrow][team].add((byte)code32);

                int occupiedBy=sq[newcol][newrow];

                if(occupiedBy>-1){

                    if(occupiedBy%2!=team){

                        addAvailableSquareMoveForPiece(code32, newcol,newrow);//eating

                    }

                }

                else{

                    addAvailableSquareMoveForPiece(code32, newcol,newrow);

                }

            }

        }

        if( team==movesPlayed.size()%2

                &&pccol[code32]==movesPlayed.getInitialColFor(code32)

                &&pcrow[code32]==movesPlayed.getInitialRowFor(code32)){

            

            RooksForCastlingFoundAndBeReadyForActualMoveOnThisTurn[0]=checkCastlingForKing(team, enemyTeam,pccol[code32], pcrow[code32],-1);

            RooksForCastlingFoundAndBeReadyForActualMoveOnThisTurn[1]=checkCastlingForKing(team, enemyTeam,pccol[code32], pcrow[code32],1);

            

        }

        //else{System.out.println("Avoiding heavy castling checking");}

        //System.out.println(code32+" kings : "+availableMoves64Coded[code32][0]);

        

    }

    

    /**

     * Castling Moves/Rooks will be assigned only for the player that is now playing!!

     */

    private byte[] RooksForCastlingFoundAndBeReadyForActualMoveOnThisTurn={-1,-1};

    /**

     * trying to avoid double coding and to be ready for random chess positions

     * @param code32

     * @param enemyTeam

     * @param i

     * @param j

     * @param dir

     * @return 

     */

    byte checkCastlingForKing(int king,int enemyTeam,int i,int j,int dir){

        //System.out.println(code32+" checking castling "+dir);

        if(validAndEmptyAndNotTargetBy(enemyTeam, i+dir, j) && validAndEmptyAndNotTargetBy(enemyTeam, i+dir+dir, j)){

            int in=i+dir*3;

            while(validAndEmpty(in, j)){

                in+=dir;

            }

            if(isValidSquare(in, j) && Math.abs(in-i)>2){

                if(sq[in][j]==(king+12) || sq[in][j]==(king+14) ){

                    if( (!movesPlayed.hasBeenMoved(king)) && (!movesPlayed.hasBeenMoved(sq[in][j]))){//here is the processor heavy...

                        addAvailableSquareMoveForPiece(king, i+dir+dir, j);

                        System.out.println("Castling available for rook "+sq[in][j]);

                        return sq[in][j];

                    }

                }

            }

        }  

        return -1;

    }

    boolean validAndEmptyAndNotTargetBy(int team,int i,int j){

        return i>-1 && i<8 && j>-1 && j<8 && sq[i][j]<0 && sqTargetedBy[i][j][team].size()==0 ;

    }

    boolean validAndEmpty(int i,int j){

        return i>-1 && i<8 && j>-1 && j<8 && sq[i][j]<0 ;

    }

    

    void setOut(int pc32){

        setOutFlag(pc32);

        sq[pccol[pc32]][pcrow[pc32]]=-1;

        pccol[pc32]=-1;//or -pccol[pc32]; to keep last postion

        pcrow[pc32]=-1;

    }

    void setNewPos(int pcfrom,int xfrom,int yfrom,int xto,int yto){

        sq[xfrom][yfrom]=-1;

        pccol[pcfrom]=(byte)xto;

        pcrow[pcfrom]=(byte)yto;

        sq[xto][yto]=(byte)pcfrom;

    }

    /**

     * sets InFlag and piece and square pos

     * @param pcfrom

     * @param xto

     * @param yto 

     */

    void setPos0(int pcfrom,int xto,int yto){

        pccol[pcfrom]=(byte)xto;

        pcrow[pcfrom]=(byte)yto;

        sq[xto][yto]=(byte)pcfrom;

        setInFlag(pcfrom);

    }

    /**

     * sets -1 the old pos on sq[][] of this piece

     * Does not change the InFlag

     * Updates pccol,pcro,sq[][] with new values

     * @param pcfrom

     * @param xto

     * @param yto 

     */

    void setNewPos(int pcfrom,int xto,int yto){

        sq[pccol[pcfrom]][pcrow[pcfrom]]=-1;

        pccol[pcfrom]=(byte)xto;

        pcrow[pcfrom]=(byte)yto;

        sq[xto][yto]=(byte)pcfrom;

    }

    

    

    

    public ChessMove applyChessMove(int xfrom,int yfrom,int xto,int yto){

        return applyChessMove(xfrom, yfrom, xto, yto,null);

    }

    public boolean wantsTransformHorse(Component toAskOnTransformation){

        int answer = JOptionPane.showOptionDialog(toAskOnTransformation,"Queen or Horse ?","Pawn transformation",JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE,null,queenOrHorseString,queenOrHorseString[0]);

        return answer==1;

    }

    

    /**

     * to help for 50-moves 

     */

    protected int notEatCounter;

    public ChessMove applyChessMove(int xfrom,int yfrom,int xto,int yto,Component toAskOnTransformation){

        //System.out.println("apply("+xfrom+","+yfrom+" ,,, "+xto+","+yto);

        ChessMove out=null;

        if(isValidSquare(xfrom, yfrom) && (xfrom!=xto || yfrom!=yto)){

            int pcfrom=sq[xfrom][yfrom];

            if(pcfrom>-1){

                int actualfrom=getSameOrTransformedToWhat(pcfrom);

                if(!isValidSquare(xto,yto)){

                    if(isGameFree()){

                        setOut(pcfrom);

                        out=new ChessMove(xfrom,yfrom,pcfrom,actualfrom,xto,yto,-1,-1);

                    }

                    else{

                        System.out.println("not valid target square");

                    }

                }

                else{

                    int teamfrom=pcfrom%2;

                    if( (!isGameFree()) && ((teamfrom!=movesPlayed.size()%2)||(!isAvailableMove(pcfrom, xto, yto)))   ){

                        System.out.println("Wrong player or This move is not allowed from precomputation.or my algo is wrong");

                    }

                    else{

                        boolean untransformedPawn=pcfrom>15 && isNotTransformedFlag(pcfrom);

                        int pcto=sq[xto][yto];

                        int actualto=-1;

                        if(pcto>-1){

                            actualto=getSameOrTransformedToWhat(pcto);

                            //neither castling ,neither anpasan

                            //no need to check if same team in case of Normal mode game because we have checked before the available moves.

                        }

                        else{//empty then just check castling and an pasan before happening

                            

                            if(untransformedPawn && Math.abs(xfrom-xto)==1 && yto-yfrom==pawnRowDirection[teamfrom]){//minimise possible cheks as possible

                                int maybepcto=sq[xto][yto-pawnRowDirection[teamfrom]];

                                if(maybepcto>=16 && maybepcto%2!=teamfrom && isNotTransformedFlag(maybepcto)&& movesPlayed.size()>0 && movesPlayed.get(movesPlayed.size()-1).pcfrom==maybepcto){

                                    System.out.println("An pasan ok");

                                    pcto=maybepcto;

                                }

                                else{

                                    System.out.println("This is not an pasan..may reach here only on free mode");

                                }

                            }

                            else if(pcfrom<2){

                                //checking castling

                                int xdif=xto-xfrom;

                                if(Math.abs(xdif)==2 && yto==yfrom){

                                    if(xdif==2 && RooksForCastlingFoundAndBeReadyForActualMoveOnThisTurn[1]>-1){

                                        System.out.println("positive roke");

                                        pcto=8*pccol[RooksForCastlingFoundAndBeReadyForActualMoveOnThisTurn[1]];

                                        pcto+=pcrow[RooksForCastlingFoundAndBeReadyForActualMoveOnThisTurn[1]];

                                        pcto+=10;

                                        pcto=-pcto;//encode the position of rook  for undo in case of random chess 

                                        setNewPos(RooksForCastlingFoundAndBeReadyForActualMoveOnThisTurn[1],xto-1,yto);

                                    }

                                    else if(RooksForCastlingFoundAndBeReadyForActualMoveOnThisTurn[0]>-1){

                                        System.out.println("negative roke");

                                        pcto=8*pccol[RooksForCastlingFoundAndBeReadyForActualMoveOnThisTurn[0]];

                                        pcto+=pcrow[RooksForCastlingFoundAndBeReadyForActualMoveOnThisTurn[0]];

                                        pcto+=10;

                                        pcto=-pcto;//encode the position of rook  for undo in case of random chess

                                        setNewPos(RooksForCastlingFoundAndBeReadyForActualMoveOnThisTurn[0],xto+1,yto);

                                    }

                                }

                            }

                            

                        }

                        if(pcto>-1){

                            actualto=getSameOrTransformedToWhat(pcto);

                            setOut(pcto);

                            notEatCounter=0;

                        }

                        else{

                            notEatCounter++;

                        }

                        setNewPos(pcfrom, xfrom, yfrom, xto, yto);

                        out=new ChessMove(xfrom,yfrom,pcfrom,actualfrom,xto,yto,pcto,actualto);


                        

                        

                        //checking here the transformation

                        if(untransformedPawn){

                            if( (yto==7 && teamfrom==0 ) || (yto==0 && teamfrom==1 ) ){

                                if(wantsTransformHorse(toAskOnTransformation)){

                                    setPawnHorse(pcfrom);

                                    

                                }

                                else{

                                    setPawnQueen(pcfrom);

                                }

                            }

                            else{

                                //System.out.println("This move is not transforming pawn");

                            }

                        }

                    }

                }

                

                

            }

            else{

                System.out.println("Move of nobody piece not allowed");

            }

        }

        else{

            System.out.println("same squares or not valid from-square");

        }

        

        if(out!=null){

            movesPlayed.add(out);

            searchAllAvailableMoves();

        }

        

        return out;

    }

    

    

    public void undo(){

        if(isGameFree()){

            int mps=movesPlayed.size();

            if(mps>0){

                ChessMove lastMove=movesPlayed.get(mps-1);

                movesPlayed.remove(lastMove);

                if(!isValidSquare(lastMove.colto, lastMove.rowto)){

                    setPos0(lastMove.pcfrom, lastMove.colfrom, lastMove.rowfrom);

                }

                else{

                    sq[lastMove.colto][lastMove.rowto]=-1;

                    //check colfrom,rowfrom ???????

                    sq[lastMove.colfrom][lastMove.rowfrom]=lastMove.pcfrom;

                    pccol[lastMove.pcfrom]=lastMove.colfrom;

                    pcrow[lastMove.pcfrom]=lastMove.rowfrom;


                    if(lastMove.pcto>-1){

                        setInFlag(lastMove.pcto);

                        sq[lastMove.colto][lastMove.rowto]=lastMove.pcto;

                        pccol[lastMove.pcto]=lastMove.colto;

                        pcrow[lastMove.pcto]=lastMove.rowto;


                        System.out.println(notEatCounter+" notEatCounter ERROR HERE !!! on undo Capturing Move ...!!!");

                    }

                    else{

                        --notEatCounter;

                    }


                    if(lastMove.pcfrom<2){

                        if(Math.abs(lastMove.colfrom-lastMove.colto)==2 && lastMove.rowfrom==lastMove.rowto){//no reason for 2nd check?

                            //System.out.println("undoing the castling not ready");

                            int rookcol=lastMove.colfrom+1;

                            if(lastMove.colto<lastMove.colfrom){

                                rookcol=lastMove.colfrom-1;

                            }

                            int rookbetween=sq[rookcol][lastMove.rowfrom];

                            if(rookbetween>-1 && rookbetween>=12 && rookbetween<=16){

                                //System.out.println(rookbetween+"=Rook , Col : "+rookcol);


                                int rookLastPos=-lastMove.pcto;//decoding 

                                rookLastPos-=10;//decoding 


                                int rookLastCol=rookLastPos/8;

                                int rookLastRow=rookLastPos%8;


                                setNewPos(rookbetween, rookLastCol,rookLastRow);

                            }

                            else{

                                //System.out.println("maybe was free big move of king");

                            }



                        }

                    }

                    else if(isPawn(lastMove.pcfrom)){

                        if(lastMove.rowto==pawnFinalRow[lastMove.pcfrom%2]){

                            setNotTransformedFlag(lastMove.pcfrom);

                        }

                    }

                }

                

                searchAllAvailableMoves();

            }

        }

    }


}



class ChessGame extends Vector<ChessMove>{

    

    /*static{//helper for creating below :byte pcinitialpos64[]

        StringTokenizer stok=new StringTokenizer(officialInitialPositionsString,",");

        int i=0;

        String out="public byte pcinitialpos64[]= {";

        while(stok.hasMoreTokens()){

            String s=stok.nextToken();

            int pos=parsePos64(s);

            //System.out.println(i+":"+pos);

            out+=pos+",";

            ++i;

        }

        out=out.substring(0,out.length()-1);

        out+="};";

        System.out.println(out);

    }*/


    

    /**

     * The order id is

     * wk(0),bk(1),wq,bq (kings and queens)

     * wkb,bkb,wqb,bqb (bishops)

     * wkh,bkh,wqh,bqh (horses)

     * wkr(12),bkr(13),wqr(14),bqr(15) (rooks)

     * 

     * and 16 pawns accordinglly 

     * wkp,bkp (white king pawn , black king pawn etc)

     * ,....,bqrp

     */

    public static final byte pcinitialpos64[]= {32,39,24,31,40,47,16,23,48,55,8,15,56,63,0,7,33,38,25,30,41,46,17,22,49,54,9,14,57,62,1,6};

    

    

    /**

     * This array is not for copying it HERE on reset games

     * Is just for future streaming

     * in case we want the swing application to have other types of chess games

     * like random initial positions etc.

     * 

     * 

     */

    protected byte[] pos64Initial=new byte[32];

    public int getInitialColFor(int code32){

        return pos64Initial[code32]/8;

    }

    public int getInitialRowFor(int code32){

        return pos64Initial[code32]%8;

    }

    

    /**

     * Creates an empty Game with the official initial positions for the 32 chess pieces

     */

    public ChessGame() {

        int i=0;

        while(i<pos64Initial.length){

            pos64Initial[i]=pcinitialpos64[i];

            ++i;

        }

    }

    public ChessGame(ChessGame toCopyFrom) {

        int i=0;

        while(i<pos64Initial.length){

            pos64Initial[i]=toCopyFrom.pos64Initial[i];

            ++i;

        }

        i=0;

        int l=toCopyFrom.size();

        while(i<l){

            add(new ChessMove(toCopyFrom.get(i)));

            ++i;

        }

    }

    

    

    

    public boolean hasBeenMoved(int code32){

        //System.out.println("processor 'Heavy' hasBeenMoved for "+code32);

        int i=0,l=size();

        while(i<l){

            if(get(i).pcfrom==code32){

                return true;

            }

            ++i;

        }

        return false;

    }

    

}



class ChessMove {

        

    /**

     * Unicode white and black pieces names 

     */

    public static final char uwk=9812;

    public static final char uwq=9813;

    public static final char uwr=9814;

    public static final char uwb=9815;

    public static final char uwh=9816;

    public static final char uwp=9817;

    public static final char ubk=9818;

    public static final char ubq=9819;

    public static final char ubr=9820;

    public static final char ubb=9821;

    public static final char ubh=9822;

    public static final char ubp=9823;

    

    public static final char u12[]={uwk,ubk,uwq,ubq,uwb,ubb,uwh,ubh,uwr,ubr,uwp,ubp};

    public static int getIndexTo12Pieces(char ch){

        int i=0;

        while(i<u12.length){

            if(ch==u12[i]){

                return i;

            }

            ++i;

        }

        return -1;

    }

    

    

    public static char umap32[]=new char [32];

    static{

        umap32[0]=uwk;

        umap32[1]=ubk;

        umap32[2]=uwq;

        umap32[3]=ubq;

        

        umap32[4]=uwb;

        umap32[5]=ubb;

        umap32[6]=uwb;

        umap32[7]=ubb;

        

        umap32[8]=uwh;

        umap32[9]=ubh;

        umap32[10]=uwh;

        umap32[11]=ubh;

        

        umap32[12]=uwr;

        umap32[13]=ubr;

        umap32[14]=uwr;

        umap32[15]=ubr;

        

        int i=16;

        while(i<32){

            umap32[i]=uwp;

            ++i;

            umap32[i]=ubp;

            ++i;

        }

        

    };

    /**

     * trying to minimise ram even if there is better solution

     */

    byte colfrom,rowfrom,pcfrom,showasfrom,colto,rowto,pcto,showasto;

    public ChessMove() {

    }


    public ChessMove(int colfrom, int rowfrom, int pcfrom,  int colto, int rowto) {

        this(colfrom, rowfrom, pcfrom,pcfrom, colto, rowto, -1,-1);

    }

    public ChessMove(int colfrom, int rowfrom, int pcfrom,  int colto, int rowto, int pcto) {

        this(colfrom, rowfrom, pcfrom,pcfrom, colto, rowto, pcto,pcto);

    }

    public ChessMove(int colfrom, int rowfrom, int pcfrom, int showasfrom, int colto, int rowto, int pcto, int showasto) {

        this.colfrom = (byte)colfrom;

        this.rowfrom = (byte)rowfrom;

        this.pcfrom = (byte)pcfrom;

        this.showasfrom = (byte)showasfrom;

        this.colto = (byte)colto;

        this.rowto = (byte)rowto;

        this.pcto = (byte)pcto;

        this.showasto = (byte)showasto;

        

        //System.out.println("created "+colfrom+","+rowfrom+","+pcfrom+","+showasfrom+","+colto+","+rowto+","+pcto+","+showasto);

    }

    public ChessMove(ChessMove toCopyFrom){

        this(toCopyFrom.colfrom, toCopyFrom.rowfrom, toCopyFrom.pcfrom, toCopyFrom.showasfrom, toCopyFrom.colto, toCopyFrom.rowto, toCopyFrom.pcto, toCopyFrom.showasto);

    }

    

    /*

    @Override

    public int hashCode() {

        int hash = 5;

        hash = 23 * hash + this.colfrom;

        hash = 23 * hash + this.rowfrom;

        hash = 23 * hash + this.pcfrom;

        hash = 23 * hash + this.showasfrom;

        hash = 23 * hash + this.colto;

        hash = 23 * hash + this.rowto;

        hash = 23 * hash + this.pcto;

        hash = 23 * hash + this.showasto;

        return hash;

    }*/


    @Override

    public boolean equals(Object obj) {

        if (this == obj) {

            return true;

        }

        if (obj == null) {

            return false;

        }

        if (getClass() != obj.getClass()) {

            return false;

        }

        final ChessMove other = (ChessMove) obj;

        

        if (this.colfrom != other.colfrom) {

            return false;

        }

        if (this.rowfrom != other.rowfrom) {

            return false;

        }

        if (this.pcfrom != other.pcfrom) {

            return false;

        }

        if (this.showasfrom != other.showasfrom) {

            return false;

        }

        if (this.colto != other.colto) {

            return false;

        }

        if (this.rowto != other.rowto) {

            return false;

        }

        if (this.pcto != other.pcto) {

            return false;

        }

        if (this.showasto != other.showasto) {

            return false;

        }

        return true;

    }


    

    


    

    

    public String toString(){

        

        String out=umap32[showasfrom]+""+ChessBoard.square(colfrom, rowfrom);

        if(pcto>-1){

            out+="x";

            if(ChessBoard.isValidSquare(colto, rowto)){

                out+=ChessBoard.square(colto, rowto);

            }

            else{

                out+=" ? ";

            }

            out+=umap32[showasto];

        }

        else{

            if(ChessBoard.isValidSquare(colto, rowto)){

                out+=" "+ChessBoard.square(colto, rowto);

            }

            else{

                out+="_Out";//in case of free type

            }

        }

        

        return out;

    }

    

}


class TransferableImage implements Transferable {


    Image i;


    public TransferableImage( Image i ) {

        this.i = i;

    }


    public Object getTransferData( DataFlavor flavor )

    throws UnsupportedFlavorException, IOException {

        if ( flavor.equals( DataFlavor.imageFlavor ) && i != null ) {

            return i;

        }

        else {

            throw new UnsupportedFlavorException( flavor );

        }

    }


    public DataFlavor[] getTransferDataFlavors() {

        DataFlavor[] flavors = new DataFlavor[ 1 ];

        flavors[ 0 ] = DataFlavor.imageFlavor;

        return flavors;

    }


    public boolean isDataFlavorSupported( DataFlavor flavor ) {

        DataFlavor[] flavors = getTransferDataFlavors();

        for ( int i = 0; i < flavors.length; i++ ) {

            if ( flavor.equals( flavors[ i ] ) ) {

                return true;

            }

        }


        return false;

    }

}


class JChessPanel extends JPanel implements ComponentListener

        ,KeyListener,MouseListener,MouseMotionListener,ClipboardOwner


{

    public static void main(String[] args) {

        JChessGame.main(args);

    }

    

    

    

    ChessBoard game;

    final int pieceFontMinSize=14;

    final int pieceFontDefaultSize=40;

    int pieceFontSize=pieceFontDefaultSize;

    int boardW=pieceFontSize*8;

    

    Vector<Color>palette=new Vector<>();

    String []paletteNames={"lett","bl sq","wh sq","wh pl","bl pl","mat","w_sax","b_sax"};

    JList<String> jlPalette=new JList<>(paletteNames);

    JPanel jpPalette=new JPanel(new BorderLayout());

    JPanel jpr=new JPanel(new BorderLayout());

    JSlider jslr=new JSlider(0,255,0);

    //JSpinner jspr=new JSpinner(new SpinnerNumberModel(0, 0, 255, 1));

    JLabel jlr=new JLabel("R");

    JPanel jpg=new JPanel(new BorderLayout());

    JSlider jslg=new JSlider(0,255,0);

    //JSpinner jspg=new JSpinner(new SpinnerNumberModel(0, 0, 255, 1));

    JLabel jlg=new JLabel("G");

    JPanel jpb=new JPanel(new BorderLayout());

    JSlider jslb=new JSlider(0,255,0);

    //JSpinner jspb=new JSpinner(new SpinnerNumberModel(0, 0, 255, 1));

    JLabel jlb=new JLabel("B");

    JPanel jpa=new JPanel(new BorderLayout());

    JSlider jsla=new JSlider(0,255,0);

    //JSpinner jspa=new JSpinner(new SpinnerNumberModel(0, 0, 255, 1));

    JLabel jla=new JLabel("A");

    JPanel jprgba=new JPanel(new GridLayout(4,1));

    

    

    void setPaletteDefaults(){

        int cs=palette.size();

        palette.add(Color.yellow);//none

        palette.add(Color.gray);//black squares

        palette.add(Color.lightGray);//white squares

        palette.add(Color.white);//white pieces

        palette.add(Color.black);//black pieces

        palette.add(new Color(255,0,0,50));//mat

        palette.add(new Color(255,255,255,50));//whites so sax

        palette.add(new Color(0,0,0,30));//blacks do sax

        int i=0;

        while(i<cs){

            palette.remove(0);

            ++i;

        }

        repaint();

        jlPalette.setSelectedIndex(jlPalette.getSelectedIndex());

        colorSelected();

    }

    void createPalette(){

        

        setPaletteDefaults();

        jpr.add(BorderLayout.CENTER,jslr);

        jpr.add(BorderLayout.WEST,jlr);

        jlr.setForeground(Color.red);

        jprgba.add(jpr);

        jpg.add(BorderLayout.CENTER,jslg);

        jpg.add(BorderLayout.WEST,jlg);

        jlg.setForeground(Color.green);

        jprgba.add(jpg);

        jpb.add(BorderLayout.CENTER,jslb);

        jpb.add(BorderLayout.WEST,jlb);

        jlb.setForeground(Color.blue);

        jprgba.add(jpb);

        jpa.add(BorderLayout.CENTER,jsla);

        jpa.add(BorderLayout.WEST,jla);

        jprgba.add(jpa);

        

        jpPalette.add(BorderLayout.CENTER,new JScrollPane(jlPalette));

        jpPalette.add(BorderLayout.SOUTH,jprgba);

        

        jlPalette.addListSelectionListener(e->colorSelected());

        jslr.addChangeListener(e->colorChanging());

        jslg.addChangeListener(e->colorChanging());

        jslb.addChangeListener(e->colorChanging());

        jsla.addChangeListener(e->colorChanging());

        jlPalette.setSelectedIndex(4);

    }

    private boolean adjustingSpinners;

    void colorSelected(){

        int ind=jlPalette.getSelectedIndex();

        if(ind>-1 && ind<palette.size()){

            adjustingSpinners=true;

            Color c=palette.get(ind);

            jslr.setValue(c.getRed());

            jslg.setValue(c.getGreen());

            jslb.setValue(c.getBlue());

            jsla.setValue(c.getAlpha());

            adjustingSpinners=false;

        }

    }

    void colorChanging(){

        if(!adjustingSpinners){

            int ind=jlPalette.getSelectedIndex();

            if(ind>-1 && ind<palette.size()){

                Color c=palette.get(ind);

                Color cn=new Color((int)jslr.getValue(),(int)jslg.getValue(),(int)jslb.getValue(),(int)jsla.getValue());

                palette.insertElementAt(cn, ind);

                palette.remove(ind+1);

                jlr.setToolTipText(""+cn.getRed());

                jlg.setToolTipText(""+cn.getGreen());

                jlb.setToolTipText(""+cn.getBlue());

                jla.setToolTipText(""+cn.getAlpha());

                repaint();

            }

        }

    }

    Color cDef(){

        return palette.get(0);

    }

    Color cSq(int i,int j){

        return palette.get(1+((i+j)%2));

    }

    Color cPc(int code32){

        return palette.get(3+(code32%2));

    }

    Color cSaxTo(int player){

        ++player;

        player%=2;

        return palette.get(6+player);

    }

    Color cMat(){

        return palette.get(5);

    }

    

    Font fdef;

    Font fpc=new Font("Dialog",Font.BOLD, pieceFontDefaultSize);

    Font fSaxMat=new Font("Dialog",Font.PLAIN,100);

    

    

    

    static AbstractButton createAddEastJtb(JPanel jppar,String text,Boolean sel,Color fore,String tooltip,ActionListener al){

        AbstractButton aa=null;

        if(sel!=null){

            aa=new JToggleButton(text,sel);

        }

        else{

            aa=new JButton(text);

        }

        aa.setMargin(JChessGame.zeroInsets);

        if(fore!=null){

            aa.setForeground(fore);

        }

        aa.setToolTipText(tooltip);

        if(al!=null){

            aa.addActionListener(al);

        }

        jppar.add(aa);

        return aa;

    }

    


    boolean informUserThoseActionsRequireFreeType=true;

    void checkInformUserThoseActionsRequireFreeType(){

        if(informUserThoseActionsRequireFreeType){

            JOptionPane.showMessageDialog(this, "Those actions requiring FREE game mode\n\n   i will not say this again...but just to know each other !");

        }

        informUserThoseActionsRequireFreeType=false;

    }

    

    public JPanel jpDrawOptions=new JPanel(new GridLayout(12,1));

    public JToggleButton jtbFree=(JToggleButton)createAddEastJtb(jpDrawOptions,"free",false,Color.RED,"Free moves",null);

    public JButton jbUndo=(JButton)createAddEastJtb(jpDrawOptions,"⎌",null,Color.RED,"Undo Previus Move....not tested very well yet...but feel free to cheat at online games !",null);

    public JToggleButton jchReversingOnMoves=(JToggleButton)createAddEastJtb(jpDrawOptions,"a_r",false,Color.BLACK,"Auto_Reverse. The one who plays always have its piece on bottom",null);

    public JToggleButton jrbReversingCols=(JToggleButton)createAddEastJtb(jpDrawOptions,"w_d",true,Color.BLACK,"Manual_Reverse...lets say you want the blacks down on starting",null);

    public JToggleButton jrbShowLetters=(JToggleButton)createAddEastJtb(jpDrawOptions,"lett",false,Color.BLACK,"Showing squares names (letters)",null);

    public JToggleButton jrbShowAvailableMoves=(JToggleButton)createAddEastJtb(jpDrawOptions,"shm",true,Color.MAGENTA,"Showing available moves of the piece clicking",null);

    public JToggleButton jrbShowTargetedByEnemyOfAvailableMoves=(JToggleButton)createAddEastJtb(jpDrawOptions,"!",true,Color.MAGENTA,"For all available moves shows the suares(pieces) target by",null);

    public JToggleButton jtbShowTargetedByEnemy=(JToggleButton)createAddEastJtb(jpDrawOptions,"sht",true,Color.YELLOW,"Showing from where it is being target the clicking square.Hold Shift (as you click) to add more squares",null);

    public JToggleButton jrbDrag=(JToggleButton)createAddEastJtb(jpDrawOptions,"drag",true,Color.BLACK,"Draging or not the clicking piece",null);

    public JButton jbScreenshot=(JButton)createAddEastJtb(jpDrawOptions,"scr",null,Color.BLACK,"Take a screenshoot of chessboard,and try to:copy to clipboard(so to be paste it),save on your defaultFolder a same name file,opens it with mspaint(if windows!)",null);

    public JToggleButton jrbKeysEnabled=(JToggleButton)createAddEastJtb(jpDrawOptions,"keys",true,Color.BLACK,"Enables moving with ARROWS|{WASD} and ENTER from keyboard for second player in same screen",null);

    public JButton jbDefColors=(JButton)createAddEastJtb(jpDrawOptions,"*col",null,Color.BLACK,"restore default colors",null);



    JPanel jpWhites=new JPanel(new GridLayout(6,1));

    JPanel jpBlacks=new JPanel(new GridLayout(6,1));

    JPanel jpPutinOnFree=new JPanel(new BorderLayout());

    ActionListener alHackingTooltip=new ActionListener() {

        @Override

        public void actionPerformed(ActionEvent e) {

            String ttt=((AbstractButton)e.getSource()).getToolTipText();

            if(ttt!=null){

                int lind=ttt.lastIndexOf(' ');

                if(lind>-1){

                    String sub=ttt.substring(lind);

                    try{

                        int pc12=Integer.parseInt(sub.trim());

                        if(!game.isGameFree()){

                            jtbFree.doClick();

                            checkInformUserThoseActionsRequireFreeType();

                        }

                        int pc32=game.putOnBoardSomeOfThe12TypesOfPieces(pc12);

                        if(pc32<0){

                            JOptionPane.showMessageDialog(jpPutinOnFree, "This type of piece is/are already on chessboard");

                        }

                        repaint();

                    }catch(NumberFormatException nfe){

                        System.out.println("someone updated the code forgotten to update here "+nfe);

                    }

                }

            }

        }

    };

    //if you change tooltips of those buttons,,,find onother way to act

    public JButton jbwk=(JButton)createAddEastJtb(jpWhites,ChessMove.uwk+"",null,Color.GRAY,"Puts some white king inside , 0",alHackingTooltip);

    public JButton jbbk=(JButton)createAddEastJtb(jpBlacks,ChessMove.ubk+"",null,Color.BLACK,"Puts some black king inside , 1",alHackingTooltip);

    public JButton jbwq=(JButton)createAddEastJtb(jpWhites,ChessMove.uwq+"",null,Color.GRAY,"Puts some white queen inside , 2",alHackingTooltip);

    public JButton jbbq=(JButton)createAddEastJtb(jpBlacks,ChessMove.ubq+"",null,Color.BLACK,"Puts some black queen inside , 3",alHackingTooltip);

    public JButton jbwb=(JButton)createAddEastJtb(jpWhites,ChessMove.uwb+"",null,Color.GRAY,"Puts some white bishop inside , 4",alHackingTooltip);

    public JButton jbbb=(JButton)createAddEastJtb(jpBlacks,ChessMove.ubb+"",null,Color.BLACK,"Puts some black bishop inside , 5",alHackingTooltip);

    public JButton jbwh=(JButton)createAddEastJtb(jpWhites,ChessMove.uwh+"",null,Color.GRAY,"Puts some white horse inside , 6",alHackingTooltip);

    public JButton jbbh=(JButton)createAddEastJtb(jpBlacks,ChessMove.ubh+"",null,Color.BLACK,"Puts some black horse inside , 7",alHackingTooltip);

    public JButton jbwr=(JButton)createAddEastJtb(jpWhites,ChessMove.uwr+"",null,Color.GRAY,"Puts some white rook inside , 8",alHackingTooltip);

    public JButton jbbr=(JButton)createAddEastJtb(jpBlacks,ChessMove.ubr+"",null,Color.BLACK,"Puts some black rook inside , 9",alHackingTooltip);

    public JButton jbwp=(JButton)createAddEastJtb(jpWhites,ChessMove.uwp+"",null,Color.GRAY,"Puts some white pawn inside , 10",alHackingTooltip);

    public JButton jbbp=(JButton)createAddEastJtb(jpBlacks,ChessMove.ubp+"",null,Color.BLACK,"Puts some black pawn inside , 11",alHackingTooltip);

    

    ActionListener alRepainter=new ActionListener() {

        @Override

        public void actionPerformed(ActionEvent e) {

            repaint();

        }

    };

    

    JPanel jpPieceStateOption=new JPanel(new GridLayout(2,6));

    public JButton jbAllPawnsOut=(JButton)createAddEastJtb(jpPieceStateOption,"-",null,Color.BLACK,"All Pawns out to be able to experiment.Check the free option if you want to adjust",alRepainter);

    public JButton jbMatQueen=(JButton)createAddEastJtb(jpPieceStateOption,"q",null,Color.BLACK,"Learn to MAT with one queen",alRepainter);

    public JButton jbMatRook=(JButton)createAddEastJtb(jpPieceStateOption,"r",null,Color.BLACK,"Learn to MAT with one rook",alRepainter);

    public JButton jbMatBishops=(JButton)createAddEastJtb(jpPieceStateOption,"b",null,Color.BLACK,"Learn to MAT with two bishops",alRepainter);

    public JButton jbMatHorseBishop=(JButton)createAddEastJtb(jpPieceStateOption,"h",null,Color.BLACK,"Learn to MAT with 1?...bishop and horse",alRepainter);

    public JButton jbRandomPos=(JButton)createAddEastJtb(jpPieceStateOption,"!",null,Color.RED,"Random positions.White plays .(testing)",alRepainter);

    

    public JButton jbAllNotPawnsOut=(JButton)createAddEastJtb(jpPieceStateOption,"+",null,Color.BLACK,"Only pawns in",alRepainter);

    public JButton jbAllQ=(JButton)createAddEastJtb(jpPieceStateOption,"Q",null,Color.BLACK,"2 queens",alRepainter);

    public JButton jbMatRooks=(JButton)createAddEastJtb(jpPieceStateOption,"R",null,Color.BLACK,"Learn to MAT with 2 rooks",alRepainter);

    public JButton jbB=(JButton)createAddEastJtb(jpPieceStateOption,"B",null,Color.BLACK,"not yet ready",alRepainter);

    public JButton jbH=(JButton)createAddEastJtb(jpPieceStateOption,"H",null,Color.BLACK,"not yet ready",alRepainter);

    public JButton jbdontknow=(JButton)createAddEastJtb(jpPieceStateOption,"~",null,Color.BLACK,"not yet ready",alRepainter);




    public JChessPanel(){

        

        super(new BorderLayout());

        

        fdef=getFont();

        createPalette();

        

        game=new ChessBoard();

        game.resetGame();

        addComponentListener(this);

        addMouseListener(this);

        addMouseMotionListener(this);

        addKeyListener(this);

        

        

        

        jpPutinOnFree.add(BorderLayout.NORTH,jpWhites);

        jpPutinOnFree.add(BorderLayout.SOUTH,jpBlacks);

        

        

        jtbFree.addActionListener(e->game.setGameFree(jtbFree.isSelected()));

        jbUndo.addActionListener(e->jbUndo());

        jrbReversingCols.addActionListener(e->jrbReversingCols());

        jrbShowLetters.addActionListener(e->repaint());

        jrbDrag.addActionListener(e->jrbDragPressed());

        jbScreenshot.addActionListener(e->takeScreenShoot());

        jbDefColors.addActionListener(e->setPaletteDefaults());

        jtbShowTargetedByEnemy.addActionListener(e->jtbShowTargetedByEnemy());

        jrbKeysEnabled.addActionListener(e->jrbKeysEnabled());

        

        

        

        

        

        jbAllPawnsOut.addActionListener(e->game.setAllPawnsOut());

        jbMatQueen.addActionListener(e->game.setPosMatQueen());

        jbMatRook.addActionListener(e->game.setPosMatRook());

        jbMatBishops.addActionListener(e->game.setPosMatBishops());

        jbMatHorseBishop.addActionListener(e->game.setPosMatHorseAndBishop());

        jbRandomPos.addActionListener(e->setPosRandom());

        

        jbAllNotPawnsOut.addActionListener(e->game.setAllNotPawnsOut());

        jbAllQ.addActionListener(e->game.setPosMatQueens());

        jbMatRooks.addActionListener(e->game.setPosMatRooks());

        

    }

    

    void jrbKeysEnabled(){

        if(jrbKeysEnabled.isSelected()){

            addKeyListener(this);

            requestFocusInWindow();

        }

        else{

            removeKeyListener(this);

        }

        repaint();

    }

    void jrbReversingCols(){

        keyp[2].x=keyp[0].x;

        keyp[2].y=keyp[0].y;

        reversePoint(keyp[2]);

        keyp[3].x=keyp[1].x;

        keyp[3].y=keyp[1].y;

        reversePoint(keyp[3]);

        repaint();

        requestFocusInWindow();

    }

    void jtbShowTargetedByEnemy(){

        jrbShowTargetedByEnemyOfAvailableMoves.setEnabled(jtbShowTargetedByEnemy.isSelected());

    }


    void jbUndo(){

        if(game.movesPlayed.size()>0){

            boolean changedModeToFree=false;

            if(!game.isGameFree()){

                game.setGameFree();

                changedModeToFree=true;

            }

            game.undo();

            movePlayed(null);

            if(changedModeToFree){

                game.setGameNormal();

            }

        }

    }

    void setPosRandom(){

        game.setPosRandom();

        movePlayed(null);

    }


    public void resetGame(){

        game.resetGame();


        repaint();

    }


    public void movePlayed(ChessMove cm) {

        if(jchReversingOnMoves.isSelected()){

            //jrbReversingCols.setSelected(!jrbReversingCols.isSelected());

            jrbReversingCols.doClick();

        }

        repaint();

    }

    public void paintComponent(Graphics g){

        super.paintComponent(g);

        repaintingChess((Graphics2D)g);

    }

    

    void reversePoint(Point p){

        if(jrbReversingCols.isSelected()){

            p.y=7-p.y;

        }

        else{

            p.x=7-p.x;

        }

    }

    

    


    Vector<Byte>piecesDrawingAvailableMoves=new Vector();

    boolean squaresShowingTargetBy[][]=new boolean [8][8];

    void clearsquaresShowingTargetBy(){

        int i=0,j;

        while(i<8){

            j=0;

            while(j<8){

                squaresShowingTargetBy[i][j]=false;

                ++j;

            }

            ++i;

        }

    }

    private Point drp=new Point();

    private Point rev=new Point();

    private FontMetrics fm=null;

    private int strYdif;

    BasicStroke strokeForMoves=new BasicStroke(2);

    BasicStroke stroke1=new BasicStroke(1);

    Graphics2D gcurr;

    public void repaintingChess(Graphics2D g){

        gcurr=g;

        int i,j,l,p,x,y,pos,col,row;

        boolean paintingAllLetters=jrbShowLetters.isSelected();

        

        g.setFont(fdef);

        g.drawString("Moves", pieceFontSize*8+2,pieceFontSize*4-fdef.getSize());

        g.drawString(game.totalAvailableMoves[0]+","+game.totalAvailableMoves[1], pieceFontSize*8+2,pieceFontSize*4);

        g.drawString("Nailed", pieceFontSize*8+2,pieceFontSize*5-fdef.getSize());

        g.drawString(game.nailedPieces[0]+","+game.nailedPieces[1], pieceFontSize*8+2,pieceFontSize*5);

        

        i=0;

        

        while(i<8){

            j=0;

            while(j<8){

                g.setColor(cSq(i, j));

                drp.x=i;

                drp.y=j;

                reversePoint(drp);

                x=drp.x*pieceFontSize;

                y=drp.y*pieceFontSize;

                g.fillRect(x,y, pieceFontSize, pieceFontSize);

                if(paintingAllLetters){

                    g.setColor(cDef());

                    g.drawString(ChessBoard.square(i,j), x, y+fdef.getSize());

                }

                ++j;

            }

            ++i;

        }

        g.setFont(fpc);

        if(fm==null){

            fm=g.getFontMetrics();

            strYdif=pieceFontSize-fm.getDescent()/2;

        }

        

        i=0;

        while(i<32){

            if(game.isInFlag(i)){

                g.setColor(cPc(i));

                if(i!=pcfrom || !dragSelectedPiece){

                    game.getPoint(i, drp);

                    reversePoint(drp);

                    x=drp.x*pieceFontSize;

                    y=drp.y*pieceFontSize;

                    y+=strYdif;

                    g.drawString(game.getPieceString(i), x, y);

                }

                else{

                    x=pdra.x;

                    y=pdra.y;

                    y+=strYdif;

                    g.drawString(game.getPieceString(pcfrom), x-pdratr.x, y-pdratr.y);

                }

            }

            ++i;

        }

        

        if(jrbShowAvailableMoves.isSelected()){

            drawAvailableMovesOfCurrentPressed();

        }

        if(jtbShowTargetedByEnemy.isSelected()){

            drawMarkedTargetedBySquares();

        }

        

        if(isSax()){

            g.setFont(fSaxMat);

            if(!isMat()){

                g.setColor(cSaxTo(game.whoPlays()));

                g.drawString("SAX",0,(int)(pieceFontSize*3.5+fSaxMat.getSize()/2));

            }

            else{

                //g.drawString("roua &",0,pieceFontSize*3);

                int h2=g.getFontMetrics().getAscent();

                h2/=2;

                g.setColor(cMat());

                g.drawString("mat!!!",0,(int)(pieceFontSize*3.1+h2));

                g.setStroke(strokeForMoves);

                g.drawLine(0,0,8*pieceFontSize,8*pieceFontSize);

                g.drawLine(0,8*pieceFontSize,8*pieceFontSize,0);

            }  

        }

        else if(game.isPat()){

            g.setFont(fpc);

            g.setColor(cSaxTo(game.whoPlays()));

            g.drawString(game.getPatString(),0,(int)(pieceFontSize*3+fSaxMat.getSize()/2));

        }   

        

        if(jrbKeysEnabled.isSelected()){

            drawKeyPressed();

        }

        

    }

    boolean isSax(){

        //return Math.random()<0.2;

        return game.isSax();

    }

    boolean isMat(){

        //return Math.random()<0.5;

        return game.isMat();

    }

    

    

    void drawAvailableMovesOfCurrentPressed(){

        int i=0,p,j;

        int l=piecesDrawingAvailableMoves.size();

        //System.out.println(l+" pieces we draw available moves");

        gcurr.setStroke(strokeForMoves);

        while(i<l){

            p=piecesDrawingAvailableMoves.get(i);

            int avms=game.getAvailableMoveCount(p);

            j=0;

            while(j<avms){

                game.getAvailableMove(p,j,drp);

                gcurr.setColor(Color.green);

                if(game.getPieceAt(drp)>-1){

                    gcurr.setColor(Color.red);

                }

                else if(p>15 && drp.x!=game.getColOf(p)&& game.isNotTransformedFlag(p)){

                    //System.out.println("an pasan movement .so make it red");

                    gcurr.setColor(Color.red);

                }

                reversePoint(drp);

                gcurr.drawOval(drp.x*pieceFontSize,drp.y*pieceFontSize, pieceFontSize, pieceFontSize);

                ++j;

            }

            ++i;

        }

        

    }

    

    void drawMarkedTargetedBySquares(){

        

        gcurr.setStroke(stroke1);

        Vector<Byte> v;

        int i=0,j,p;

        int vi,vl;

        while(i<8){

            j=0;

            while(j<8){

                if(squaresShowingTargetBy[i][j]){

                    rev.setLocation(i,j);

                    reversePoint(rev);

                    

                    v=game.sqTargetedBy[i][j][0];

                    gcurr.setColor(Color.WHITE);

                    vl=v.size();

                    vi=0;

                    while(vi<vl){

                        p=v.get(vi);

                        game.getPoint(p, drp);

                        reversePoint(drp);

                        gcurr.drawLine(drp.x*pieceFontSize+pieceFontSize/2, drp.y*pieceFontSize+pieceFontSize/2,

                                rev.x*pieceFontSize+pieceFontSize/2, rev.y*pieceFontSize+pieceFontSize/2);

                        

                        ++vi;

                    }

                    

                    

                    v=game.sqTargetedBy[i][j][1];

                    gcurr.setColor(Color.BLACK);

                    vl=v.size();

                    vi=0;

                    while(vi<vl){

                        p=v.get(vi);

                        game.getPoint(p, drp);

                        reversePoint(drp);

                        gcurr.drawLine(drp.x*pieceFontSize+pieceFontSize/2, drp.y*pieceFontSize+pieceFontSize/2,

                                rev.x*pieceFontSize+pieceFontSize/2, rev.y*pieceFontSize+pieceFontSize/2);

                        

                        ++vi;

                    }

                }

                ++j;

            }

            ++i;

        }

        

    }


   

    void setPieceFontSize(int newPieceFontSize){

        if(newPieceFontSize!=pieceFontSize){

            pieceFontSize=newPieceFontSize;

            boardW=pieceFontSize*8;

            fpc=new Font(fpc.getFontName(),fpc.getStyle(),pieceFontSize);

            fSaxMat=new Font(fSaxMat.getFontName(),fSaxMat.getStyle(),pieceFontSize*4);

            fm=null;

            repaint();

            //System.out.println("font size reseted");

        }

        

    }

    void resizedWithMin(int minDimension){

        if(minDimension>=pieceFontMinSize && minDimension!=pieceFontSize){

            setPieceFontSize(minDimension/8);

        }

    }

    

    

    

    

    Point ppr=new Point();

    Point pprtr=new Point();

    byte pcfrom;

    boolean pressing;

    boolean pressingOnValid;

    @Override

    public void mousePressed(MouseEvent e) {

        requestFocusInWindow();

        ppr.x=e.getX();

        ppr.y=e.getY();

        pdratr.x=e.getX()%pieceFontSize;

        pdratr.y=e.getY()%pieceFontSize;

        

        keycurr=0;

        

        pressing(ppr.x/pieceFontSize,ppr.y/pieceFontSize);

    }

    void pressing(int someCol,int someRow){

        pressing=true;

        piecesDrawingAvailableMoves.clear();

        pprtr.x=someCol;

        pprtr.y=someRow;

        reversePoint(pprtr);

        if(ChessBoard.isValidSquare(pprtr)){

            pressingOnValid=true;

            

            squaresShowingTargetBy[pprtr.x][pprtr.y]=true;


            pcfrom=(byte)game.getPieceAt(pprtr);

            if(pcfrom>-1){

                if(!piecesDrawingAvailableMoves.contains(pcfrom)){

                    piecesDrawingAvailableMoves.add((byte)pcfrom);

                }

                if(jrbShowTargetedByEnemyOfAvailableMoves.isSelected()){

                    int l=game.getAvailableMoveCount(pcfrom);

                    int i=0,pos;

                    while(i<l){

                        pos=(byte)game.getAvailableMove(pcfrom, i); 

                        squaresShowingTargetBy[pos/8][pos%8]=true;

                        ++i;

                    }

                }

            }

            //System.out.println("Pressing at "+ChessGame.square(pprtr.x,pprtr.y));

        }

        else{

            pcfrom=-1;

            System.out.println("pressing out");

        }

        repaint();

    }


    Point pre=new Point();

    Point pretr=new Point();

    @Override

    public void mouseReleased(MouseEvent e) {

        mouseReleaseAt(e.getX(), e.getY(),e.isShiftDown());

    }

    void mouseReleaseAt(int sx,int sy,boolean shift){

        dragSelectedPiece=false;

        pre.x=sx;

        pre.y=sy;

        pretr.x=pre.x/pieceFontSize;

        pretr.y=pre.y/pieceFontSize;

        reversePoint(pretr);

        if(!shift){

            clearsquaresShowingTargetBy();

        }

        

        mouseReleased();

        

    }

    void mouseReleased(){

        if(ChessBoard.isValidSquare(pprtr.x,pprtr.y)){

            piecesDrawingAvailableMoves.clear();

            if(pprtr.x!=pretr.x || pprtr.y!=pretr.y){

                ChessMove cm=game.applyChessMove(pprtr.x,pprtr.y,pretr.x,pretr.y,this);

                if(cm!=null){

                    movePlayed(cm);

                }

                else{

                    JChessGame.beep();

                }

            }

        }

        pcfrom=-1;

        pressing=false;

        pressingOnValid=false;

        repaint();

    }



    @Override

    public void mouseEntered(MouseEvent e) {

    }


    @Override

    public void mouseExited(MouseEvent e) {

    }


    void jrbDragPressed(){

        if(jrbDrag.isSelected()){

            addMouseMotionListener(this);

        }

        else{

            removeMouseMotionListener(this);

            dragSelectedPiece=false;

        }

        

    }

    Point pdra=new Point();

    Point pdratr=new Point();

    boolean dragSelectedPiece=false;

    @Override

    public void mouseDragged(MouseEvent e) {

        pdra.x=e.getX();

        pdra.y=e.getY();

        dragSelectedPiece=true;

        repaint();

    }


    @Override

    public void mouseMoved(MouseEvent e) {

    }


    

    

    @Override

    public void keyTyped(KeyEvent e) {

    }

    

    

    Point keyp[]={new Point(4,5),new Point(4,5),new Point(4,2),new Point(4,2)};

    int keycurr=0;

    void drawKeyPressed(){

        gcurr.setColor(Color.black);

        int x=keyp[2].x*pieceFontSize;

        int y=keyp[2].y*pieceFontSize;

        gcurr.drawRect(x,y, pieceFontSize, pieceFontSize);

        if(keycurr>0){

            gcurr.setStroke(strokeForMoves);

            x=keyp[3].x*pieceFontSize;

            y=keyp[3].y*pieceFontSize;

            gcurr.drawRect(x,y, pieceFontSize, pieceFontSize);

        }

        

    }

    

    void resetKeyPressedReversed(int difx,int dify){

        if(!jrbReversingCols.isSelected()){

            difx=-difx;

            dify=-dify;

        }

        difx+=keyp[keycurr].x;

        dify+=keyp[keycurr].y;

        if(ChessBoard.isValidSquare(difx, dify)){

            keyp[keycurr].x=difx;

            keyp[keycurr].y=dify;

            keyp[keycurr+2].x=keyp[keycurr].x;

            keyp[keycurr+2].y=keyp[keycurr].y;

            reversePoint(keyp[keycurr+2]);


            if(keycurr==0){

                piecesDrawingAvailableMoves.clear();

                clearsquaresShowingTargetBy();

                pressing(keyp[keycurr+2].x, keyp[keycurr+2].y);

            }

            repaint();

        }

    }

    @Override

    public void keyPressed(KeyEvent e) {

        if(e.getKeyCode()==KeyEvent.VK_RIGHT || e.getKeyCode()==KeyEvent.VK_D){

            resetKeyPressedReversed(1,0);

        }

        else if(e.getKeyCode()==KeyEvent.VK_LEFT || e.getKeyCode()==KeyEvent.VK_A){

            resetKeyPressedReversed(-1,0);

        }

        else if(e.getKeyCode()==KeyEvent.VK_UP || e.getKeyCode()==KeyEvent.VK_W){

            resetKeyPressedReversed(0,1);

        }

        else if(e.getKeyCode()==KeyEvent.VK_DOWN || e.getKeyCode()==KeyEvent.VK_S){

            resetKeyPressedReversed(0,-1);

        }

    }


    @Override

    public void keyReleased(KeyEvent e) {

        if(e.getKeyCode()==KeyEvent.VK_ENTER){

            if(keycurr==0){//System.out.println("entering");

                if(pcfrom>-1){

                    //System.out.println("select to move "+pcfrom);

                    int avm=game.getAvailableMoveCount(pcfrom);

                    if(avm>0){

                        game.getAvailableMove(pcfrom, 0, keyp[1]);

                    }

                    else{

                        keyp[1].x=keyp[0].x;

                        keyp[1].y=keyp[0].y;

                    }

                    keyp[3].x=keyp[1].x;

                    keyp[3].y=keyp[1].y;    

                    reversePoint(keyp[3]);

                    

                }

                else{

                    //System.out.println("not selected piece to move");

                    keycurr=(keycurr+1)%2;

                }

            }

            else{

                if(pcfrom>-1){

                    pprtr.x=keyp[2].x;

                    pprtr.y=keyp[2].y;

                    pretr.x=keyp[3].x;

                    pretr.y=keyp[3].y;

                    reversePoint(pprtr);

                    reversePoint(pretr);

                    //System.out.println(ChessGame.square(WIDTH, WIDTH)"");

                    clearsquaresShowingTargetBy();

                    mouseReleased();

                }

                else{

                    System.out.println("keycurr==1 and pcfrom<0 ????????????????????");

                }

                

            }

            keycurr=(keycurr+1)%2;

            repaint();

           

        }

    }

    

    

    

    @Override

    public void componentResized(ComponentEvent e) {

        resizedWithMin(Math.min(getWidth(), getHeight()));

    }

    @Override

    public void componentMoved(ComponentEvent e) {}

    @Override

    public void componentShown(ComponentEvent e) {}

    @Override

    public void componentHidden(ComponentEvent e) {}

    @Override

    public void mouseClicked(MouseEvent e) {}


    

    public void takeScreenShoot(){

        String message="";

        Exception someefallen=null;

        try{

            BufferedImage bim=new BufferedImage(pieceFontSize*8, pieceFontSize*8, BufferedImage.TYPE_INT_RGB);

            Graphics g=bim.createGraphics();

            repaintingChess((Graphics2D)g);

            g.dispose();

            message+="\nImage created";

            

            try{

                TransferableImage trans = new TransferableImage( bim );

                Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();

                c.setContents( trans, this);

                message+="\nImage copied to clipboard";

                

                try{

                    String home = System.getProperty("user.home");

                    String filename="tempChessSceenshoot";

                    String ext="png";

                    File file = new File(home+"/Downloads/" + filename+"."+ext);

                    ImageIO.write(bim, ext, file);

                    message+="\nwritten @: "+file.getAbsolutePath();

                    

                    

                    try {

                        Runtime rs = Runtime.getRuntime();

                        rs.exec("mspaint "+file.getAbsolutePath());

                        message+="\nopened with mspaint if windows gates is here";

                    }

                    catch (Exception e3) {someefallen=e3;}  

                }catch(Exception e2){someefallen=e2;}

            }catch(Exception e1){someefallen=e1;}

        }catch(Exception e){someefallen=e;}

        

        

       //someefallen=new Exception("test");

       if(someefallen!=null){

           JOptionPane.showMessageDialog(this, message+" \n\n\n"+someefallen);

       }

        

        


    }

    public void lostOwnership( Clipboard clip, Transferable trans ) {

        //System.out.println( "Lost Clipboard Ownership" );

    }

     

    

    

}



class JChessGame extends JPanel{


    public static Toolkit tk=null;

    public static Dimension screendim=null;

    public static Insets zeroInsets=new Insets(0,0,0,0);

    

    public static boolean beepsOn=true;

    

    public static void beep(){

        if(tk!=null && beepsOn){

            tk.beep();

        }

    }

    public static void beep(int times,long firstStop,long secondStop){

        if(tk!=null && beepsOn){

            Thread beeper=new Thread(){

                public void run(){

                    int i=0;

                    while(i<times){

                        tk.beep();

                        try{

                            sleep(firstStop);

                        }catch(InterruptedException inter){}

                        tk.beep();

                        try{

                            sleep(secondStop);

                        }catch(InterruptedException inter){}

                        ++i;

                    }

                }

            };

            beeper.setDaemon(true);

            beeper.start();

        }

        

    }

    

    

    /**

     * @param args the command line arguments

     */

    public static void main(String[] args) {

        // TODO code application logic here

        try{

            tk=Toolkit.getDefaultToolkit();

            screendim=tk.getScreenSize();

            JFrame jfr=new JFrame("Standalone java Simple Chess for kids - opensource");

            jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            //jfr.setBounds(screendim.width/4,screendim.height/4,screendim.width/2,screendim.height/2);

            jfr.setBounds(0,0,screendim.width/2,50+screendim.height/2);

            //jfr.setBounds(0,0,300,300);

            jfr.setVisible(true);

            

            JChessGame test=new JChessGame();

            jfr.getContentPane().add(test);

            //jfr.validate();

            //test.jpGameMain.jtbFree.doClick();

            

        }catch(Throwable thr){

            try{

                JOptionPane.showMessageDialog(null, "Cant play java chess\n\n"+thr,"Sorry",JOptionPane.ERROR_MESSAGE);

            }catch(Throwable thr2){}

            try{

                thr.printStackTrace();

            }catch(Throwable thr1){}

        }

    }

    

    JChessPanel jpGameMain;

    JPanel jpToolsMain=new JPanel(new BorderLayout());

    JSplitPane jspl;

    

    

    int playsWithWhite=0;

    JTextField jtfPlayerNames[]={new JTextField("Leonidas"),new JTextField("Jim")};

    JLabel jlPlayerScores[]={new JLabel("1"),new JLabel("0")};

    JPanel jpPlayerScoresHolders[]={new JPanel(new BorderLayout()),new JPanel(new BorderLayout())};

    JPanel jpScoreNorth=new JPanel(new GridLayout(1,2));

    

    

    JList<ChessMove> jlMovesPlayed;

    JTabbedPane jtp=new JTabbedPane(JTabbedPane.BOTTOM);

    

    

    JButton jbResetScore=new JButton("sc");

    JButton jbGiveUp=new JButton("lost");

    JButton jbDraw=new JButton("draw");

    JButton jbFinishThisGame=new JButton("win");

    JPanel jpmainGameButtonsCenter=new JPanel(new GridLayout(1,2));

    JPanel jpmainGameButtons=new JPanel(new BorderLayout());

    

    

    JPanel jpNorth=new JPanel(new BorderLayout());

    

    JMenuBar jmb=new JMenuBar();

    JMenu jmFile=new JMenu("File");

    JMenuItem jmiAbout=new JMenuItem("About");

    JMenu jmOtherOptions=new JMenu("Opts");

    JRadioButton jrbBeepsOnOff=new JRadioButton("Beeps",true);

    JMenuItem jmiHelp=new JMenuItem("help");

    

    void jmiAbout(){

        JOptionPane.showMessageDialog(jpGameMain, "jimakoskx@hotmail.com\n@all.ext\n250 series 3.23.1981 \nTsoukalas I. Dimitrios \nHellas-Athens\n\nfor Leonida.!.and kids\n\nMarch 2022");

    }

    void jrbBeepsOnOff(){

        beepsOn=jrbBeepsOnOff.isSelected();

    }

    void buildjmb(){

        jmb.add(jmFile);

        jmb.add(jmOtherOptions);

        

        

        jmiAbout.addActionListener(e->jmiAbout());

        jmFile.add(jmiAbout);

        

        

        jrbBeepsOnOff.addActionListener(e->jrbBeepsOnOff());

        jmOtherOptions.add(jrbBeepsOnOff);

        jmiHelp.addActionListener(e->help());

        jmOtherOptions.add(jmiHelp);

    }

    void help(){

        JOptionPane.showMessageDialog(jpGameMain, "Hold shift as you click a square to add showing pieces targeting at."

                + "\nSecond player can use ARROWS or (ASDW) to move selected square."

                + "\nPress Enter to grap the piece ,move again,and enter to leave it somewhere."

                + "\n\nPut your mouse over some button(~ 2 sec) and a tooltip text must be appeared to help you!!!"

                + "\n\nTry exercize using the red ! button (white playing after each random posistions.)"

                + "\ngood luck!"

                + "\n\nLearn the first ~5? chapters of some programming lan+gauge (java or c++)"

                + "\n ....if you want to upgrade this program !"

        ,"help from the past! (error hehehe!)",JOptionPane.ERROR_MESSAGE);

    }

    public JChessGame(){

        super(new BorderLayout());

        

        jpGameMain=new JChessPanel(){

            @Override

            public void movePlayed(ChessMove cm) {

                super.movePlayed(cm); 

                moveHappened();

            }

        };

        jspl=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,jpToolsMain,jpGameMain);

        jlMovesPlayed=new JList<>(jpGameMain.game.movesPlayed);

        jlMovesPlayed.setFont(new Font("Dialog",Font.PLAIN,16));

        jtp.addTab("*", new JScrollPane(jlMovesPlayed));

        jtp.addTab("~", jpGameMain.jpPalette);

        

        jspl.setResizeWeight(0.1);

        jspl.setDividerLocation(0.1);

        jspl.setOneTouchExpandable(true);

        jspl.setContinuousLayout(true);

        

        add(BorderLayout.CENTER,jspl);

        

        jpmainGameButtonsCenter.add(jbGiveUp);

        jpmainGameButtonsCenter.add(jbDraw);

        jpmainGameButtons.add(BorderLayout.WEST,jbResetScore);

        jpmainGameButtons.add(BorderLayout.CENTER,jpmainGameButtonsCenter);

        jpmainGameButtons.add(BorderLayout.EAST,jbFinishThisGame);

        

        

        

        jtfPlayerNames[1].setBackground(Color.green);

        jpPlayerScoresHolders[0].add(BorderLayout.NORTH,jtfPlayerNames[0]);

        jpPlayerScoresHolders[1].add(BorderLayout.NORTH,jtfPlayerNames[1]);

        jpPlayerScoresHolders[0].add(BorderLayout.SOUTH,jlPlayerScores[0]);

        jpPlayerScoresHolders[1].add(BorderLayout.SOUTH,jlPlayerScores[1]);

        jlPlayerScores[0].setHorizontalAlignment(SwingConstants.CENTER);

        jlPlayerScores[1].setHorizontalAlignment(SwingConstants.CENTER);

        jbResetScore.setHorizontalAlignment(SwingConstants.CENTER);

        jbResetScore.setMargin(zeroInsets);

        jbResetScore.setToolTipText("reseting the score and restarts with SAME order !!! or if 0-0 exchanges the who plays with white");

        

        

        

        buildjmb();

        jpNorth.add(BorderLayout.NORTH,jmb);

        jpNorth.add(BorderLayout.CENTER,jpScoreNorth);

        jpNorth.add(BorderLayout.SOUTH,jpmainGameButtons);

        

        

        

        jpToolsMain.add(BorderLayout.WEST,jpGameMain.jpPutinOnFree);

        jpToolsMain.add(BorderLayout.NORTH,jpNorth);

        jpToolsMain.add(BorderLayout.CENTER,jtp);

        jpToolsMain.add(BorderLayout.EAST,jpGameMain.jpDrawOptions);

        jpToolsMain.add(BorderLayout.SOUTH,jpGameMain.jpPieceStateOption);

        


        

        exhangeWhoPlaysWithWhite();

        

        

        jbGiveUp.setMargin(zeroInsets);

        jbDraw.setMargin(zeroInsets);

        jbFinishThisGame.setMargin(zeroInsets);

        jbGiveUp.setToolTipText("Give Up.Current Playing Player will take zero(0) and the other 1 points ! ..restarts a new game");

        jbDraw.setToolTipText("Both players will take a point(1) and restarts a new game");

        jbFinishThisGame.setToolTipText("Use this after mat. Current Playing Player will take 1 point ..restarts a new game");

        

        

        jbResetScore.addActionListener(e->jbResetScore());

        jbDraw.addActionListener(e->jbDraw());

        jbFinishThisGame.addActionListener(e->jbFinishThisGame());

        jbGiveUp.addActionListener(e->jbGiveUp());

        

        

        

        

        

        

        

        

        

        

        

        Thread thrValidaterOneJobOnly=new Thread(){

            public void run(){

                try{Thread.sleep(123);}catch(InterruptedException inter){}

                Container par=getParent();

                while(par!=null){

                    par.validate();

                    par=par.getParent();

                    try{Thread.sleep(23);}catch(InterruptedException inter){}

                }

                jspl.setDividerLocation(0.2);

            }

        };

        thrValidaterOneJobOnly.setDaemon(true);

        thrValidaterOneJobOnly.start();

        

    }


    


    

    public static void setGridLayoutOrientation(int orientation,JPanel jp){

        int counts=jp.getComponentCount();

        int rows=1,cols=counts;

        if(orientation==JSplitPane.VERTICAL_SPLIT){

            rows=counts;

            cols=1;

        }

        GridLayout gl=new GridLayout(rows,cols);

        jp.setLayout(gl);

        jp.validate();

        

    }

    void setMainButtonsOrientation(int orientation){

        setGridLayoutOrientation(orientation, jpmainGameButtons);

    }

    

    

    

    int getScore(int index){

        return Integer.parseInt(jlPlayerScores[index].getText());

    }

    void jbResetScore(){

        resetScoreOrExhangeWhoPlaysWithWhite();

    }

    void resetScoreOrExhangeWhoPlaysWithWhite(){

        int sc0=getScore(0);

        int sc1=getScore(1);

        if(sc0==sc1 && sc0==0){

            exhangeWhoPlaysWithWhite();

        }

        else{

            jlPlayerScores[0].setText("0");

            jlPlayerScores[1].setText("0");

        }

    }

    void exhangeWhoPlaysWithWhite(){

        ++playsWithWhite;

        playsWithWhite%=2;

        jpScoreNorth.removeAll();

        int first=0,second=1;

        if(playsWithWhite==1){

            first=1;

            second=0;

        }

        jpScoreNorth.add(jpPlayerScoresHolders[first]);

        jpScoreNorth.add(jpPlayerScoresHolders[second]);       

        jpScoreNorth.validate();

    }

    void jbDraw(){

        jlPlayerScores[0].setText((getScore(0)+1)+"");

        jlPlayerScores[1].setText((getScore(1)+1)+"");

        resetGame();

    }

    void jbFinishThisGame(){//same code

        int whoplays=jpGameMain.game.whoPlays();

        whoplays+=playsWithWhite;

        whoplays++;

        whoplays%=2;

        jlPlayerScores[whoplays].setText((getScore(whoplays)+1)+"");

        resetGame();

        

    }

    void jbGiveUp(){

        int whoplays=jpGameMain.game.whoPlays();

        whoplays+=playsWithWhite;

        whoplays++;

        whoplays%=2;

        jlPlayerScores[whoplays].setText((getScore(whoplays)+1)+"");

        resetGame();

    }

    

    void resetGame(){

        jpGameMain.resetGame();

        exhangeWhoPlaysWithWhite();

        moveHappened();

    }

    

    void moveHappened(){

        jlMovesPlayed.setListData(jpGameMain.game.movesPlayed);

        int lastindex=jpGameMain.game.movesPlayed.size()-1;

        jlMovesPlayed.setSelectedIndex(lastindex);

        jlMovesPlayed.ensureIndexIsVisible(lastindex);

        int whoplays=jpGameMain.game.whoPlays();

        //System.out.println("Now plays "+whoplays);

        whoplays+=playsWithWhite;

        whoplays%=2;

        jtfPlayerNames[whoplays].setBackground(Color.green);

        jtfPlayerNames[(whoplays+1)%2].setBackground(Color.white);

        

        if(jpGameMain.game.isMat()){

            jbFinishThisGame.setForeground(Color.red);

        }

        else{

            jbFinishThisGame.setForeground(Color.black);

        }

    }


}