/* GNU Chess 5.0 - test.c - testing code
   Copyright (c) 1999-2002 Free Software Foundation, Inc.

   GNU Chess is based on the two research programs 
   Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.

   GNU Chess 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 2, or (at your option)
   any later version.

   GNU Chess 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 GNU Chess; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

   Contact Info: 
     bug-gnu-chess@gnu.org
     cracraft@ai.mit.edu, cracraft@stanfordalumni.org, cracraft@earthlink.net
*/

#include <stdio.h>
#include <sys/time.h>

#include "util.h"
#include "epd.h"
#include "movelist.h"
#include "searchdata.h"
#include "searchstats.h"
#include "searchparams.h"
#include "genmove.h"
#include "eval.h"

void TestMoveGenSpeed (void)
/**************************************************************************
 *
 *   This routine benchmarks the speed of the bitmap move generation.
 *   The test case is BK.epd, the 24 positions from the Brat-Kopec test
 *   suite.
 *
 **************************************************************************/
{
   unsigned long i;
   struct timeval t1, t2;
   double et;
   short side, xside;
   board_t board[1];
   movelist_t movelist[1];
   epd_iter_t epd_iter[1];
   long unsigned int GenCnt=0;
   et = 0;
   EPDIterInit(epd_iter);
   EPDIterStart(epd_iter,"wac.epd");
   while (EPDIterNext(epd_iter,board,NULL,NULL))
   {
      gettimeofday (&t1, NULL);
      side = board->side;
      xside = 1^side;
      for (i = 0; i < 2000000; i++)
      {
	 GenMoves (board,movelist);
	 GenCnt+=movelist->gencnt;
      }
      gettimeofday (&t2, NULL);
      et += (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) / 1e6;
      Output ("Time = %f\n", et);
   }
   Output ("No. of moves generated = %lu\n", GenCnt);
   Output ("Time taken = %f secs\n", et);
   if (et > 0)
      Output ("Rate = %f moves/sec.\n", GenCnt / et);
}



void TestNonCaptureGenSpeed (void)
/**************************************************************************
 *
 *   This routine benchmarks the speed of the bitmap move generation
 *   for non capturing moves.
 *   The test case is BK.epd, the 24 positions from the Brat-Kopec test
 *   suite.
 *
 **************************************************************************/
{
   unsigned long i;
   struct timeval t1, t2;
   double et;
   board_t board[1];
   movelist_t movelist[1];
   epd_iter_t epd_iter[1];
   long unsigned int GenCnt=0;
   
   et = 0;
   EPDIterInit(epd_iter);
   EPDIterStart(epd_iter,"wac.epd");

   while (EPDIterNext(epd_iter,board,NULL,NULL))
   {
      gettimeofday (&t1, NULL);
      for (i = 0; i < 100000; i++)
      {
         GenPseudoNonCaptures (board,movelist);
	 GenCnt+=movelist->gencnt;
      }
      gettimeofday (&t2, NULL);
      et += (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) / 1e6;
      Output ("Time = %f\n", et);
   }
   Output ("No. of moves generated = %lu\n", GenCnt);
   Output ("Time taken = %f\n", et);
   if (et > 0)
      Output ("Rate = %f\n", GenCnt / et);  
}


void TestCaptureGenSpeed (void)
/**************************************************************************
 *
 *   This routine benchmarks the speed of the bitmap move generation
 *   for captures.
 *   The test case is BK.epd, the 24 positions from the Brat-Kopec test
 *   suite.
 *
 **************************************************************************/
{
   unsigned long i;
   struct timeval t1, t2;
   double et;
   movelist_t movelist[1];
   board_t board[1];
   epd_iter_t epd_iter[1];
   long unsigned int GenCnt=0;
   EPDIterInit(epd_iter);
   EPDIterStart(epd_iter,"wac.epd");

   et = 0;
   while (EPDIterNext(epd_iter,board,NULL,NULL))
   {
      gettimeofday (&t1, NULL);
      for (i = 0; i < 200000; i++)
      {
	         GenPseudoCaptures (board,movelist);
		 GenCnt+=movelist->gencnt;
      }
      gettimeofday (&t2, NULL);
      et += (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) / 1e6;
      Output ("Time = %f\n", et);
   }
   Output ("No. of moves generated = %lu\n", GenCnt);
   Output ("Time taken = %f\n", et);
   if (et > 0)
      Output ("Rate = %f\n", GenCnt / et);  
}


