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];
41 analysis_limit
= TIME_LIMIT
;
44 st_computer_color
= BLACK
;
56 /* register engine commands */
59 /* register engine variables */
63 log
= fopen("rattatechess.log", "w");
67 if(!open_book("ratta.book"))
68 if(!open_book("../ratta.book"))
71 snprintf(buf
, 1024, "%s/ratta.book", getenv("HOME"));
75 /* open the play lines */
76 if(!open_lines("ratta.lines"))
77 if(!open_lines("../ratta.lines"))
80 snprintf(buf
, 1024, "%s/ratta.lines", getenv("HOME"));
85 board
.set_as_default();
88 unsigned char Engine::color_to_move()
90 return board
.color_to_move
;
93 unsigned char Engine::computer_color()
95 return st_computer_color
;
98 int Engine::get_status()
103 int Engine::move_number()
105 return board
.num_moves
;
110 st_computer_color
= board
.color_to_move
;
112 status_string
= NULL
;
113 eng_status
= PLAYING
;
114 //output("starting!\n");
119 void Engine::start(unsigned char color
)
121 st_computer_color
= color
;
123 status_string
= NULL
;
124 eng_status
= PLAYING
;
131 st_computer_color
= 0;
132 eng_status
= FORCING
;
137 void Engine::analyze()
139 st_computer_color
= 0;
140 HashKey h
= board
.hash
;
143 /* exited analyzing without any move being done?
144 (because of a near mate or a book entry found) */
145 while(eng_status
==ANALYZING
&& h
== board
.hash
)
149 void Engine::do_ponder()
151 HashKey h
= board
.hash
;
154 /* exited pondering without any move being done?
155 (because of a near mate or a book entry found) */
156 while(ponder
&& eng_status
==PLAYING
&&
157 st_computer_color
== board
.other_color
&& h
== board
.hash
)
161 void Engine::move_now()
165 output("You cannot use this command now!\n");
172 /* do the move and update a couple of things */
173 void Engine::move(Move mv
)
175 /* save the move in the stack of played moves (from the starting position) */
176 mv_done
[mv_done_num
++] = mv
;
180 if(insufficient_material())
183 status_string
= "Insufficient material";
188 if(board
.fifty
>= 100)
191 status_string
= "Drawn by 50-move rule";
195 /* for the latest reversible moves check if the hash value
196 (for this player) is the same */
197 int first_candidate
= MAX(board
.num_old_hashes
-(board
.fifty
/2)*2, 0);
199 for(int i
=board
.num_old_hashes
-4;i
>=first_candidate
;i
-=2)
201 if(board
.hash
== board
.old_hashes
[i
])
206 status_string
= "Drawn by 3-fold repetition";
212 if(board
.find_moves(mvs
)==0) //mate or stalemate...
214 if(board
.under_check
)
216 if(board
.color_to_move
==WHITE
)
219 status_string
= "Black mates";
224 status_string
= "White mates";
230 status_string
= "Stalemate";
236 void Engine::retract_move()
239 board
.undo_move(mv_done
[--mv_done_num
]);
240 board
.undo_move(mv_done
[--mv_done_num
]);
246 board
.undo_move(mv_done
[--mv_done_num
]);
250 void Engine::new_game()
253 analysis_limit
= TIME_LIMIT
;
255 st_computer_color
= BLACK
;
257 eng_status
= PLAYING
;
259 strcpy(opponent
, "<unknown>");
263 board
.set_as_default();
267 void Engine::set_depth(int d
)
269 analysis_limit
= DEPTH_LIMIT
;
273 void Engine::set_max_nodes(int d
)
275 analysis_limit
= NODES_LIMIT
;
279 void Engine::set_time_fixed(int t
)
281 analysis_limit
= TIME_LIMIT
;
285 void Engine::set_time_control(int mps
, int basesec
, int inc
)
287 analysis_limit
= TIME_LIMIT
;
292 time_clock_csec
= time_base
*100;
295 void Engine::set_my_clock(int t
)
300 void Engine::set_other_clock(int t
)
302 time_oth_clock_csec
= t
;
305 void Engine::print_board()
310 void Engine::read_board(char* brd
, char* color
, char* castle
,
311 char* passing
, int moves_to_draw
, int num_moves
)
313 board
.read_board(brd
, color
,castle
,passing
,moves_to_draw
,num_moves
);
320 void Engine::read_board(char* str
)
322 board
.read_board(str
);
329 void Engine::read_board(FILE* f
)
333 board
.read_board(str
);
336 void Engine::write_board(FILE* f
)
339 board
.write_board(str
);
343 bool Engine::check_time()
348 if( eng_status
== PLAYING
&&
349 analysis_limit
== NODES_LIMIT
&&
350 processed_nodes
> (unsigned int)st_nodes
)
356 if( (processed_nodes
%4096) == 0 )
358 if( eng_status
== PLAYING
&&
359 analysis_limit
== TIME_LIMIT
&&
360 current_time()>=max_think_time
)
366 if(search_gui
) search_gui
->process_events();
368 if(input_available())
380 if(eng_status
== PLAYING
&& !ponder
381 && st_computer_color
== board
.other_color
)
384 while(input_available());
393 void Engine::calc_best_time()
396 time_best_csec
= time_fixed
* 100;
399 int nummoves
= (time_mps
== 0) ? 30 :
400 MAX((time_mps
- (board
.num_moves
% time_mps
)), 30);
401 time_best_csec
= time_clock_csec
/ nummoves
+ time_inc
* 100;
402 //time_best_csec = time_clock_csec / nummoves * (50 + rand()%300) / 200 + time_inc * 100;
406 uint64_t Engine::perft(int lev
)
410 num
= board
.find_moves(mv_stack
);
417 for(int i
=0;i
<num
;i
++)
419 board
.do_move(mv_stack
[i
]);
421 board
.undo_move(mv_stack
[i
]);
427 void Engine::autotune()
429 struct Tunable
{ const char* name
; int& param
; int start
; int end
; int step
; };
431 { "v_search_threat_threshold", v_search_threat_threshold
, 150, 720, 190 },
432 { "v_search_threat_extension", v_search_threat_extension
, 40, 120, 80 },
433 { "v_search_null_reduction", v_search_null_reduction
, 200, 400, 100 },
435 int numparams
= sizeof(data
)/sizeof(Tunable
);
438 for(int p
=0;p
<numparams
;p
++)
440 int oldv
= data
[p
].param
;
442 int best_goodness
= -1;
443 int worst_goodness
= 99999;
445 for(data
[p
].param
= data
[p
].start
; data
[p
].param
<= data
[p
].end
; data
[p
].param
+= data
[p
].step
)
448 for(int k
=0;k
<numparams
;k
++)
449 output("%s = %d%s\n", data
[k
].name
, data
[k
].param
, k
==p
? " <--" : "");
450 int goodness
= run_epd_prog("self", 1, "epd/abbe.epd");
451 if(goodness
> best_goodness
)
453 best_goodness
= goodness
;
454 best
= data
[p
].param
;
456 if(goodness
< worst_goodness
)
457 worst_goodness
= goodness
;
460 if(worst_goodness
== best_goodness
)
461 data
[p
].param
= oldv
;
463 data
[p
].param
= best
;
467 output("FINAL REPORT:\n");
468 for(int k
=0;k
<numparams
;k
++)
469 output("%s = %d\n", data
[k
].name
, data
[k
].param
);