version 1.4.30b
[polyglot.git] / search.c
diff --git a/search.c b/search.c
new file mode 100644 (file)
index 0000000..524a874
--- /dev/null
+++ b/search.c
@@ -0,0 +1,252 @@
+// 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