void TestMoveList (void)
/****************************************************************************
 *  
 *  This routine reads in a *.epd file (EPD notation) and prints the legal
 *  moves for that position.  
 *
 ****************************************************************************/
{
  board_t board[1];
  movelist_t movelist[1];
  long unsigned int GenCnt=0;
  epd_iter_t epd_iter[1];
  EPDIterInit(epd_iter);
  EPDIterStart(epd_iter,"wac.epd");

  while (EPDIterNext(epd_iter,board,NULL,NULL)) {
    BoardShow (board); 
    GenMoves (board,movelist);
    MoveListShow (board,movelist); 
    GenCnt+=movelist->gencnt;
    Output ("No. of moves generated = %lu\n\n", GenCnt);
  }
}


void TestNonCaptureList (void)
/****************************************************************************
 *  
 *  This routine reads in a *.epd file (EPD notation) and prints the 
 *  non-capturing moves for that position.  
 *
 ****************************************************************************/
{
  movelist_t movelist[1];
  board_t board[1];
  epd_iter_t epd_iter[1];
  unsigned long GenCnt;
  EPDIterInit(epd_iter);
  EPDIterStart(epd_iter,"wac.epd");
  while (EPDIterNext(epd_iter,board,NULL,NULL)) {
      BoardShow (board); 
      GenPseudoNonCaptures (board,movelist);
      MoveListFilter (board,movelist);
      GenCnt+=movelist->gencnt;
      MoveListShow (board,movelist); 
      Output ("No. of moves generated = %lu\n\n", GenCnt);
   }
}


void TestCaptureList (void)
/****************************************************************************
 *  
 *  This routine reads in a *.epd file (EPD notation) and prints the capture
 *  moves for that position.  
 *
 ****************************************************************************/
{
  movelist_t movelist[1];
  board_t board[1];
  epd_iter_t epd_iter[1];
  unsigned long GenCnt;
  EPDIterInit(epd_iter);
  EPDIterStart(epd_iter,"wac.epd");
  while (EPDIterNext(epd_iter,board,NULL,NULL))
   {
      BoardShow (board); 
      GenPseudoCaptures (board,movelist);
      MoveListFilter (board,movelist);
      MoveListShow (board,movelist); 
      GenCnt+=movelist->gencnt;
      Output ("No. of moves generated = %lu\n\n", GenCnt);
   }
}


#define NEVALS 30000

void TestEvalSpeed (void)
/***************************************************************************
 *
 *  This routine reads in the BK.epd and test the speed of the 
 *  evaluation routines.
 *
 ***************************************************************************/
{
   unsigned long i;
   struct timeval t1, t2;
   double et;
   board_t board[1];
   searchdata_t searchdata[1];
   searchstats_t searchstats[1];
   searchparams_t searchparams[1];
   SearchParamsCreate(searchparams,Protocol);
   epd_iter_t epd_iter[1];
   et = 0;
   EPDIterInit(epd_iter);
   EPDIterStart(epd_iter,"wac.epd");
   SearchStatsInit(searchstats);
   while (EPDIterNext(epd_iter,board,NULL,NULL))  
   {
     SearchDataInit(searchdata,board);
      gettimeofday (&t1, NULL);
      for (i = 0; i < NEVALS; i++)
      {
	(void) Evaluate (board, 
			 searchparams,
			 searchdata, 
			 searchstats,
			 -INFIN, 
			 INFIN);
      }
      gettimeofday (&t2, NULL);
      et += (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec)/1e6;
      Output ("Time = %f\n", et);
   }
   Output ("No. of positions evaluated = %lu\n", searchstats->EvalCnt);
   Output ("Time taken = %f\n", et);
   if (et > 0)
      Output ("Rate = %f\n", searchstats->EvalCnt / et);  
}



void TestEval (void)
/**************************************************************************
 *
 *  To test the evaluation routines,  read from the BK.epd test file.
 *  Print out the score.  This can be improved by being more verbose
 *  and printing out salient features of the board, e.g. King safety,
 *  double bishops, rook on seventh rank, weak pawns, doubled pawns,
 *  bad bishops, passwd pawns, etc etc.
 *
 ***************************************************************************/
{
   int score;
   board_t board[1];
   searchdata_t searchdata[1];
   searchstats_t searchstats[1];
   searchparams_t searchparams[1];
   SearchParamsCreate(searchparams,Protocol);
   epd_iter_t epd_iter[1];
   EPDIterInit(epd_iter);
   EPDIterStart(epd_iter,"wac.epd");
   while (EPDIterNext(epd_iter,board,NULL,NULL))
   {
      BoardShow (board);
      SearchDataInit(searchdata,board);
      SearchStatsInit(searchstats);
      score = Evaluate (board,
			searchparams,
			searchdata, 
			searchstats,
			-INFIN, 
			INFIN);
      Output (board->side == white ? "W : " : "B : ");
      Output ("score = %d\n\n", score);
   }
}

