Cleaned print_moves, no more hash lookups
[rattatechess.git] / engine.cpp
blob1816316613cb6fa70edd97adde6ee88085a49d59
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[400];
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 /* register engine commands */
60 register_commands();
62 /* register engine variables */
63 register_variables();
65 /* open log file */
66 log = fopen("rattatechess.log", "w");
68 /* open the book */
69 book_mmap = NULL;
71 srand(time(NULL));
72 board.set_as_default();
74 load_ini();
77 unsigned char Engine::color_to_move()
79 return board.color_to_move;
82 unsigned char Engine::computer_color()
84 return st_computer_color;
87 int Engine::get_status()
89 return status;
92 int Engine::move_number()
94 return board.num_moves;
97 void Engine::start()
99 st_computer_color = board.color_to_move;
100 status = PLAYING;
101 status_string = NULL;
102 eng_status = PLAYING;
103 //output("starting!\n");
104 if(thinking)
105 longjmp(back, 1);
108 void Engine::start(unsigned char color)
110 st_computer_color = color;
111 status = PLAYING;
112 status_string = NULL;
113 eng_status = PLAYING;
114 if(thinking)
115 longjmp(back, 1);
118 void Engine::force()
120 st_computer_color = 0;
121 eng_status = FORCING;
122 if(thinking)
123 longjmp(back, 1);
126 void Engine::analyze()
128 st_computer_color = 0;
129 HashKey h = board.hash;
130 find_best_move();
132 /* exited analyzing without any move being done?
133 (because of a near mate or a book entry found) */
134 while(eng_status==ANALYZING && h == board.hash)
135 process_input();
138 void Engine::do_ponder()
140 HashKey h = board.hash;
141 find_best_move();
143 /* exited pondering without any move being done?
144 (because of a near mate or a book entry found) */
145 while(ponder && eng_status==PLAYING &&
146 st_computer_color == board.other_color && h == board.hash)
147 process_input();
150 void Engine::move_now()
152 if(!thinking)
154 output("You cannot use this command now!\n");
155 return;
158 longjmp(back, 1);
161 /* do the move and update a couple of things */
162 void Engine::move(Move mv)
164 /* save the move in the stack of played moves (from the starting position) */
165 mv_done[mv_done_num++] = mv;
167 board.do_move(mv, save_buf[save_buf_num++]);
169 if(board.insufficient_material())
171 status=_12;
172 status_string = "Insufficient material";
173 return;
176 /* 50mvs rule */
177 if(board.fifty >= 100)
179 status=_12;
180 status_string = "Drawn by 50-move rule";
181 return;
184 /* draw by 3fold repetition */
185 if(check_repetition(3))
187 status = _12;
188 status_string = "Drawn by 3-fold repetition";
189 return;
192 Move mvs[250];
193 if(board.find_moves(mvs)==0) //mate or stalemate...
195 if(board.under_check)
197 if(board.color_to_move==WHITE)
199 status = _01;
200 status_string = "Black mates";
202 else
204 status = _10;
205 status_string = "White mates";
208 else
210 status = _12;
211 status_string = "Stalemate";
213 return;
217 void Engine::retract_move()
219 if(mv_done_num>1)
221 board.undo_move(mv_done[--mv_done_num], save_buf[--save_buf_num]);
222 board.undo_move(mv_done[--mv_done_num], save_buf[--save_buf_num]);
226 void Engine::undo()
228 if(mv_done_num>0)
229 board.undo_move(mv_done[--mv_done_num], save_buf[--save_buf_num]);
230 status = PLAYING;
233 void Engine::new_game()
235 mv_done_num = 0;
236 analysis_limit = TIME_LIMIT;
237 time_fixed = 2;
238 st_computer_color = BLACK;
239 status = PLAYING;
240 eng_status = PLAYING;
242 strcpy(opponent, "<unknown>");
243 w_rating = 0;
244 b_rating = 0;
246 board.set_as_default();
247 reset_hash();
250 void Engine::set_depth(int d)
252 analysis_limit = DEPTH_LIMIT;
253 st_depth = d;
256 void Engine::set_max_nodes(int d)
258 analysis_limit = NODES_LIMIT;
259 st_nodes = d;
262 void Engine::set_time_fixed(int t)
264 analysis_limit = TIME_LIMIT;
265 time_fixed = t;
268 void Engine::set_time_control(int mps, int basesec, int inc)
270 analysis_limit = TIME_LIMIT;
271 time_fixed = 0;
272 time_mps = mps;
273 time_base = basesec;
274 time_inc = inc;
275 time_clock_csec = time_base*100;
278 void Engine::set_my_clock(int t)
280 time_clock_csec = t;
283 void Engine::set_other_clock(int t)
285 time_oth_clock_csec = t;
288 void Engine::print_board()
290 board.print_board();
293 void Engine::read_board(char* brd, char* color, char* castle,
294 char* passing, int moves_to_draw, int num_moves)
296 board.read_board(brd, color,castle,passing,moves_to_draw,num_moves);
297 mv_done_num = 0;
298 reset_hash();
299 if(thinking)
300 longjmp(back, 1);
303 void Engine::read_board(char* str)
305 board.read_board(str);
306 mv_done_num = 0;
307 reset_hash();
308 if(thinking)
309 longjmp(back, 1);
312 void Engine::read_board(FILE* f)
314 char str[256];
315 fgets(str,256,f);
316 board.read_board(str);
319 void Engine::write_board(FILE* f)
321 fputs( board.to_fen(BigStr().data()), f );
324 bool Engine::check_time()
326 processed_nodes++;
328 if( eng_status == PLAYING &&
329 analysis_limit == NODES_LIMIT &&
330 processed_nodes > (unsigned int)st_nodes)
331 longjmp(back, 1);
333 if( (processed_nodes%4096) == 0 )
335 if( eng_status == PLAYING &&
336 analysis_limit == TIME_LIMIT &&
337 current_time()>=max_think_time )
338 longjmp(back, 1);
340 if(search_gui) search_gui->process_events();
342 if(input_available())
344 int n = mv_done_num;
347 process_input();
349 if(n != mv_done_num)
350 longjmp(back, 1);
352 if(eng_status == PLAYING && !ponder
353 && st_computer_color == board.other_color)
354 longjmp(back, 1);
356 while(input_available());
359 return false;
362 //very primitive
363 void Engine::calc_best_time()
365 if(time_fixed)
366 time_best_csec = time_fixed * 100;
367 else
369 int nummoves = (time_mps == 0) ? 30 :
370 MAX((time_mps - (board.num_moves % time_mps)), 30);
371 time_best_csec = time_clock_csec / nummoves + time_inc * 100;
372 //time_best_csec = time_clock_csec / nummoves * (50 + rand()%300) / 200 + time_inc * 100;
376 uint64_t Engine::perft(int lev)
378 Move mv_stack[200];
379 int num;
380 num = board.find_moves(mv_stack);
382 if(lev==1)
383 return num;
384 else
386 uint64_t retv=0;
387 for(int i=0;i<num;i++)
389 board.do_move(mv_stack[i], save_buf[save_buf_num++]);
390 retv+=perft(lev-1);
391 board.undo_move(mv_stack[i], save_buf[--save_buf_num]);
393 return retv;
397 void Engine::autotune()
399 struct Tunable { const char* name; int& param; int start; int end; int step; };
400 Tunable data[] = {
401 { "v_search_threat_threshold", v_search_threat_threshold, 150, 720, 190 },
402 { "v_search_threat_extension", v_search_threat_extension, 40, 120, 80 },
403 { "v_search_null_reduction", v_search_null_reduction, 200, 400, 100 },
405 int numparams = sizeof(data)/sizeof(Tunable);
407 for(int i=0;i<3;i++)
408 for(int p=0;p<numparams;p++)
410 int oldv = data[p].param;
411 int best = 0;
412 int best_goodness = -1;
413 int worst_goodness = 99999;
415 for(data[p].param = data[p].start; data[p].param <= data[p].end; data[p].param += data[p].step)
417 output("\n");
418 for(int k=0;k<numparams;k++)
419 output("%s = %d%s\n", data[k].name, data[k].param, k==p ? " <--" : "");
420 int goodness = run_epd_prog("self", 1, "epd/abbe.epd");
421 if(goodness > best_goodness)
423 best_goodness = goodness;
424 best = data[p].param;
426 if(goodness < worst_goodness)
427 worst_goodness = goodness;
430 if(worst_goodness == best_goodness)
431 data[p].param = oldv;
432 else
433 data[p].param = best;
436 output("\n");
437 output("FINAL REPORT:\n");
438 for(int k=0;k<numparams;k++)
439 output("%s = %d\n", data[k].name, data[k].param);
440 exit(0);