2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 struct engine_t e
; /* engine parameters */
27 int history
[2][7][4096]; /* history for move ordering */
28 int hash_moves
[MAX_PLY
]; /* moves to try first */
29 struct killers_t killers
[MAX_PLY
]; /* moves to try after hash moves */
31 int pv
[MAX_PLY
][MAX_PLY
]; /* triangular array for PV */
32 int pv_length
[MAX_PLY
];
34 /* initial chess position */
35 char start_position
[] = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -";
36 char book_file_name
[] = "book.bin";
38 /* statistic counters */
39 struct counters_t counters
;
42 * Return variable's value in thread-safe way
45 get_engine_value(int *val
)
49 pthread_mutex_lock(&e
.mutex
);
51 pthread_mutex_unlock(&e
.mutex
);
57 * Set value in thread-safe way
60 set_engine_value(int *src
, int new_value
)
62 pthread_mutex_lock(&e
.mutex
);
64 pthread_mutex_unlock(&e
.mutex
);
67 /* time from Epoc in second/100 units - xboard time units */
74 return t
.tv_sec
* 100 + t
.tv_usec
/ 10000;
77 /* check if we should abort search */
83 if (!(counters
.searched_nodes
& e
.chk_time
))
84 if (get_time() >= get_engine_value((int *)&e
.stop_time
)) {
85 /* takeback all moves in search tree */
86 for (i
= 0; i
< ply
; i
++)
99 srand(get_time()); /* for opening book randomization */
100 setup_board(start_position
);
102 clear_main_hashtable();
103 clear_pawn_hashtable();
106 /* print brief stats to console. used mostly for debugging */
108 print_stats(int timediff
)
111 double move_ordering
;
114 search_time
= timediff
/ 100.0;
115 move_ordering
= counters
.failed_high_total
? \
116 (counters
.failed_high_first
/ (double) counters
.failed_high_total
) * \
118 nps
= counters
.searched_nodes
/ search_time
;
120 fprintf(stdout
, "Time: %.2f, nodes: %llu, NPS: %d/sec, MO: %.2f%%\n" \
121 "NULL: %llu, delta: %llu, LMR: %llu, razor: %llu, futility: %llu\n" \
122 "pawn hash evaluations: %llu, transposition: %llu, evaluations: %llu, phase: %d\n",
123 search_time
, counters
.searched_nodes
, nps
, move_ordering
,
124 counters
.null_move_prunings
, counters
.delta_prunings
,
125 counters
.reductions
, counters
.razorings
, counters
.futility_prunings
,
126 counters
.pawn_hash_evaluations
, counters
.transposition
,
127 counters
.evaluations
, GAME_PHASE
);
130 /* if it's engine's turn to move we should search */
132 process_turn(void *args
)
136 char buf
[MAX_STRING
];
138 move_from_book
= TRUE
;
142 move_from_book
= FALSE
;
143 set_engine_value(&e
.thinking
, TRUE
);
145 set_engine_value(&e
.thinking
, FALSE
);
149 fprintf(stdout
, "resign\n");
150 if (get_engine_value(&e
.side
) == WHITE
)
151 fprintf(stdout
, "0-1 {WHITE resigns}\n");
153 fprintf(stdout
, "1-0 {BLACK resigns}\n");
154 set_engine_value(&e
.side
, NOBODY
);
156 /* free resources after termination */
157 pthread_detach(pthread_self());
162 if (!move
|| evaluate_draw() || reps() >= 3) {
163 if (evaluate_draw()) {
164 if (brd
.fifty_rule
>= 100)
165 fprintf(stdout
, "1/2-1/2 {Fifty move rule}\n");
167 fprintf(stdout
, "1/2-1/2 {draw}\n");
168 } else if (reps() >= 3)
169 fprintf(stdout
, "1/2-1/2 {draw by repetition}\n");
170 else if (IS_CHECKED(WHITE
))
171 fprintf(stdout
, "0-1 {BLACK mates}\n");
172 else if (IS_CHECKED(BLACK
))
173 fprintf(stdout
, "1-0 {WHITE mates}\n");
175 fprintf(stdout
, "1/2-1/2 {Stalemate}\n");
176 set_engine_value(&e
.side
, NOBODY
);
178 if (get_engine_value(&e
.san_notation
) || \
179 !get_engine_value(&e
.xboard_mode
)) {
181 make_move(move
, FALSE
);
182 fprintf(stdout
, "move %s\n", buf
);
184 make_move(move
, FALSE
);
185 fprintf(stdout
, "move %s\n", coord_move(move
, buf
));
188 if (!get_engine_value(&e
.xboard_mode
) && !move_from_book
)
189 fprintf(stdout
, "[%s]$ ", program_name
);
191 /* free resources after termination */
192 pthread_detach(pthread_self());
200 pthread_mutex_init(&e
.mutex
, 0);
202 set_engine_value(&e
.side
, NOBODY
);
203 set_engine_value(&e
.force_mode
, TRUE
);
204 set_engine_value(&e
.post_mode
, FALSE
);
205 set_engine_value(&e
.xboard_mode
, FALSE
);
206 set_engine_value(&e
.san_notation
, FALSE
);
208 /* set small limits for quick testing */
209 set_engine_value(&e
.max_depth
, 9);
210 set_engine_value(&e
.max_time
, 10000);
212 /* check if we should abort search every 1024 nodes */
213 set_engine_value(&e
.chk_time
, 1023);
215 /* use 1/30 of total time for thinking */
216 set_engine_value(&e
.time_div
, 30);
218 set_engine_value(&e
.fixed_time
, FALSE
);
219 set_engine_value((int *)&e
.stop_time
, 0);
221 /* if FALSE we are playing to mate */
222 set_engine_value(&e
.resign
, TRUE
);
223 set_engine_value(&e
.resign_value
, -600);
225 /* if EPD tests are currently running */
226 set_engine_value(&e
.thinking
, FALSE
);
229 set_engine_value(&e
.delta_pruning
, TRUE
);
230 set_engine_value(&e
.futility_pruning
, TRUE
);
231 set_engine_value(&e
.iid
, TRUE
);
232 set_engine_value(&e
.null_pruning
, TRUE
);
233 set_engine_value(&e
.lmr
, TRUE
);
234 set_engine_value(&e
.razoring
, TRUE
);
236 /* used to calculate 'game phase' */
237 set_engine_value(&e
.phase_factor
, (piece_value
[KNIGHT
] * 2 + \
238 piece_value
[BISHOP
] * 2 + piece_value
[ROOK
] * 2 + \
239 piece_value
[QUEEN
]) / 128);
243 /* initialize hashtable */
244 e
.pawn_hash_size
= 2;
245 e
.main_hash_size
= 16;
246 e
.pawn_hash_enabled
= TRUE
;
247 e
.main_hash_enabled
= TRUE
;
249 book_open(book_file_name
);
254 void perform_cleanup(void)
257 if (get_engine_value(&e
.pawn_hash_enabled
))
258 free_pawn_hashtable();
260 /* destroy engine mutex */
261 pthread_mutex_destroy(&e
.mutex
);
263 /* close book file descriptor */