/*
 * Copyright (C) 2013-2014 Phokham Nonava
 *
 * Use of this source code is governed by the MIT license that can be
 * found in the LICENSE file.
 */
package com.fluxchess.pulse;

import java.util.concurrent.TimeUnit;

import static com.fluxchess.pulse.MoveList.MoveEntry;

final class Perft {

  private static final int MAX_DEPTH = 6;

  private final MoveGenerator[] moveGenerators = new MoveGenerator[MAX_DEPTH];

  void run() {
    Position position = Notation.toPosition(Notation.STANDARDPOSITION);
    int depth = MAX_DEPTH;

    for (int i = 0; i < MAX_DEPTH; ++i) {
      moveGenerators[i] = new MoveGenerator();
    }

    System.out.format("Testing %s at depth %d%n", Notation.fromPosition(position), depth);

    long startTime = System.currentTimeMillis();
    long result = miniMax(depth, position, 0);
    long endTime = System.currentTimeMillis();

    long duration = endTime - startTime;

    System.out.format(
        "Nodes: %d%nDuration: %02d:%02d:%02d.%03d%n",
        result,
        TimeUnit.MILLISECONDS.toHours(duration),
        TimeUnit.MILLISECONDS.toMinutes(duration) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration)),
        TimeUnit.MILLISECONDS.toSeconds(duration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)),
        duration - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration))
    );

    System.out.format("n/ms: %d%n", result / duration);
  }

  private long miniMax(int depth, Position position, int ply) {
    if (depth == 0) {
      return 1;
    }

    int totalNodes = 0;

    boolean isCheck = position.isCheck();
    MoveGenerator moveGenerator = moveGenerators[ply];
    MoveList<MoveEntry> moves = moveGenerator.getMoves(position, depth, isCheck);
    for (int i = 0; i < moves.size; ++i) {
      int move = moves.entries[i].move;
      long nodes = 0;

      position.makeMove(move);
      if (!position.isCheck(Color.opposite(position.activeColor))) {
        nodes = miniMax(depth - 1, position, ply + 1);
      }
      position.undoMove(move);

      totalNodes += nodes;
    }

    return totalNodes;
  }

}

@@ -186,39 +186,50 @@
 ort 
-java.util.concurrent.TimeUnit;%0A
+static com.fluxchess.pulse.Color.opposite;
 %0Aimp
@@ -278,16 +278,281 @@
 veEntry;
+%0Aimport static java.lang.System.currentTimeMillis;%0Aimport static java.util.concurrent.TimeUnit.HOURS;%0Aimport static java.util.concurrent.TimeUnit.MILLISECONDS;%0Aimport static java.util.concurrent.TimeUnit.MINUTES;%0Aimport static java.util.concurrent.TimeUnit.SECONDS;
 %0A%0Afinal 
@@ -1009,31 +1009,24 @@
 startTime = 
-System.
 currentTimeM
@@ -1100,23 +1100,16 @@
 dTime = 
-System.
 currentT
@@ -1261,33 +1261,24 @@
 lt,%0A        
-TimeUnit.
 MILLISECONDS
@@ -1301,33 +1301,24 @@
 n),%0A        
-TimeUnit.
 MILLISECONDS
@@ -1340,25 +1340,16 @@
 tion) - 
-TimeUnit.
 HOURS.to
@@ -1356,25 +1356,16 @@
 Minutes(
-TimeUnit.
 MILLISEC
@@ -1397,25 +1397,16 @@
         
-TimeUnit.
 MILLISEC
@@ -1432,25 +1432,16 @@
 tion) - 
-TimeUnit.
 MINUTES.
@@ -1450,25 +1450,16 @@
 Seconds(
-TimeUnit.
 MILLISEC
@@ -1504,25 +1504,16 @@
 ation - 
-TimeUnit.
 SECONDS.
@@ -1521,25 +1521,16 @@
 oMillis(
-TimeUnit.
 MILLISEC
@@ -2102,22 +2102,16 @@
 isCheck(
-Color.
 opposite

Add static import in Perft