/*
  Copyright 2011 Ken Takusagawa
  
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */
import chesspresso.position.ImmutablePosition;
import chesspresso.position.Position;
import chesspresso.position.MoveablePosition;
import chesspresso.position.MutablePosition;
import chesspresso.move.IllegalMoveException;
import chesspresso.move.Move;
import chesspresso.position.FEN;
public class mycode {
    public static void main(String[] args){
        (new mycode()).runcross2();
    }
    final String[] fs={FEN.START_POSITION,
                       "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1",
                       "8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 1",
                       "r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1 w kq - 0 1",
                       "r2q1rk1/pP1p2pp/Q4n2/bbp1p3/Np6/1B3NBn/pPPP1PPP/R3K2R b KQ - 0 1"};

    final int[] depth={6,5,7,6,6};

    final String[] cross=
    {"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
     "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1",
     "4k3/8/8/8/8/8/8/4K2R w K - 0 1",
     "4k3/8/8/8/8/8/8/R3K3 w Q - 0 1",
     "4k2r/8/8/8/8/8/8/4K3 w k - 0 1",
     "r3k3/8/8/8/8/8/8/4K3 w q - 0 1",
     "4k3/8/8/8/8/8/8/R3K2R w KQ - 0 1",
     "r3k2r/8/8/8/8/8/8/4K3 w kq - 0 1",
     "8/8/8/8/8/8/6k1/4K2R w K - 0 1",
     "8/8/8/8/8/8/1k6/R3K3 w Q - 0 1",
     "4k2r/6K1/8/8/8/8/8/8 w k - 0 1",
     "r3k3/1K6/8/8/8/8/8/8 w q - 0 1",
     "r3k2r/8/8/8/8/8/8/R3K2R w KQkq - 0 1",
     "r3k2r/8/8/8/8/8/8/1R2K2R w Kkq - 0 1",
     "r3k2r/8/8/8/8/8/8/2R1K2R w Kkq - 0 1",
     "r3k2r/8/8/8/8/8/8/R3K1R1 w Qkq - 0 1",
     "1r2k2r/8/8/8/8/8/8/R3K2R w KQk - 0 1",
     "2r1k2r/8/8/8/8/8/8/R3K2R w KQk - 0 1",
     "r3k1r1/8/8/8/8/8/8/R3K2R w KQq - 0 1",
     "4k3/8/8/8/8/8/8/4K2R b K - 0 1",
     "4k3/8/8/8/8/8/8/R3K3 b Q - 0 1",
     "4k2r/8/8/8/8/8/8/4K3 b k - 0 1",
     "r3k3/8/8/8/8/8/8/4K3 b q - 0 1",
     "4k3/8/8/8/8/8/8/R3K2R b KQ - 0 1",
     "r3k2r/8/8/8/8/8/8/4K3 b kq - 0 1",
     "8/8/8/8/8/8/6k1/4K2R b K - 0 1",
     "8/8/8/8/8/8/1k6/R3K3 b Q - 0 1",
     "4k2r/6K1/8/8/8/8/8/8 b k - 0 1",
     "r3k3/1K6/8/8/8/8/8/8 b q - 0 1",
     "r3k2r/8/8/8/8/8/8/R3K2R b KQkq - 0 1",
     "r3k2r/8/8/8/8/8/8/1R2K2R b Kkq - 0 1",
     "r3k2r/8/8/8/8/8/8/2R1K2R b Kkq - 0 1",
     "r3k2r/8/8/8/8/8/8/R3K1R1 b Qkq - 0 1",
     "1r2k2r/8/8/8/8/8/8/R3K2R b KQk - 0 1",
     "2r1k2r/8/8/8/8/8/8/R3K2R b KQk - 0 1",
     "r3k1r1/8/8/8/8/8/8/R3K2R b KQq - 0 1",
     "8/1n4N1/2k5/8/8/5K2/1N4n1/8 w - - 0 1",
     "8/1k6/8/5N2/8/4n3/8/2K5 w - - 0 1",
     "8/8/4k3/3Nn3/3nN3/4K3/8/8 w - - 0 1",
     "K7/8/2n5/1n6/8/8/8/k6N w - - 0 1",
     "k7/8/2N5/1N6/8/8/8/K6n w - - 0 1",
     "8/1n4N1/2k5/8/8/5K2/1N4n1/8 b - - 0 1",
     "8/1k6/8/5N2/8/4n3/8/2K5 b - - 0 1",
     "8/8/3K4/3Nn3/3nN3/4k3/8/8 b - - 0 1",
     "K7/8/2n5/1n6/8/8/8/k6N b - - 0 1",
     "k7/8/2N5/1N6/8/8/8/K6n b - - 0 1",
     "B6b/8/8/8/2K5/4k3/8/b6B w - - 0 1",
     "8/8/1B6/7b/7k/8/2B1b3/7K w - - 0 1",
     "k7/B7/1B6/1B6/8/8/8/K6b w - - 0 1",
     "K7/b7/1b6/1b6/8/8/8/k6B w - - 0 1",
     "B6b/8/8/8/2K5/5k2/8/b6B b - - 0 1",
     "8/8/1B6/7b/7k/8/2B1b3/7K b - - 0 1",
     "k7/B7/1B6/1B6/8/8/8/K6b b - - 0 1",
     "K7/b7/1b6/1b6/8/8/8/k6B b - - 0 1",
     "7k/RR6/8/8/8/8/rr6/7K w - - 0 1",
     "R6r/8/8/2K5/5k2/8/8/r6R w - - 0 1",
     "7k/RR6/8/8/8/8/rr6/7K b - - 0 1",
     "R6r/8/8/2K5/5k2/8/8/r6R b - - 0 1",
     "6kq/8/8/8/8/8/8/7K w - - 0 1",
     "6KQ/8/8/8/8/8/8/7k b - - 0 1",
     "K7/8/8/3Q4/4q3/8/8/7k w - - 0 1",
     "6qk/8/8/8/8/8/8/7K b - - 0 1",
     "6KQ/8/8/8/8/8/8/7k b - - 0 1",
     "K7/8/8/3Q4/4q3/8/8/7k b - - 0 1",
     "8/8/8/8/8/K7/P7/k7 w - - 0 1",
     "8/8/8/8/8/7K/7P/7k w - - 0 1",
     "K7/p7/k7/8/8/8/8/8 w - - 0 1",
     "7K/7p/7k/8/8/8/8/8 w - - 0 1",
     "8/2k1p3/3pP3/3P2K1/8/8/8/8 w - - 0 1",
     "8/8/8/8/8/K7/P7/k7 b - - 0 1",
     "8/8/8/8/8/7K/7P/7k b - - 0 1",
     "K7/p7/k7/8/8/8/8/8 b - - 0 1",
     "7K/7p/7k/8/8/8/8/8 b - - 0 1",
     "8/2k1p3/3pP3/3P2K1/8/8/8/8 b - - 0 1",
     "8/8/8/8/8/4k3/4P3/4K3 w - - 0 1",
     "4k3/4p3/4K3/8/8/8/8/8 b - - 0 1",
     "8/8/7k/7p/7P/7K/8/8 w - - 0 1",
     "8/8/k7/p7/P7/K7/8/8 w - - 0 1",
     "8/8/3k4/3p4/3P4/3K4/8/8 w - - 0 1",
     "8/3k4/3p4/8/3P4/3K4/8/8 w - - 0 1",
     "8/8/3k4/3p4/8/3P4/3K4/8 w - - 0 1",
     "k7/8/3p4/8/3P4/8/8/7K w - - 0 1",
     "8/8/7k/7p/7P/7K/8/8 b - - 0 1",
     "8/8/k7/p7/P7/K7/8/8 b - - 0 1",
     "8/8/3k4/3p4/3P4/3K4/8/8 b - - 0 1",
     "8/3k4/3p4/8/3P4/3K4/8/8 b - - 0 1",
     "8/8/3k4/3p4/8/3P4/3K4/8 b - - 0 1",
     "k7/8/3p4/8/3P4/8/8/7K b - - 0 1",
     "7k/3p4/8/8/3P4/8/8/K7 w - - 0 1",
     "7k/8/8/3p4/8/8/3P4/K7 w - - 0 1",
     "k7/8/8/7p/6P1/8/8/K7 w - - 0 1",
     "k7/8/7p/8/8/6P1/8/K7 w - - 0 1",
     "k7/8/8/6p1/7P/8/8/K7 w - - 0 1",
     "k7/8/6p1/8/8/7P/8/K7 w - - 0 1",
     "k7/8/8/3p4/4p3/8/8/7K w - - 0 1",
     "k7/8/3p4/8/8/4P3/8/7K w - - 0 1",
     "7k/3p4/8/8/3P4/8/8/K7 b - - 0 1",
     "7k/8/8/3p4/8/8/3P4/K7 b - - 0 1",
     "k7/8/8/7p/6P1/8/8/K7 b - - 0 1",
     "k7/8/7p/8/8/6P1/8/K7 b - - 0 1",
     "k7/8/8/6p1/7P/8/8/K7 b - - 0 1",
     "k7/8/6p1/8/8/7P/8/K7 b - - 0 1",
     "k7/8/8/3p4/4p3/8/8/7K b - - 0 1",
     "k7/8/3p4/8/8/4P3/8/7K b - - 0 1",
     "7k/8/8/p7/1P6/8/8/7K w - - 0 1",
     "7k/8/p7/8/8/1P6/8/7K w - - 0 1",
     "7k/8/8/1p6/P7/8/8/7K w - - 0 1",
     "7k/8/1p6/8/8/P7/8/7K w - - 0 1",
     "k7/7p/8/8/8/8/6P1/K7 w - - 0 1",
     "k7/6p1/8/8/8/8/7P/K7 w - - 0 1",
     "3k4/3pp3/8/8/8/8/3PP3/3K4 w - - 0 1",
     "7k/8/8/p7/1P6/8/8/7K b - - 0 1",
     "7k/8/p7/8/8/1P6/8/7K b - - 0 1",
     "7k/8/8/1p6/P7/8/8/7K b - - 0 1",
     "7k/8/1p6/8/8/P7/8/7K b - - 0 1",
     "k7/7p/8/8/8/8/6P1/K7 b - - 0 1",
     "k7/6p1/8/8/8/8/7P/K7 b - - 0 1",
     "3k4/3pp3/8/8/8/8/3PP3/3K4 b - - 0 1",
     "8/Pk6/8/8/8/8/6Kp/8 w - - 0 1",
     "n1n5/1Pk5/8/8/8/8/5Kp1/5N1N w - - 0 1",
     "8/PPPk4/8/8/8/8/4Kppp/8 w - - 0 1",
     "n1n5/PPPk4/8/8/8/8/4Kppp/5N1N w - - 0 1",
     "8/Pk6/8/8/8/8/6Kp/8 b - - 0 1",
     "n1n5/1Pk5/8/8/8/8/5Kp1/5N1N b - - 0 1",
     "8/PPPk4/8/8/8/8/4Kppp/8 b - - 0 1",
     "n1n5/PPPk4/8/8/8/8/4Kppp/5N1N b - - 0 1"
    };

