Fixed bug in the search, now no more near-mate values should randomly appear.
[rattatechess.git] / engine.cpp
blob1966881b7bf176ad8f91c43e588f56c5ced4e90e
1 /***************************************************************************
2 engine.cpp - description
3 -------------------
4 begin : mer ott 23 2002
5 copyright : (C) 2002-2005 by Maurizio Monge
6 email : monge@linuz.sns.it
7 ***************************************************************************/
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
18 #include "engine.h"
19 #include "utils.h"
20 #include "commands.h"
21 #include "search_gui.h"
22 #include <string.h>
24 Engine* Engine::instance = NULL;
26 Engine* Engine::eng()
28 return instance;
31 Engine::Engine()
33 instance = this;
35 mv_done = new Move[4096];
36 mv_done_num = 0;
38 save_buf = new SaveBuf[4096];
39 save_buf_num = 0;
41 create_hash();
42 reset_hash();
44 analysis_limit = TIME_LIMIT;
45 time_fixed = 2;
47 st_computer_color = BLACK;
48 status = PLAYING;
49 eng_status = PLAYING;
50 thinking = false;
51 status_string = NULL;
52 post = true;
53 ponder = false;
55 io_xboard = false;
56 io_san = false;
57 io_colors = false;
59 current_root = NULL;
61 /* register engine commands */
62 register_commands();
64 /* register engine variables */
65 register_variables();
67 /* open log file */
68 log = fopen("rattatechess.log", "w");
70 /* open the book */
71 book_mmap = NULL;
73 srand(time(NULL));
74 board.set_as_default();
76 load_ini();
79 unsigned char Engine::color_to_move()
81 return board.color_to_move;
84 unsigned char Engine::computer_color()
86 return st_computer_color;
89 int Engine::get_status()
91 return status;
94 int Engine::move_number()
96 return board.num_moves;
99 void Engine::start()
101 st_computer_color = board.color_to_move;
102 status = PLAYING;
103 status_string = NULL;
104 eng_status = PLAYING;
105 //output("starting!\n");
106 if(thinking)
107 longjmp(back, 1);
110 void Engine::start(unsigned char color)
112 st_computer_color = color;
113 status = PLAYING;
114 status_string = NULL;
115 eng_status = PLAYING;
116 if(thinking)
117 longjmp(back, 1);
120 void Engine::force()
122 st_computer_color = 0;
123 eng_status = FORCING;
124 if(thinking)
125 longjmp(back, 1);
128 void Engine::analyze()
130 st_computer_color = 0;
131 HashKey h = board.hash;
132 find_best_move();
134 /* exited analyzing without any move being done?
135 (because of a near mate or a book entry found) */
136 while(eng_status==ANALYZING && h == board.hash)
137 process_input();
140 void Engine::do_ponder()
142 HashKey h = board.hash;
143 find_best_move();
145 /* exited pondering without any move being done?
146 (because of a near mate or a book entry found) */
147 while(ponder && eng_status==PLAYING &&
148 st_computer_color == board.other_color && h == board.hash)
149 process_input();
152 void Engine::move_now()
154 if(!thinking)
156 output("You cannot use this command now!\n");
157 return;
160 longjmp(back, 1);
163 /* do the move and update a couple of things */
164 void Engine::move(Move mv)
166 /* save the move in the stack of played moves (from the starting position) */
167 mv_done[mv_done_num++] = mv;
169 board.do_move(mv, save_buf[save_buf_num++]);
171 if(board.insufficient_material())
173 status=_12;
174 status_string = "Insufficient material";
175 return;
178 /* 50mvs rule */
179 if(board.fifty >= 100)
181 status=_12;
182 status_string = "Drawn by 50-move rule";
183 return;
186 /* draw by 3fold repetition */
187 if(check_repetition(3))
189 status = _12;
190 status_string = "Drawn by 3-fold repetition";
191 return;
194 Move mvs[250];
195 if(board.find_moves(mvs)==0) //mate or stalemate...
197 if(board.under_check)
199 if(board.color_to_move==WHITE)
201 status = _01;
202 status_string = "Black mates";
204 else
206 status = _10;
207 status_string = "White mates";
210 else
212 status = _12;
213 status_string = "Stalemate";
215 return;
219 void Engine::retract_move()
221 if(mv_done_num>1)
223 board.undo_move(mv_done[--mv_done_num], save_buf[--save_buf_num]);
224 board.undo_move(mv_done[--mv_done_num], save_buf[--save_buf_num]);
228 void Engine::undo()
230 if(mv_done_num>0)
231 board.undo_move(mv_done[--mv_done_num], save_buf[--save_buf_num]);
232 status = PLAYING;
235 void Engine::new_game()
237 mv_done_num = 0;
238 analysis_limit = TIME_LIMIT;
239 time_fixed = 2;
240 st_computer_color = BLACK;
241 status = PLAYING;
242 eng_status = PLAYING;
244 strcpy(opponent, "<unknown>");
245 w_rating = 0;
246 b_rating = 0;
248 board.set_as_default();
249 reset_hash();
252 void Engine::set_depth(int d)
254 analysis_limit = DEPTH_LIMIT;
255 st_depth = d;
258 void Engine::set_max_nodes(int d)
260 analysis_limit = NODES_LIMIT;
261 st_nodes = d;
264 void Engine::set_time_fixed(int t)
266 analysis_limit = TIME_LIMIT;
267 time_fixed = t;
270 void Engine::set_time_control(int mps, int basesec, int inc)
272 analysis_limit = TIME_LIMIT;
273 time_fixed = 0;
274 time_mps = mps;
275 time_base = basesec;
276 time_inc = inc;
277 time_clock_csec = time_base*100;
280 void Engine::set_my_clock(int t)
282 time_clock_csec = t;
285 void Engine::set_other_clock(int t)
287 time_oth_clock_csec = t;
290 void Engine::print_board()
292 board.print_board();
295 void Engine::read_board(char* brd, char* color, char* castle,
296 char* passing, int moves_to_draw, int num_moves)
298 board.read_board(brd, color,castle,passing,moves_to_draw,num_moves);
299 mv_done_num = 0;
300 reset_hash();
301 if(thinking)
302 longjmp(back, 1);
305 void Engine::read_board(char* str)
307 board.read_board(str);
308 mv_done_num = 0;
309 reset_hash();
310 if(thinking)
311 longjmp(back, 1);
314 void Engine::read_board(FILE* f)
316 char str[256];
317 fgets(str,256,f);
318 board.read_board(str);
321 void Engine::write_board(FILE* f)
323 fputs( board.to_fen(BigStr().data()), f );
326 bool Engine::check_time()
328 processed_nodes++;
330 if( eng_status == PLAYING &&
331 analysis_limit == NODES_LIMIT &&
332 processed_nodes > (unsigned int)st_nodes)
333 longjmp(back, 1);
335 if( (processed_nodes%4096) == 0 )
337 if( eng_status == PLAYING &&
338 analysis_limit == TIME_LIMIT &&
339 current_time()>=max_think_time )
340 longjmp(back, 1);
342 if(search_gui) search_gui->process_events();
344 if(input_available())
346 int n = mv_done_num;
349 process_input();
351 if(n != mv_done_num)
352 longjmp(back, 1);
354 if(eng_status == PLAYING && !ponder
355 && st_computer_color == board.other_color)
356 longjmp(back, 1);
358 while(input_available());
361 return false;
364 //very primitive
365 void Engine::calc_best_time()
367 if(time_fixed)
368 time_best_csec = time_fixed * 100;
369 else
371 int nummoves = (time_mps == 0) ? 30 :
372 MAX((time_mps - (board.num_moves % time_mps)), 30);
373 time_best_csec = time_clock_csec / nummoves + time_inc * 100;
374 //time_best_csec = time_clock_csec / nummoves * (50 + rand()%300) / 200 + time_inc * 100;
378 uint64_t Engine::perft(int lev)
380 Move mv_stack[200];
381 int num;
382 num = board.find_moves(mv_stack);
384 if(lev==1)
385 return num;
386 else
388 uint64_t retv=0;
389 for(int i=0;i<num;i++)
391 board.do_move(mv_stack[i], save_buf[save_buf_num++]);
392 retv+=perft(lev-1);
393 board.undo_move(mv_stack[i], save_buf[--save_buf_num]);
395 return retv;
399 void Engine::autotune()
401 struct Tunable { const char* name; int& param; int start; int end; int step; };
402 Tunable data[] = {
403 { "v_search_threat_threshold", v_search_threat_threshold, 150, 720, 190 },
404 { "v_search_threat_extension", v_search_threat_extension, 40, 120, 80 },
405 { "v_search_null_reduction", v_search_null_reduction, 200, 400, 100 },
407 int numparams = sizeof(data)/sizeof(Tunable);
409 for(int i=0;i<3;i++)
410 for(int p=0;p<numparams;p++)
412 int oldv = data[p].param;
413 int best = 0;
414 int best_goodness = -1;
415 int worst_goodness = 99999;
417 for(data[p].param = data[p].start; data[p].param <= data[p].end; data[p].param += data[p].step)
419 output("\n");
420 for(int k=0;k<numparams;k++)
421 output("%s = %d%s\n", data[k].name, data[k].param, k==p ? " <--" : "");
422 int goodness = run_epd_prog("self", 1, "epd/abbe.epd");
423 if(goodness > best_goodness)
425 best_goodness = goodness;
426 best = data[p].param;
428 if(goodness < worst_goodness)
429 worst_goodness = goodness;
432 if(worst_goodness == best_goodness)
433 data[p].param = oldv;
434 else
435 data[p].param = best;
438 output("\n");
439 output("FINAL REPORT:\n");
440 for(int k=0;k<numparams;k++)
441 output("%s = %d\n", data[k].name, data[k].param);
442 exit(0);