Revitalized the gui, disabled most search features to go to the evaluation.
[rattatechess.git] / moveparse.cpp
blobced890a020e33b7fadc13c1ee6323d26ed99520c
1 /***************************************************************************
2 moveparse.cpp - description
3 -------------------
4 begin : mer ott 30 2002
5 copyright : (C) 2002-2007 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 <string.h>
22 void Engine::print_moves(Move* m, int num, bool nums, bool walk_ht)
24 int i,j;
25 if(board.color_to_move==BLACK &&nums)
26 output("%d. ...",board.num_moves+1);
28 for(i=0;i<num;i++)
30 if(m[i].as_int == 0)
31 break;
33 if(board.color_to_move==WHITE && nums)
34 printf(" %d.",board.num_moves+1);
35 output(" %s", board.move_to_alg(MoveStr().data(), m[i]) );
36 board.do_move(m[i], save_buf[save_buf_num++]);
39 if(walk_ht)
41 Move hash_mv[24];
42 for(j=0;j<24-i;j++)
44 HashEntry *h = probe_hash( board.hash );
45 if(!h || !h->best_mv || h->depth<0)
46 break;
48 /* don't follow the hash if there is draw for repetition :) */
49 if( check_draw() )
51 output( " <DRAW>" );
52 break;
55 hash_mv[j] = board.uncompress_move( h->best_mv );
57 /* verify that the move in the hash is a legal move */
58 Move tmp[255];
59 int num_tmp = board.find_moves(tmp);
60 bool ok = false;
61 for(int q=0;q<num_tmp;q++)
62 if(tmp[q] == hash_mv[j])
64 ok = true;
65 break;
68 if(!ok)
69 break;
71 if(j==0)
72 output(" |");
74 if(board.color_to_move==WHITE && nums)
75 output(" %d.",board.num_moves+1);
76 output( " %s", board.move_to_alg(MoveStr().data(), hash_mv[j]) );
77 board.do_move(hash_mv[j], save_buf[save_buf_num++]);
80 while(j--)
81 board.undo_move(hash_mv[j], save_buf[--save_buf_num]);
84 while(i--)
85 board.undo_move(m[i], save_buf[--save_buf_num]);
87 output("\n");
90 /* TODO: load correctly the pgn that start with a fen */
91 int Engine::load_pgn(FILE *f)
93 char buf[1024];
95 board.set_as_default();
96 mv_done_num = 0;
98 while(1)
100 if(!fgets(buf, 1024, f))
101 return 0;
102 if(buf[0]=='\n' || buf[0]=='\r' || buf[0]=='\t'
103 || buf[0]==' ' || buf[0]=='[' || buf[0]=='#')
104 continue;
105 break;
108 while(1)
110 char *ptr = buf;
111 ptr += strspn(ptr, ". \t\r\n");
113 for(int i=0;;i++)
115 if(!*ptr)
116 break;
117 char *t = ptr;
118 char *tmp = (ptr += strcspn(ptr, ". \t\r\n"));
119 ptr += strspn(ptr, ". \t\r\n");
120 *tmp = 0;
122 /* is this the result? */
123 if(!strcmp(t, "1-0"))
125 status = _10;
126 return 1;
128 else if(!strcmp(t, "0-1"))
130 status = _01;
131 return 1;
133 else if(!strcmp(t, "1/2-1/2") || !strcmp(t, "*"))
135 status = _12;
136 return 1;
139 /* is this a move number? */
140 char *e;
141 strtol(t, &e, 10);
142 if(e!=t)
143 continue;
145 Move mv = board.move_from_string(t);
146 if(!mv.valid())
148 board.print_board();
149 output("Error! \"%s\" %x\n", t, mv.as_int);
150 return 0; /* error */
153 mv_done[mv_done_num++] = mv;
154 board.do_move(mv, save_buf[save_buf_num++]);
157 if(!fgets(buf, 1024, f))
158 return 1;
162 int Engine::run_epd_prog(const char* prog, int time, const char* file, bool quiet)
164 char buf[1024];
165 bool failed[8000];
166 FILE *in = NULL;
167 FILE *out = NULL;
168 FILE *f;
170 /* open the file with the tests */
171 f = fopen(file, "r");
172 if(!f)
174 output("Error, could not open %s for reading!\n", file);
175 return 0;
178 if(!strcmp(prog, "self"))
180 if(quiet)
181 post = false;
182 set_time_fixed(time);
184 else
185 start_engine(prog, &in, &out);
187 /* reset passed flags */
188 int done = 0;
189 int passed = 0;
190 for(int i=0;i<8000;i++)
191 failed[i] = false;
193 while(fgets(buf, 1024, f))
195 char brd[81];
196 char color[2],castle[5],passing[3];
197 char best[256];
198 char avoid[256];
199 char name[64];// = "unknown";
200 char *tmp;
201 Move best_mv[10];
202 Move avoid_mv[10];
203 int num_best = 0;
204 int num_avoid = 0;
205 Move m;
208 /* read the board */
209 sscanf(buf,"%s%s%s%s",
210 brd,color,castle,passing);
211 read_board(brd,color,castle,passing,0,0);
212 if(!quiet)
214 output("\n\n");
215 board.print_board();
219 done++;
220 //printf("%s\n", buf);
222 /* save the best moves in the best_mv array */
223 tmp = strstr(buf, "bm");
224 if(tmp)
226 int tok = 0;
227 sscanf(tmp, "bm %63[^;];", best);
228 tok += strspn(best + tok, " \t\r\n");
230 for(num_best=0;num_best<10;num_best++)
232 if(!best[tok])
233 break;
235 int start = tok;
236 int firstspace = (tok += strcspn(best + tok, " \t\r\n"));
237 tok += strspn(best + tok, " \t\r\n");
238 best[firstspace] = 0;
240 best_mv[num_best] = board.move_from_string(best+start);
242 if(!best_mv[num_best].valid())
244 output("Error, could not parse move %s in pos %d\n", best+start, done);
245 return 0;
250 /* save the avoid moves in the best_mv array */
251 tmp = strstr(buf, "am");
252 if(tmp)
254 int tok = 0;
255 sscanf(tmp, "am %63[^;];", avoid);
256 tok += strspn(avoid + tok, " \t\r\n");
258 for(num_avoid=0;num_avoid<10;num_avoid++)
260 if(!avoid[tok])
261 break;
263 int start = tok;
264 int firstspace = (tok += strcspn(avoid + tok, " \t\r\n"));
265 tok += strspn(avoid + tok, " \t\r\n");
266 avoid[firstspace] = 0;
268 avoid_mv[num_avoid] = board.move_from_string(avoid+start);
270 if(!avoid_mv[num_avoid].valid())
272 output("Error, could not parse move %s in pos %d\n", best+start, done);
273 return 0;
278 /* get the id */
279 tmp = strstr(buf, "id");
280 if(tmp)
281 sscanf ( tmp, "id %63[^;];", name);
282 else
283 strcpy( name, "<unknown>" );
285 if(!quiet)
287 output(" %d - Thinking", done);
288 if(num_best)
290 output(", the best move%s\e[32;1m", num_best>1 ? "s are" : " is");
291 for(int i=0;i<num_best;i++)
292 output(" %s", board.move_to_alg(MoveStr().data(), best_mv[i]) );
293 output("\e[0m");
295 if(num_avoid)
297 output(", the move%s to avoid\e[31;1m", num_avoid>1 ? "s are" : " is");
298 for(int i=0;i<num_avoid;i++)
299 output(" %s", board.move_to_alg(MoveStr().data(), avoid_mv[i]) );
300 output("\e[0m");
302 output("\n");
305 if(!strcmp(prog, "self"))
307 st_computer_color = board.color_to_move;
308 m = find_best_move();
310 else
312 fprintf(out, "force\n");
313 fprintf(out, "setboard %s\n", board.to_fen(BigStr().data()) );
314 fprintf(out, "st %d\n", time);
315 //fprintf(out, "level 1 %d 0\n", time);
316 fprintf(out, "time %d\n", time*200);
317 fprintf(out, "otim %d\n", time*200);
318 fprintf(out, "go\n");
320 while(fgets(buf, 1024, in))
322 char mv[32];
323 if(!strncmp(buf, "move ", 5))
325 sscanf ( buf, "move %s", mv);
326 m = board.move_from_string(mv);
327 if(!m.valid())
329 output("Got illegal move %s\n", mv);
330 return 0;
332 break;
334 else
335 output(buf);
339 bool fail = false;
340 if(!quiet)
341 output("Result: \e[36;1m%s\e[0m\n", board.move_to_alg(MoveStr().data(), m));
342 for(int i=0;i<num_avoid;i++)
343 if(m == avoid_mv[i])
345 fail = true;
346 if(!quiet)
347 output("Test %d \e[31;1mFAILURE\e[0m, %s did not avoid the "
348 "wrong move \e[33;1m%s\e[0m (che pollo!)\n",done, prog,
349 board.move_to_alg(MoveStr().data(), avoid_mv[i]));
351 if(num_avoid && !fail && !quiet)
352 output("Test %d \e[32;1mSUCCESS\e[0m, %s avoided the "
353 "wrong move%s \e[33;1m%s\e[0m (teto figo!)\n",
354 done, prog, num_avoid>1?"s":"", avoid);
355 if(!fail && num_best)
357 fail = true;
358 for(int i=0;i<num_best;i++)
359 if(m == best_mv[i])
361 fail = false;
362 if(!quiet)
363 output("Test %d \e[32;1mSUCCESS\e[0m, %s found the "
364 "best move \e[33;1m%s\e[0m (o se figo!)\n",
365 done, prog, board.move_to_alg(MoveStr().data(), best_mv[i]));
366 break;
368 if(fail && !quiet)
369 output("Test %d \e[31;1mFAILURE\e[0m, %s missed the best "
370 "move%s (\e[33;1m%s\e[0m) (che scarso!)\n", done, prog,
371 num_best>1?"s":"", best);
373 if(!fail)
374 passed++;
375 else
376 failed[done] = true;
378 if(!quiet)
379 output("Test %d %s %s! (+%d, -%d, ~%d%%)\n", done, name, fail ?
380 "\e[31;1mFAILED\e[0m" : "\e[32;1mPASSED\e[0m",
381 passed, done-passed, passed*100/done);
382 else {
383 output("%s", fail ? "-" : "+");
384 char str[80];
385 snprintf(str, 40, "(%d/%d)", passed, done);
386 int l = strlen(str);
387 for(int i=0;i<l;i++)
388 str[l+i] = '\b';
389 fwrite(str, 2*l, 1, stdout);
390 fflush(stdout);
393 if(quiet)
394 output("\n");
395 output("Passed %d tests out of %d (%d%%)\n", passed, done, passed*100/done);
396 if(!quiet)
398 output("Failed are:\n");
399 int numsh = 0;
400 for(int i=1;i<done+1;i++)
401 if(failed[i])
403 output(" %d", i);
404 if(((++numsh) % 10) == 0)
405 output("\n");
407 output("\n");
410 if(strcmp(prog, "self"))
412 fprintf(out, "quit\n");
413 fclose(out);
414 fclose(in);
416 fclose(f);
418 return passed;
421 void Engine::save_pgn(FILE *f, const char *result1, const char *result)
423 for(int i=mv_done_num-1;i>=0;i--)
424 board.undo_move(mv_done[i], save_buf[--save_buf_num]);
426 fprintf(f, "[White \"%s\"]\n", st_computer_color == WHITE ?
427 "RattateChess" : opponent );
428 fprintf(f, "[Black \"%s\"]\n", st_computer_color == BLACK ?
429 "RattateChess" : opponent );
430 fprintf(f, "[WhiteELO \"%d\"]\n", w_rating);
431 fprintf(f, "[BlackELO \"%d\"]\n", b_rating);
433 time_t t = time(NULL);
434 char tbuf[256];
435 strftime(tbuf, 256, "%Y.%m.%d %H:%M", localtime(&t));
436 fprintf(f, "[Date \"%s\"]\n", tbuf);
437 fprintf(f, "[Result \"%s\"]\n", result1);
439 if(0)
440 fprintf(f, "[FEN \"%s\"]\n", board.to_fen(BigStr().data()) );
442 if(board.color_to_move==BLACK)
443 fprintf(f, "%d. ... ",board.num_moves+1);
444 for(int i=0;i<mv_done_num;i++)
446 if(board.color_to_move==WHITE)
447 fprintf(f, "%d. ",board.num_moves+1);
448 fprintf(f, "%s ", board.move_to_alg(MoveStr().data(), mv_done[i]) );
449 if((i+1)%14 == 0 && i!=mv_done_num-1)
450 fprintf(f, "\n");
451 board.do_move(mv_done[i], save_buf[save_buf_num++]);
453 fprintf(f, "\n%s\n\n", result);
456 void Engine::challenge(const char* prog, int time, const char* file)
458 char buf[1024];
459 FILE *in = NULL;
460 FILE *out = NULL;
461 FILE *f;
462 FILE *log;
463 int won=0, draw=0, lost=0;
465 /* open the file with the tests */
466 f = fopen(file, "r");
467 log = fopen("challenge.pgn", "w");
469 if(!f)
471 output("Error, could not open %s for reading!\n", file);
472 return;
475 start_engine(prog, &in, &out);
477 while(fgets(buf, 1024, f))
479 uint8_t cols[2] = {WHITE, BLACK};
481 for(int i=0;i<2;i++)
483 bool go_done = false;
484 read_board(buf);
485 //set_max_nodes(time);
486 //set_time_fixed(time);
487 set_time_control(40, time, 0);
488 ponder = false;
490 fprintf(out, "new\n");
491 //fprintf(out, "st %d\n", time);
492 fprintf(out, "level 40 %d:%d 0\n", time/60, time%60);
493 fprintf(out, "force\n");
494 fprintf(out, "setboard %s\n", board.to_fen(BigStr().data()));
497 status = PLAYING;
498 st_computer_color = cols[i];
500 while(1)
502 char buf[1024];
504 /*output("\n\n");
505 board.print_board();*/
507 /* print the pgn to the log file */
508 if(status != PLAYING)
510 const char *result = status==_01?"0-1":(status==_10?"1-0":"1/2-1/2");
511 const char *white = st_computer_color == WHITE ? "Rattatechess" : prog;
512 const char *black = st_computer_color == BLACK ? "Rattatechess" : prog;
514 if(log)
516 for(int i=mv_done_num-1;i>=0;i--)
517 board.undo_move(mv_done[i], save_buf[--save_buf_num]);
519 fprintf(log, "[White \"%s\"]\n", white);
520 fprintf(log, "[Black \"%s\"]\n", black);
521 fprintf(log, "[Result \"%s\"]\n", result);
522 fprintf(log, "[FEN \"%s\"]\n", board.to_fen(BigStr().data()) );
524 if(board.color_to_move==BLACK)
525 fprintf(log, "%d. ... ",board.num_moves+1);
526 for(int i=0;i<mv_done_num;i++)
528 if(board.color_to_move==WHITE)
529 fprintf(log, "%d. ",board.num_moves+1);
530 fprintf(log, "%s ", board.move_to_alg(MoveStr().data(), mv_done[i]) );
531 if((i+1)%14 == 0)
532 fprintf(log, "\n");
533 board.do_move(mv_done[i], save_buf[save_buf_num++]);
535 fprintf(log, "%s\n\n", result);
536 fflush(log);
539 if((status==_01 && st_computer_color==BLACK) ||
540 (status==_10 && st_computer_color==WHITE))
542 output("RATTA!!!\n");
543 won++;
545 else if(status==_12)
547 output("DRAW!\n");
548 draw++;
550 else
552 output("ARGH!!!\n");
553 lost++;
555 break;
558 /* think or wait for a new move */
559 if(st_computer_color == board.color_to_move)
561 /* think and move */
562 Move mv = find_best_move();
563 output("%d. %s %s\n",board.num_moves+1,
564 board.color_to_move==BLACK ? "..." : "",
565 board.move_to_alg(MoveStr().data(), mv) );
566 fprintf( out, "%s\n", Board::move_to_coord(MoveStr().data(), mv));
567 move(mv);
569 else
571 if(!go_done)
573 fprintf( out, "go\n");
574 go_done = true;
577 while(fgets(buf, 1024, in))
579 /* get a move from the other engine */
580 if(!strncmp(buf, "move ", 5))
582 Move mv;
583 char buf2[32];
584 sscanf( buf, "move %s", buf2);
585 mv = board.move_from_string(buf2);
586 if(!mv.valid())
588 output("Got illegal move %s\n", buf2);
589 return;
591 output("%d. %s %s\n",board.num_moves+1,
592 board.color_to_move==BLACK ? "..." : "",
593 board.move_to_alg(MoveStr().data(), mv) );
594 move(mv);
595 break;
597 else if(!strcmp(buf, "resign"))
599 status = board.color_to_move==WHITE?_01:_10;
600 break;
602 //else
603 // output(buf);
610 fprintf(out, "quit\n");
611 fclose(out);
612 fclose(in);
613 if(log) fclose(log);
614 fclose(f);
616 output("\n\n%d games played (+%d =%d -%d)\n", won+draw+lost, won, draw, lost);