    //http://hem.passagen.se/maragor/perftsuite.epd
    void failing1(){
        perft(new Position(fs[2],true),6);
    }
    void failing2(){
        MoveablePosition p=new Position("8/8/3p4/KPp3r1/5p1k/8/1R2P1P1/8 w - c6 0 1");
        System.out.println(p.getMovesAsString(p.getAllMoves(),false));
    }
    void run(){
        new Position("8/8/2Pp4/r7/5p1k/1R6/4P1P1/8 w - - 0 3",true);
    }
    void run1(){
        for(int f=0;f<fs.length;++f){
            MoveablePosition foo=new Position(fs[f],true);
            
            System.out.println("position "+f+" "+foo);
            for(int i=1;i<=depth[f];++i){
                System.out.println(""+i+" "+perft(foo,i));
            }
        }
    }
    void runcross(){

        //Position.createInitialPosition();
        for(int i=1;i<=7;++i){
            for(int f=0;f<fs.length;++f){
                if(i<=depth[f]){
                    MoveablePosition foo=new Position(fs[f],true);
                    System.out.println("position "+f+" "+foo);
                    System.out.println(""+i+" "+perft(foo,i));
                }
            }
            System.out.println();
        }
    }
    
    void runcross2(){

        //Position.createInitialPosition();
        for(int i=1;i<=6;++i){
            for(int f=0;f<cross.length;++f){
                MoveablePosition foo=new Position(cross[f],true);
                System.out.println("position "+f+" "+foo);
                System.out.println(""+i+" "+perft(foo,i));
            }
            System.out.println();
        }
    }

    long perft(MoveablePosition start,int depth){
        //System.out.println("start "+start);

        short[] moves=start.getAllMoves();
        
        //if (depth==1) return moves.length;

        if(depth==0) return 1;
        long nodes=0;
        for(int i=0;i<moves.length;++i){
            //System.out.println(""+start);
            try{
                start.doMove(moves[i]);
            } catch (IllegalMoveException e){
                throw new RuntimeException();
            }
            if(Move.isEPMove(moves[i])){
                if(start.isLegal()){
                    //workaround for bug
                    if(depth>1){
                        nodes+=perft(new Position(start),depth-1);
                    } else {
                        nodes++;
                    }
                } else {
                    //try{ System.out.println("rejecting "+start.getLastMove()); } catch (IllegalMoveException e){ throw new RuntimeException();}
                }
            } else {
                if(depth>1){
                    nodes+=perft(new Position(start),depth-1);
                } else {
                    nodes++;
                }
            }
            start.undoMove();
        }
        //System.out.println("finished "+nodes);
        return nodes;
    }
}
