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 ***************************************************************************/
23 Engine
* Engine::instance
= NULL
;
34 mv_done
= new Move
[400];
40 analysis_limit
= TIME_LIMIT
;
43 st_computer_color
= BLACK
;
55 /* register engine commands */
58 /* register engine variables */
62 log
= fopen("rattatechess.log", "w");
66 if(!open_book("ratta.book"))
67 if(!open_book("../ratta.book"))
70 snprintf(buf
, 1024, "%s/ratta.book", getenv("HOME"));
74 /* open the play lines */
75 if(!open_lines("ratta.lines"))
76 if(!open_lines("../ratta.lines"))
79 snprintf(buf
, 1024, "%s/ratta.lines", getenv("HOME"));
84 board
.set_as_default();
87 unsigned char Engine::color_to_move()
89 return board
.color_to_move
;
92 unsigned char Engine::computer_color()
94 return st_computer_color
;
97 int Engine::get_status()
102 int Engine::move_number()
104 return board
.num_moves
;
109 st_computer_color
= board
.color_to_move
;
111 status_string
= NULL
;
112 eng_status
= PLAYING
;
113 //output("starting!\n");
118 void Engine::start(unsigned char color
)
120 st_computer_color
= color
;
122 status_string
= NULL
;
123 eng_status
= PLAYING
;
130 st_computer_color
= 0;
131 eng_status
= FORCING
;
136 void Engine::analyze()
138 st_computer_color
= 0;
139 HashKey h
= board
.hash
;
142 /* exited analyzing without any move being done?
143 (because of a near mate or a book entry found) */
144 while(eng_status
==ANALYZING
&& h
== board
.hash
)
148 void Engine::do_ponder()
150 HashKey h
= board
.hash
;
153 /* exited pondering without any move being done?
154 (because of a near mate or a book entry found) */
155 while(ponder
&& eng_status
==PLAYING
&&
156 st_computer_color
== board
.other_color
&& h
== board
.hash
)
160 void Engine::move_now()
164 output("You cannot use this command now!\n");
171 /* do the move and update a couple of things */
172 void Engine::move(Move mv
)
174 /* save the move in the stack of played moves (from the starting position) */
175 mv_done
[mv_done_num
++] = mv
;
179 if(insufficient_material())
182 status_string
= "Insufficient material";
187 if(board
.fifty
>= 100)
190 status_string
= "Drawn by 50-move rule";
194 /* for the latest reversible moves check if the hash value
195 (for this player) is the same */
196 int first_candidate
= MAX(board
.num_old_hashes
-(board
.fifty
/2)*2, 0);
198 for(int i
=board
.num_old_hashes
-4;i
>=first_candidate
;i
-=2)
200 if(board
.hash
== board
.old_hashes
[i
])
205 status_string
= "Drawn by 3-fold repetition";
211 if(board
.find_moves(mvs
)==0) //mate or stalemate...
213 if(board
.under_check
)
215 if(board
.color_to_move
==WHITE
)
218 status_string
= "Black mates";
223 status_string
= "White mates";
229 status_string
= "Stalemate";
235 void Engine::retract_move()
238 board
.undo_move(mv_done
[--mv_done_num
]);
239 board
.undo_move(mv_done
[--mv_done_num
]);
245 board
.undo_move(mv_done
[--mv_done_num
]);
249 void Engine::new_game()
252 analysis_limit
= TIME_LIMIT
;
254 st_computer_color
= BLACK
;
256 eng_status
= PLAYING
;
258 strcpy(opponent
, "<unknown>");
262 board
.set_as_default();
266 void Engine::set_depth(int d
)
268 analysis_limit
= DEPTH_LIMIT
;
272 void Engine::set_max_nodes(int d
)
274 analysis_limit
= NODES_LIMIT
;
278 void Engine::set_time_fixed(int t
)
280 analysis_limit
= TIME_LIMIT
;
284 void Engine::set_time_control(int mps
, int basesec
, int inc
)
286 analysis_limit
= TIME_LIMIT
;
291 time_clock_csec
= time_base
*100;
294 void Engine::set_my_clock(int t
)
299 void Engine::set_other_clock(int t
)
301 time_oth_clock_csec
= t
;
304 void Engine::print_board()
309 void Engine::read_board(char* brd
, char* color
, char* castle
,
310 char* passing
, int moves_to_draw
, int num_moves
)
312 board
.read_board(brd
, color
,castle
,passing
,moves_to_draw
,num_moves
);
319 void Engine::read_board(char* str
)
321 board
.read_board(str
);
328 void Engine::read_board(FILE* f
)
332 board
.read_board(str
);
335 void Engine::write_board(FILE* f
)
338 board
.write_board(str
);
342 bool Engine::check_time()
347 if( eng_status
== PLAYING
&&
348 analysis_limit
== NODES_LIMIT
&&
349 processed_nodes
> (unsigned int)st_nodes
)
355 if( (processed_nodes
%4096) == 0 )
357 if( eng_status
== PLAYING
&&
358 analysis_limit
== TIME_LIMIT
&&
359 current_time()>=max_think_time
)
365 if(input_available())
377 if(eng_status
== PLAYING
&& !ponder
378 && st_computer_color
== board
.other_color
)
381 while(input_available());
390 void Engine::calc_best_time()
393 time_best_csec
= time_fixed
* 100;
396 int nummoves
= (time_mps
== 0) ? 30 :
397 MAX((time_mps
- (board
.num_moves
% time_mps
)), 30);
398 time_best_csec
= time_clock_csec
/ nummoves
+ time_inc
* 100;
399 //time_best_csec = time_clock_csec / nummoves * (50 + rand()%300) / 200 + time_inc * 100;
403 uint64_t Engine::perft(int lev
)
407 num
= board
.find_moves(mv_stack
);
414 for(int i
=0;i
<num
;i
++)
416 board
.do_move(mv_stack
[i
]);
418 board
.undo_move(mv_stack
[i
]);
424 void Engine::autotune()
426 struct Tunable
{ const char* name
; int& param
; int start
; int end
; int step
; };
428 { "v_search_threat_threshold", v_search_threat_threshold
, 150, 720, 190 },
429 { "v_search_threat_extension", v_search_threat_extension
, 40, 120, 80 },
430 { "v_search_null_reduction", v_search_null_reduction
, 200, 400, 100 },
432 int numparams
= sizeof(data
)/sizeof(Tunable
);
435 for(int p
=0;p
<numparams
;p
++)
437 int oldv
= data
[p
].param
;
439 int best_goodness
= -1;
440 int worst_goodness
= 99999;
442 for(data
[p
].param
= data
[p
].start
; data
[p
].param
<= data
[p
].end
; data
[p
].param
+= data
[p
].step
)
445 for(int k
=0;k
<numparams
;k
++)
446 output("%s = %d%s\n", data
[k
].name
, data
[k
].param
, k
==p
? " <--" : "");
447 int goodness
= run_epd_prog("self", 1, "epd/abbe.epd");
448 if(goodness
> best_goodness
)
450 best_goodness
= goodness
;
451 best
= data
[p
].param
;
453 if(goodness
< worst_goodness
)
454 worst_goodness
= goodness
;
457 if(worst_goodness
== best_goodness
)
458 data
[p
].param
= oldv
;
460 data
[p
].param
= best
;
464 output("FINAL REPORT:\n");
465 for(int k
=0;k
<numparams
;k
++)
466 output("%s = %d\n", data
[k
].name
, data
[k
].param
);