--- /dev/null
+// search.c\r
+\r
+// includes\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "attack.h"\r
+#include "board.h"\r
+#include "colour.h"\r
+#include "engine.h"\r
+#include "fen.h"\r
+#include "line.h"\r
+#include "list.h"\r
+#include "move.h"\r
+#include "move_do.h"\r
+#include "move_gen.h"\r
+#include "move_legal.h"\r
+#include "option.h"\r
+#include "parse.h"\r
+#include "san.h"\r
+#include "search.h"\r
+#include "uci.h"\r
+#include "util.h"\r
+\r
+// constants\r
+\r
+static const int StringSize = 4096;\r
+\r
+// variables\r
+\r
+static int Depth;\r
+\r
+static int BestMove;\r
+static int BestValue;\r
+static move_t BestPV[LineSize];\r
+\r
+static sint64 NodeNb;\r
+static sint64 LeafNb;\r
+static double Time;\r
+\r
+static int Move;\r
+static int MovePos;\r
+static int MoveNb;\r
+\r
+// prototypes\r
+\r
+static bool depth_is_ok (int depth);\r
+static void perft (const board_t * board, int depth);\r
+\r
+// functions\r
+\r
+// depth_is_ok()\r
+\r
+static bool depth_is_ok(int depth) {\r
+\r
+ return depth >= 0 && depth < DepthMax;\r
+}\r
+\r
+// search()\r
+\r
+void search(const board_t * board, int depth_max, double time_max) {\r
+\r
+ char string[256];\r
+\r
+ ASSERT(board_is_ok(board));\r
+ ASSERT(depth_max>=1&&depth_max<DepthMax);\r
+ ASSERT(time_max>=0.0);\r
+\r
+ // engine\r
+\r
+ Depth = 0;\r
+\r
+ BestMove = MoveNone;\r
+ BestValue = 0;\r
+ line_clear(BestPV);\r
+\r
+ NodeNb = 0;\r
+ LeafNb = 0;\r
+ Time = 0.0;\r
+\r
+ Move = MoveNone;\r
+ MovePos = 0;\r
+ MoveNb = 0;\r
+\r
+ // init\r
+\r
+ uci_send_ucinewgame(Uci);\r
+ uci_send_isready_sync(Uci);\r
+\r
+ // position\r
+\r
+ if (!board_to_fen(board,string,256)) ASSERT(FALSE);\r
+ engine_send(Engine,"position fen %s",string);\r
+\r
+ // search\r
+\r
+ engine_send_queue(Engine,"go");\r
+\r
+ engine_send_queue(Engine," movetime %.0f",time_max*1000.0);\r
+ engine_send_queue(Engine," depth %d",depth_max);\r
+\r
+ engine_send(Engine,""); // newline\r
+\r
+ // wait for feed-back\r
+\r
+ while (!engine_eof(Engine)) {\r
+\r
+ engine_get(Engine,string);\r
+\r
+ if (FALSE) {\r
+\r
+ } else if (match(string,"bestmove * ponder *")) {\r
+\r
+ BestMove = move_from_can(Star[0],board);\r
+ ASSERT(BestMove!=MoveNone&&move_is_legal(BestMove,board));\r
+\r
+ break;\r
+\r
+ } else if (match(string,"bestmove *")) {\r
+\r
+ BestMove = move_from_can(Star[0],board);\r
+ ASSERT(BestMove!=MoveNone&&move_is_legal(BestMove,board));\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ printf("\n");\r
+}\r
+\r
+// do_perft()\r
+\r
+void do_perft(int argc,char * argv[]){\r
+ const char * fen=NULL;\r
+ int depth=1;\r
+ board_t board[1];\r
+ int i;\r
+ for (i = 1; i < argc; i++) {\r
+ if (FALSE) {\r
+ } else if (my_string_equal(argv[i],"perft")) {\r
+ // skip\r
+ } else if (my_string_equal(argv[i],"-fen")) {\r
+ i++;\r
+ if (argv[i] == NULL) my_fatal("do_perft(): missing argument\n");\r
+ my_string_set(&fen,argv[i]);\r
+ } else if (my_string_equal(argv[i],"-max-depth")){\r
+ i++;\r
+ if (argv[i] == NULL) my_fatal("do_perft(): missing argument\n");\r
+ depth=atoi(argv[i]);\r
+ if(depth<1) my_fatal("do_perft(): illegal depth %d\n",depth);\r
+ } else {\r
+ my_fatal("do_perft(): unknown option \"%s\"\n",argv[i]);\r
+ }\r
+ }\r
+ if(fen==NULL){\r
+ my_string_set(&fen,StartFen);\r
+ }\r
+ board_from_fen(board,fen);\r
+ search_perft(board,depth);\r
+}\r
+\r
+// search_perft()\r
+\r
+void search_perft(const board_t * board, int depth_max) {\r
+\r
+ int depth;\r
+ my_timer_t timer[1];\r
+ double time, speed;\r
+ char node_string[StringSize];\r
+ char leafnode_string[StringSize];\r
+\r
+ ASSERT(board_is_ok(board));\r
+ ASSERT(depth_max>=1&&depth_max<DepthMax);\r
+\r
+ // init\r
+\r
+ board_disp(board);\r
+\r
+ // iterative deepening\r
+\r
+ for (depth = 1; depth <= depth_max; depth++) {\r
+\r
+ // init\r
+\r
+ NodeNb = 0;\r
+ LeafNb = 0;\r
+\r
+ my_timer_reset(timer);\r
+\r
+ my_timer_start(timer);\r
+ perft(board,depth);\r
+ my_timer_stop(timer);\r
+\r
+ time = my_timer_elapsed_real(timer);//my_timer_elapsed_cpu(timer);\r
+ speed = (time < 0.01) ? 0.0 : ((double)NodeNb) / time;\r
+\r
+ snprintf(node_string,StringSize,S64_FORMAT,NodeNb);\r
+ snprintf(leafnode_string,StringSize,S64_FORMAT,LeafNb);\r
+\r
+ printf("depth=%2d nodes=%12s leafnodes=%12s time=%7.2fs nps=%8.0f\n",depth,node_string,leafnode_string,time,speed);\r
+ }\r
+\r
+}\r
+\r
+// perft()\r
+\r
+static void perft(const board_t * board, int depth) {\r
+\r
+ int me;\r
+ list_t list[1];\r
+ int i, move;\r
+ board_t new_board[1];\r
+\r
+ ASSERT(board_is_ok(board));\r
+ ASSERT(depth_is_ok(depth));\r
+\r
+ ASSERT(!is_in_check(board,colour_opp(board->turn)));\r
+\r
+ // init\r
+\r
+ NodeNb++;\r
+\r
+ // leaf\r
+\r
+ if (depth == 0) {\r
+ LeafNb++;\r
+ return;\r
+ }\r
+\r
+ // more init\r
+\r
+ me = board->turn;\r
+\r
+ // move loop\r
+\r
+ gen_moves(list,board);\r
+\r
+ for (i = 0; i < list_size(list); i++) {\r
+\r
+ move = list_move(list,i);\r
+\r
+ board_copy(new_board,board);\r
+ move_do(new_board,move);\r
+\r
+ if (!is_in_check(new_board,me)) perft(new_board,depth-1);\r
+ }\r
+}\r
+\r
+// end of search.cpp\r
+\r