home / fornax / fornax-v4-0 / src / supplementary / perft.cpp

perft.cpp



//
//  perft.cpp
//  fornax3
//
//  Created by Anders on 24/12/2020.
//

#include <stdio.h>
#include "perft.hpp"
#include "../moving/movegen.hpp"
#include "../moving/makemove.hpp"
#include "../libs/stopwatch.h"

template<bool printmoves, color active>
static long perft_templ(Board* board, int depth) {
  constexpr color opp = COLOR_OPPOSITE(active);
  
  if (depth == 0) {
    return 1;
  }
  else if (depth == 1 && !printmoves) {
    evalmove moves[128];
    uint8_t length = movegen_generate<active>(board, moves);
    return length;
  }
  
  long count = 0;
  
  evalmove moves[128];
  uint8_t length = movegen_generate<active>(board, moves);
  for (uint8_t i = 0; i < length; ++i) {
    if (printmoves) parsing_printmove((move) moves[i]);
    makemove_make<active>(board, (move) moves[i]);
    long local = perft_templ<false, opp>(board, depth - 1);
    makemove_takeback<opp>(board, (move) moves[i]);
    count += local;
    if (printmoves) printf(" = %ld\n", local);
  }
  return count;
}

long perft(const Board* board, int depth, bool printmoves) {
  long start = stopwatch_wall_start();
  Board copy = *board;
  long total = board->active == WHITE
  ? (printmoves ? perft_templ<true, WHITE>(&copy, depth) : perft_templ<false, WHITE>(&copy, depth))
  : (printmoves ? perft_templ<true, BLACK>(&copy, depth) : perft_templ<false, BLACK>(&copy, depth));
  
  long time = stopwatch_wall_stop(start);
  if (printmoves) {
    printf("total = %ld", total);
    if (time > 0) printf(" (time = %.3fs mps = %ld)", (double) time / 1000, total * 1000 / time);
    printf("\n");
  }
  return total;
}