1 /***************************************************************************
2 engine.cpp - description
4 begin : mer ott 23 2002
5 copyright : (C) 2002-2005 by Maurizio Monge
6 email : monge@linuz.sns.it
7 ***************************************************************************/
9 /***************************************************************************
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. *
16 ***************************************************************************/
21 #include "search_gui.h"
24 Engine
* Engine::instance
= NULL
;
35 mv_done
= new Move
[400];
38 save_buf
= new SaveBuf
[4096];
44 analysis_limit
= TIME_LIMIT
;
47 st_computer_color
= BLACK
;
59 /* register engine commands */
62 /* register engine variables */
66 log
= fopen("rattatechess.log", "w");
70 if(!open_book("ratta.book"))
71 if(!open_book("../ratta.book"))
74 snprintf(buf
, 1024, "%s/ratta.book", getenv("HOME"));
78 /* open the play lines */
79 if(!open_lines("ratta.lines"))
80 if(!open_lines("../ratta.lines"))
83 snprintf(buf
, 1024, "%s/ratta.lines", getenv("HOME"));
88 board
.set_as_default();
91 unsigned char Engine::color_to_move()
93 return board
.color_to_move
;
96 unsigned char Engine::computer_color()
98 return st_computer_color
;
101 int Engine::get_status()
106 int Engine::move_number()
108 return board
.num_moves
;
113 st_computer_color
= board
.color_to_move
;
115 status_string
= NULL
;
116 eng_status
= PLAYING
;
117 //output("starting!\n");
122 void Engine::start(unsigned char color
)
124 st_computer_color
= color
;
126 status_string
= NULL
;
127 eng_status
= PLAYING
;
134 st_computer_color
= 0;
135 eng_status
= FORCING
;
140 void Engine::analyze()
142 st_computer_color
= 0;
143 HashKey h
= board
.hash
;
146 /* exited analyzing without any move being done?
147 (because of a near mate or a book entry found) */
148 while(eng_status
==ANALYZING
&& h
== board
.hash
)
152 void Engine::do_ponder()
154 HashKey h
= board
.hash
;
157 /* exited pondering without any move being done?
158 (because of a near mate or a book entry found) */
159 while(ponder
&& eng_status
==PLAYING
&&
160 st_computer_color
== board
.other_color
&& h
== board
.hash
)
164 void Engine::move_now()
168 output("You cannot use this command now!\n");
175 /* do the move and update a couple of things */
176 void Engine::move(Move mv
)
178 /* save the move in the stack of played moves (from the starting position) */
179 mv_done
[mv_done_num
++] = mv
;
181 board
.do_move(mv
, save_buf
[save_buf_num
++]);
183 if(board
.insufficient_material())
186 status_string
= "Insufficient material";
191 if(board
.fifty
>= 100)
194 status_string
= "Drawn by 50-move rule";
198 /* draw by 3fold repetition */
199 if(check_repetition(3))
202 status_string
= "Drawn by 3-fold repetition";
207 if(board
.find_moves(mvs
)==0) //mate or stalemate...
209 if(board
.under_check
)
211 if(board
.color_to_move
==WHITE
)
214 status_string
= "Black mates";
219 status_string
= "White mates";
225 status_string
= "Stalemate";
231 void Engine::retract_move()
235 board
.undo_move(mv_done
[--mv_done_num
], save_buf
[--save_buf_num
]);
236 board
.undo_move(mv_done
[--mv_done_num
], save_buf
[--save_buf_num
]);
243 board
.undo_move(mv_done
[--mv_done_num
], save_buf
[--save_buf_num
]);
247 void Engine::new_game()
250 analysis_limit
= TIME_LIMIT
;
252 st_computer_color
= BLACK
;
254 eng_status
= PLAYING
;
256 strcpy(opponent
, "<unknown>");
260 board
.set_as_default();
264 void Engine::set_depth(int d
)
266 analysis_limit
= DEPTH_LIMIT
;
270 void Engine::set_max_nodes(int d
)
272 analysis_limit
= NODES_LIMIT
;
276 void Engine::set_time_fixed(int t
)
278 analysis_limit
= TIME_LIMIT
;
282 void Engine::set_time_control(int mps
, int basesec
, int inc
)
284 analysis_limit
= TIME_LIMIT
;
289 time_clock_csec
= time_base
*100;
292 void Engine::set_my_clock(int t
)
297 void Engine::set_other_clock(int t
)
299 time_oth_clock_csec
= t
;
302 void Engine::print_board()
307 void Engine::read_board(char* brd
, char* color
, char* castle
,
308 char* passing
, int moves_to_draw
, int num_moves
)
310 board
.read_board(brd
, color
,castle
,passing
,moves_to_draw
,num_moves
);
317 void Engine::read_board(char* str
)
319 board
.read_board(str
);
326 void Engine::read_board(FILE* f
)
330 board
.read_board(str
);
333 void Engine::write_board(FILE* f
)
336 board
.write_board(str
);
340 bool Engine::check_time()
344 if( eng_status
== PLAYING
&&
345 analysis_limit
== NODES_LIMIT
&&
346 processed_nodes
> (unsigned int)st_nodes
)
349 if( (processed_nodes
%4096) == 0 )
351 if( eng_status
== PLAYING
&&
352 analysis_limit
== TIME_LIMIT
&&
353 current_time()>=max_think_time
)
356 if(search_gui
) search_gui
->process_events();
358 if(input_available())
368 if(eng_status
== PLAYING
&& !ponder
369 && st_computer_color
== board
.other_color
)
372 while(input_available());
379 void Engine::calc_best_time()
382 time_best_csec
= time_fixed
* 100;
385 int nummoves
= (time_mps
== 0) ? 30 :
386 MAX((time_mps
- (board
.num_moves
% time_mps
)), 30);
387 time_best_csec
= time_clock_csec
/ nummoves
+ time_inc
* 100;
388 //time_best_csec = time_clock_csec / nummoves * (50 + rand()%300) / 200 + time_inc * 100;
392 uint64_t Engine::perft(int lev
)
396 num
= board
.find_moves(mv_stack
);
403 for(int i
=0;i
<num
;i
++)
405 board
.do_move(mv_stack
[i
], save_buf
[save_buf_num
++]);
407 board
.undo_move(mv_stack
[i
], save_buf
[--save_buf_num
]);
413 void Engine::autotune()
415 struct Tunable
{ const char* name
; int& param
; int start
; int end
; int step
; };
417 { "v_search_threat_threshold", v_search_threat_threshold
, 150, 720, 190 },
418 { "v_search_threat_extension", v_search_threat_extension
, 40, 120, 80 },
419 { "v_search_null_reduction", v_search_null_reduction
, 200, 400, 100 },
421 int numparams
= sizeof(data
)/sizeof(Tunable
);
424 for(int p
=0;p
<numparams
;p
++)
426 int oldv
= data
[p
].param
;
428 int best_goodness
= -1;
429 int worst_goodness
= 99999;
431 for(data
[p
].param
= data
[p
].start
; data
[p
].param
<= data
[p
].end
; data
[p
].param
+= data
[p
].step
)
434 for(int k
=0;k
<numparams
;k
++)
435 output("%s = %d%s\n", data
[k
].name
, data
[k
].param
, k
==p
? " <--" : "");
436 int goodness
= run_epd_prog("self", 1, "epd/abbe.epd");
437 if(goodness
> best_goodness
)
439 best_goodness
= goodness
;
440 best
= data
[p
].param
;
442 if(goodness
< worst_goodness
)
443 worst_goodness
= goodness
;
446 if(worst_goodness
== best_goodness
)
447 data
[p
].param
= oldv
;
449 data
[p
].param
= best
;
453 output("FINAL REPORT:\n");
454 for(int k
=0;k
<numparams
;k
++)
455 output("%s = %d\n", data
[k
].name
, data
[k
].param
);