1/*
2    Sjeng - a chess variants playing program
3    Copyright (C) 2000-2001 Gian-Carlo Pascutto
4    Originally based on Faile, Copyright (c) 2000 Adrien M. Regimbald
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20    As a special exception, Gian-Carlo Pascutto gives permission
21    to link this program with the Nalimov endgame database access
22    code. See the Copying/Distribution section in the README file
23    for more details.
24
25    File: sjeng.c
26    Purpose: main program, xboard/user interface
27
28*/
29
30#include "sjeng.h"
31#include "protos.h"
32#include "extvars.h"
33#include "config.h"
34#include <machine/endian.h>
35
36char divider[50] = "-------------------------------------------------";
37move_s dummy = {0,0,0,0,0};
38
39int board[144], moved[144], ep_square, white_to_move, comp_color, wking_loc,
40  bking_loc, white_castled, black_castled, result, ply, pv_length[PV_BUFF],
41  pieces[62], squares[144], num_pieces, i_depth, fifty, piece_count;
42
43int32_t nodes, raw_nodes, qnodes,  killer_scores[PV_BUFF],
44  killer_scores2[PV_BUFF], killer_scores3[PV_BUFF], moves_to_tc, min_per_game,
45  sec_per_game, inc, time_left, opp_time, time_cushion, time_for_move, cur_score;
46
47uint32_t history_h[144][144];
48
49uint32_t hash_history[600];
50int move_number;
51
52bool captures, searching_pv, post, time_exit, time_failure;
53
54int xb_mode, maxdepth;
55
56int phase;
57int root_to_move;
58
59int my_rating, opp_rating;
60
61char setcode[30];
62
63move_s pv[PV_BUFF][PV_BUFF], killer1[PV_BUFF], killer2[PV_BUFF],
64 killer3[PV_BUFF];
65
66move_x path_x[PV_BUFF];
67move_s path[PV_BUFF];
68
69rtime_t start_time;
70
71int is_promoted[62];
72
73int NTries, NCuts, TExt;
74uint32_t PVS, FULL, PVSF;
75int EGTBHits, EGTBProbes;
76
77bool is_pondering, allow_pondering, is_analyzing;
78
79int Variant;
80int Giveaway;
81
82char my_partner[STR_BUFF];
83bool have_partner;
84bool must_sit;
85bool go_fast;
86
87int32_t fixed_time;
88
89FILE *lrn_standard;
90FILE *lrn_zh;
91FILE *lrn_suicide;
92FILE *lrn_losers;
93
94/*
95 * sjeng expects to get away with calling fclose(NULL), which crashes
96 * on MacOS X
97 */
98void safe_fclose(FILE * f)
99{
100  if (f) fclose(f);
101}
102
103/*
104 * We'll keep different learning files on big endian and little endian machines.
105 */
106FILE * learn_open(const char * name, const char * label)
107{
108	FILE *lrn;
109	char fname[30];
110
111	sprintf(fname, "%s_%cE.lrn", label,
112#if __DARWIN_BYTE_ORDER == __DARWIN_BIG_ENDIAN
113			'B'
114#elif __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
115			'L'
116#else
117#error Unknown Byte Order
118#endif
119			);
120
121	if ((lrn = fopen (fname, "rb+")) == NULL) {
122		printf("No %s learn file.\n", name);
123
124		if ((lrn = fopen (fname, "wb+")) == NULL) {
125			printf("Error creating %s learn file.\n", name);
126		} else {
127			fclose(lrn);
128			lrn = fopen (fname, "rb+");
129		}
130    }
131	return lrn;
132}
133
134
135int main (int argc, char *argv[]) {
136
137  char input[STR_BUFF], *p, output[STR_BUFF];
138  char readbuff[STR_BUFF];
139  move_s move, comp_move;
140  int depth = 4;
141  bool force_mode, show_board;
142  double nps, elapsed;
143  clock_t cpu_start, cpu_end;
144  move_s game_history[600];
145  move_x game_history_x[600];
146  int is_edit_mode, edit_color;
147  int confirm_moves;
148  int pingnum;
149  int braindeadinterface;
150  int automode;
151  rtime_t xstart_time;
152
153  read_rcfile();
154  initialize_zobrist();
155
156  Variant = Normal;
157  //Variant = Crazyhouse;
158
159  memcpy(material, std_material, sizeof(std_material));
160  //memcpy(material, zh_material, sizeof(zh_material));
161
162  if (!init_book())
163    printf("No .OPN opening book found.\n");
164
165  lrn_standard = learn_open("standard", "standard");
166  lrn_zh	   = learn_open("crazyhouse", "bug");
167  lrn_suicide  = learn_open("suicide", "suicide");
168  lrn_losers   = learn_open("losers", "losers");
169
170  start_up ();
171  init_game ();
172
173  initialize_hash();
174  clear_tt();
175  reset_ecache();
176
177  if (init_segtb())
178    SEGTB = TRUE;
179  else
180    SEGTB = FALSE;
181
182  EGTBProbes = 0;
183  EGTBHits = 0;
184  ECacheProbes = 0;
185  ECacheHits = 0;
186  TTProbes = 0;
187  TTStores = 0;
188  TTHits = 0;
189  bookidx = 0;
190  total_moves = 0;
191  ply = 0;
192  braindeadinterface = 0;
193  moves_to_tc = 40;
194  min_per_game = 5;
195  time_left = 30000;
196  my_rating = opp_rating = 2000;
197  maxdepth = 40;
198  must_go = 1;
199  tradefreely = 1;
200  automode = 0;
201
202  xb_mode = FALSE;
203  force_mode = FALSE;
204  comp_color = 0;
205  show_board = TRUE;
206  is_pondering = FALSE;
207  allow_pondering = TRUE;
208  is_analyzing = FALSE;
209  is_edit_mode = FALSE;
210  have_partner = FALSE;
211  must_sit = FALSE;
212  go_fast = FALSE;
213  fixed_time = FALSE;
214  phase = Opening;
215  root_to_move = WHITE;
216  kibitzed = FALSE;
217  confirm_moves = FALSE;
218
219  move_number = 0;
220  memset(game_history, 0, sizeof(game_history));
221  memset(game_history_x, 0, sizeof(game_history_x));
222
223  hash_history[move_number] = hash;
224
225  setbuf (stdout, NULL);
226  setbuf (stdin, NULL);
227
228  /* keep looping for input, and responding to it: */
229  while (TRUE) {
230
231    /* case where it's the computer's turn to move: */
232    if (!is_edit_mode && (comp_color == white_to_move || automode)
233	&& !force_mode && !must_sit && !result) {
234
235      /* whatever happens, never allow pondering in normal search */
236      is_pondering = FALSE;
237
238      cpu_start = clock ();
239      comp_move = think ();
240      cpu_end = clock();
241
242      ply = 0;
243
244      /* must_sit can be changed by search */
245      if (!must_sit || must_go != 0)
246	{
247	  /* check for a game end: */
248	  if ((
249	      ((Variant == Losers || Variant == Suicide)
250	        &&
251	      ((result != white_is_mated) && (result != black_is_mated)))
252	      ||
253	      ((Variant == Normal || Variant == Crazyhouse || Variant == Bughouse)
254	      && ((comp_color == 1 && result != white_is_mated)
255	         ||
256	         (comp_color == 0 && result != black_is_mated)
257	        )))
258	      && result != stalemate
259	      && result != draw_by_fifty
260	      && result != draw_by_rep)
261	  {
262
263	    comp_to_coord (comp_move, output);
264
265	    hash_history[move_number] = hash;
266
267	    game_history[move_number] = comp_move;
268	    make (&comp_move, 0);
269
270	    /* saves state info */
271	    game_history_x[move_number++] = path_x[0];
272
273	    userealholdings = 0;
274	    must_go--;
275
276            /* check to see if we draw by rep/fifty after our move: */
277	    if (is_draw ()) {
278	    	result = draw_by_rep;
279	    }
280	    else if (fifty > 100) {
281	        result = draw_by_fifty;
282	    }
283
284	    root_to_move ^= 1;
285
286	    reset_piece_square ();
287
288	    if (book_ply < 40) {
289	      if (!book_ply) {
290		strcpy(opening_history, output);
291	      }
292	      else {
293		strcat(opening_history, output);
294	      }
295	    }
296
297	    book_ply++;
298
299	    printf ("\nNodes: %d (%0.2f%% qnodes)\n", nodes,
300		    (float) ((float) qnodes / (float) nodes * 100.0));
301
302	    elapsed = (cpu_end-cpu_start)/(double) CLOCKS_PER_SEC;
303	    nps = (float) nodes/(float) elapsed;
304
305	    if (!elapsed)
306	      printf ("NPS: N/A\n");
307	    else
308	      printf ("NPS: %d\n", (int32_t) nps);
309
310	    printf("ECacheProbes : %d   ECacheHits : %d   HitRate : %f%%\n",
311		   ECacheProbes, ECacheHits,
312		   ((float)ECacheHits/((float)ECacheProbes+1)) * 100);
313
314	    printf("TTStores : %d TTProbes : %d   TTHits : %d   HitRate : %f%%\n",
315		   TTStores, TTProbes, TTHits,
316		   ((float)TTHits/((float)TTProbes+1)) * 100);
317
318	    printf("NTries : %d  NCuts : %d  CutRate : %f%%  TExt: %d\n",
319		   NTries, NCuts, (((float)NCuts*100)/((float)NTries+1)), TExt);
320
321	    printf("Check extensions: %d  Razor drops : %d  Razor Material : %d\n", ext_check, razor_drop, razor_material);
322
323            printf("EGTB Hits: %d  EGTB Probes: %d  Efficiency: %3.1f%%\n", EGTBHits, EGTBProbes,
324		(((float)EGTBHits*100)/(float)(EGTBProbes+1)));
325
326	    printf("Move ordering : %f%%\n", (((float)FHF*100)/(float)(FH+1)));
327
328	    printf("Material score: %d   Eval : %d  White hand: %d  Black hand : %d\n",
329		   Material, (int)eval(), white_hand_eval, black_hand_eval);
330
331	    printf("Hash : %X  HoldHash : %X\n", (unsigned)hash, (unsigned)hold_hash);
332
333	    /* check to see if we mate our opponent with our current move: */
334	    if (!result) {
335	      if (xb_mode) {
336
337		/* safety in place here */
338		if (comp_move.from != dummy.from || comp_move.target != dummy.target)
339		    printf ("move %s\n", output);
340
341		if (Variant == Bughouse)
342		  {
343		    CheckBadFlow(FALSE);
344		  }
345	      }
346	      else {
347		if (comp_move.from != dummy.from || comp_move.target != dummy.target)
348		printf ("\n%s\n", output);
349      	      }
350	    }
351	    else {
352	      if (xb_mode) {
353		if (comp_move.from != dummy.from || comp_move.target != dummy.target)
354		    printf ("move %s\n", output);
355	      }
356	      else {
357		if (comp_move.from != dummy.from || comp_move.target != dummy.target)
358		printf ("\n%s\n", output);
359	      }
360	      if (result == white_is_mated) {
361		printf ("0-1 {Black Mates}\n");
362	      }
363	      else if (result == black_is_mated) {
364		printf ("1-0 {White Mates}\n");
365	      }
366	      else if (result == draw_by_fifty) {
367	        printf ("1/2-1/2 {Fifty move rule}\n");
368	      }
369	      else if (result == draw_by_rep) {
370	        printf ("1/2-1/2 {3 fold repetition}\n");
371	      }
372	      else {
373		printf ("1/2-1/2 {Draw}\n");
374	      }
375	      automode = 0;
376	    }
377	  }
378	  /* we have been mated or stalemated: */
379	  else {
380	    if (result == white_is_mated) {
381	      printf ("0-1 {Black Mates}\n");
382	    }
383	    else if (result == black_is_mated) {
384	      printf ("1-0 {White Mates}\n");
385	    }
386            else if (result == draw_by_fifty) {
387	      printf ("1/2-1/2 {Fifty move rule}\n");
388	    }
389	    else if (result == draw_by_rep) {
390	      printf ("1/2-1/2 {3 fold repetition}\n");
391	    }
392	    else {
393	      printf ("1/2-1/2 {Draw}\n");
394	    }
395	    automode = 0;
396	  }
397	}
398    }
399
400    /* get our input: */
401    if (!xb_mode) {
402      if (show_board) {
403	printf ("\n");
404	display_board (stdout, 1-comp_color);
405      }
406      if (!automode)
407      {
408      	printf ("Sjeng: ");
409      	rinput (input, STR_BUFF, stdin);
410      }
411    }
412    else {
413      /* start pondering */
414
415      if ((must_sit || (allow_pondering && !is_edit_mode && !force_mode &&
416	      move_number != 0) || is_analyzing) && !result && !automode)
417	{
418	  is_pondering = TRUE;
419	  think();
420	  is_pondering = FALSE;
421
422	  ply = 0;
423	}
424      if (!automode)
425      {
426      	rinput (input, STR_BUFF, stdin);
427      }
428    }
429
430    /* check to see if we have a move.  If it's legal, play it. */
431    if (!is_edit_mode && is_move (&input[0])) {
432      if (verify_coord (input, &move)) {
433
434	if (confirm_moves) printf ("Legal move: %s\n", input);
435
436	game_history[move_number] = move;
437	hash_history[move_number] = hash;
438
439        make (&move, 0);
440	game_history_x[move_number++] = path_x[0];
441
442	reset_piece_square ();
443
444	root_to_move ^= 1;
445
446	if (book_ply < 40) {
447	  if (!book_ply) {
448	    strcpy(opening_history, input);
449	  }
450	  else {
451	    strcat(opening_history, input);
452	  }
453        }
454
455	book_ply++;
456
457	if (show_board) {
458	  printf ("\n");
459	  display_board (stdout, 1-comp_color);
460	}
461      }
462      else {
463	printf ("Illegal move: %s\n", input);
464	}
465    }
466    else {
467
468      /* make everything lower case for convenience: */
469      /* GCP: except for setboard, which is case sensitive */
470      if (!strstr(input, "setboard"))
471      	for (p = input; *p; p++) *p = tolower (*p);
472
473      /* command parsing: */
474      if (!strcmp (input, "quit") || (!input[0] && feof(stdin))) {
475	safe_fclose(lrn_standard);
476	safe_fclose(lrn_zh);
477	safe_fclose(lrn_suicide);
478	safe_fclose(lrn_losers);
479	free_hash();
480	free_ecache();
481	exit (EXIT_SUCCESS);
482      }
483      else if (!strcmp (input, "exit"))
484	{
485	  if (is_analyzing)
486	    {
487	      is_analyzing = FALSE;
488	      is_pondering = FALSE;
489	      time_for_move = 0;
490	    }
491	  else
492	    {
493	      safe_fclose(lrn_standard);
494	      safe_fclose(lrn_zh);
495	      safe_fclose(lrn_suicide);
496	      safe_fclose(lrn_losers);
497	      free_hash();
498	      free_ecache();
499	      exit (EXIT_SUCCESS);
500	    }
501	}
502      else if (!strcmp (input, "diagram") || !strcmp (input, "d")) {
503	toggle_bool (&show_board);
504      }
505      else if (!strncmp (input, "perft", 5)) {
506	sscanf (input+6, "%d", &depth);
507	raw_nodes = 0;
508	xstart_time = rtime();
509	perft (depth);
510	printf ("Raw nodes for depth %d: %d\n", depth, raw_nodes);
511	printf("Time : %.2f\n", (float)rdifftime(rtime(), xstart_time)/100.);
512      }
513	  else if (!strcmp (input, "confirm_moves")) {
514		  confirm_moves = TRUE;
515		  printf("Will now confirm moves.\n");
516	  }
517      else if (!strcmp (input, "new")) {
518
519	if (xb_mode)
520	  {
521	    printf("tellics set 1 Sjeng " VERSION " (2001-9-28/%s)\n", setcode);
522	  }
523
524	if (!is_analyzing)
525	{
526	  memcpy(material, std_material, sizeof(std_material));
527	  Variant = Normal;
528
529	 // memcpy(material, zh_material, sizeof(zh_material));
530	  //Variant = Crazyhouse;
531
532	  init_game ();
533	  initialize_hash();
534
535	  if (!braindeadinterface)
536	  {
537	    clear_tt();
538	    init_book();
539	    reset_ecache();
540	  }
541
542	  force_mode = FALSE;
543	  must_sit = FALSE;
544	  go_fast = FALSE;
545	  piecedead = FALSE;
546	  partnerdead = FALSE;
547	  kibitzed = FALSE;
548	  fixed_time = FALSE;
549
550	  root_to_move = WHITE;
551
552	  comp_color = 0;
553	  move_number = 0;
554	  hash_history[move_number] = 0;
555	  bookidx = 0;
556	  my_rating = opp_rating = 2000;
557          must_go = 0;
558	  tradefreely = 1;
559	  automode = 0;
560
561	  CheckBadFlow(TRUE);
562	  ResetHandValue();
563	}
564	else
565	{
566	  init_game ();
567	  move_number = 0;
568	}
569
570      }
571      else if (!strcmp (input, "xboard")) {
572	xb_mode = TRUE;
573	toggle_bool (&show_board);
574	signal (SIGINT, SIG_IGN);
575	printf ("\n");
576
577	/* Reset f5 in case we left with partner */
578	printf("tellics set f5 1=1\n");
579
580	BegForPartner();
581      }
582      else if (!strcmp (input, "nodes")) {
583	printf ("Number of nodes: %d (%0.2f%% qnodes)\n", nodes,
584		(float) ((float) qnodes / (float) nodes * 100.0));
585      }
586      else if (!strcmp (input, "nps")) {
587	elapsed = (cpu_end-cpu_start)/(double) CLOCKS_PER_SEC;
588	nps = (float) nodes/(float) elapsed;
589	if (!elapsed)
590	  printf ("NPS: N/A\n");
591	else
592	  printf ("NPS: %d\n", (int32_t) nps);
593      }
594      else if (!strcmp (input, "post")) {
595	toggle_bool (&post);
596	if (xb_mode)
597	  post = TRUE;
598      }
599      else if (!strcmp (input, "nopost")) {
600	post = FALSE;
601      }
602      else if (!strcmp (input, "random")) {
603	continue;
604      }
605      else if (!strcmp (input, "hard")) {
606
607	allow_pondering = TRUE;
608
609	continue;
610      }
611      else if (!strcmp (input, "easy")) {
612
613	allow_pondering = FALSE;
614
615	continue;
616      }
617      else if (!strcmp (input, "?")) {
618	continue;
619      }
620      else if (!strcmp (input, "white")) {
621	white_to_move = 1;
622	root_to_move = WHITE;
623	comp_color = 0;
624      }
625      else if (!strcmp (input, "black")) {
626	white_to_move = 0;
627	root_to_move = BLACK;
628	comp_color = 1;
629      }
630      else if (!strcmp (input, "force")) {
631	force_mode = TRUE;
632      }
633      else if (!strcmp (input, "eval")) {
634	check_phase();
635	printf("Eval: %d\n", (int)eval());
636      }
637      else if (!strcmp (input, "go")) {
638	comp_color = white_to_move;
639	force_mode = FALSE;
640      }
641      else if (!strncmp (input, "time", 4)) {
642	sscanf (input+5, "%d", &time_left);
643      }
644      else if (!strncmp (input, "otim", 4)) {
645	sscanf (input+5, "%d", &opp_time);
646      }
647      else if (!strncmp (input, "level", 5)) {
648         if (strstr(input+6, ":"))
649	 {
650	   /* time command with seconds */
651	   sscanf (input+6, "%d %d:%d %d", &moves_to_tc, &min_per_game,
652		   &sec_per_game, &inc);
653	   time_left = (min_per_game*6000) + (sec_per_game * 100);
654	   opp_time = time_left;
655	 }
656	 else
657	   {
658	     /* extract the time controls: */
659	     sscanf (input+6, "%d %d %d", &moves_to_tc, &min_per_game, &inc);
660	     time_left = min_per_game*6000;
661	     opp_time = time_left;
662	   }
663	 fixed_time = FALSE;
664	 time_cushion = 0;
665      }
666      else if (!strncmp (input, "rating", 6)) {
667	sscanf (input+7, "%d %d", &my_rating, &opp_rating);
668	if (my_rating == 0) my_rating = 2000;
669	if (opp_rating == 0) opp_rating = 2000;
670      }
671      else if (!strncmp (input, "holding", 7)) {
672	ProcessHoldings(input);
673      }
674      else if (!strncmp (input, "variant", 7)) {
675	if (strstr(input, "normal"))
676	  {
677	    Variant = Normal;
678	    memcpy(material, std_material, sizeof(std_material));
679	    init_book();
680	  }
681	else if (strstr(input, "crazyhouse"))
682	  {
683	    Variant = Crazyhouse;
684	    memcpy(material, zh_material, sizeof(zh_material));
685	    init_book();
686	  }
687	else if (strstr(input, "bughouse"))
688	  {
689	    Variant = Bughouse;
690	    memcpy(material, zh_material, sizeof(zh_material));
691	    init_book();
692	  }
693	else if (strstr(input, "suicide"))
694	  {
695	    Variant = Suicide;
696	    Giveaway = FALSE;
697	    memcpy(material, suicide_material, sizeof(suicide_material));
698	    init_book();
699	  }
700	else if (strstr(input, "giveaway"))
701	  {
702	    Variant = Suicide;
703	    Giveaway = TRUE;
704	    memcpy(material, suicide_material, sizeof(suicide_material));
705	    init_book();
706	  }
707	else if (strstr(input, "losers"))
708	  {
709	    Variant = Losers;
710	    memcpy(material, losers_material, sizeof(losers_material));
711	    init_book();
712	  }
713
714	initialize_hash();
715	clear_tt();
716	reset_ecache();
717
718      }
719      else if (!strncmp (input, "analyze", 7)) {
720	is_analyzing = TRUE;
721	is_pondering = TRUE;
722	think();
723	ply = 0;
724      }
725      else if (!strncmp (input, "undo", 4)) {
726	    printf("Move number : %d\n", move_number);
727	if (move_number > 0)
728	  {
729		  ply = 1;
730	    path_x[0] = game_history_x[--move_number];
731	    unmake(&game_history[move_number], 0);
732	    reset_piece_square();
733	    root_to_move ^= 1;
734	  }
735	result = 0;
736      }
737      else if (!strncmp (input, "remove", 5)) {
738	if (move_number > 1)
739	  {
740		  ply = 1;
741	    path_x[0] = game_history_x[--move_number];
742	    unmake(&game_history[move_number], 0);
743	    reset_piece_square();
744
745		  ply = 1;
746	    path_x[0] = game_history_x[--move_number];
747	    unmake(&game_history[move_number], 0);
748	    reset_piece_square();
749	  }
750	result = 0;
751      }
752      else if (!strncmp (input, "edit", 4)) {
753	is_edit_mode = TRUE;
754	edit_color = WHITE;
755      }
756      else if (!strncmp (input, ".", 1) && is_edit_mode) {
757	is_edit_mode = FALSE;
758	if (wking_loc == 30) white_castled = no_castle;
759	if (bking_loc == 114) black_castled = no_castle;
760	book_ply = 50;
761	ep_square = 0;
762	move_number = 0;
763	memset(opening_history, 0, sizeof(opening_history));
764	clear_tt();
765	initialize_hash();
766	reset_piece_square();
767      }
768      else if (is_edit_mode && !strncmp (input, "c", 1)) {
769	if (edit_color == WHITE) edit_color = BLACK; else edit_color = WHITE;
770	}
771      else if (is_edit_mode && !strncmp (input, "#", 1)) {
772	reset_board();
773	move_number = 0;
774      }
775      else if (is_edit_mode
776	       && isalpha(input[0])
777	       && isalpha(input[1])
778	       && isdigit(input[2])) {
779	PutPiece(edit_color, input[0], input[1], input[2]);
780      }
781      else if (!strncmp (input, "partner", 7)) {
782	HandlePartner(input+7);
783	}
784      else if (!strncmp (input, "$partner", 8)) {
785	HandlePartner(input+8);
786      }
787      else if (!strncmp (input, "ptell", 5)) {
788	HandlePtell(input);
789      }
790      else if (!strncmp (input, "test", 4)) {
791	run_epd_testsuite();
792      }
793      else if (!strncmp (input, "st", 2)) {
794	sscanf(input+3, "%d", &fixed_time);
795	fixed_time = fixed_time * 100;
796      }
797      else if (!strncmp (input, "book", 4)) {
798	build_book();
799      }
800      else if (!strncmp (input, "speed",  5)) {
801	speed_test();
802      }
803      else if (!strncmp (input, "result", 6)) {
804	if (cfg_booklearn)
805	  {
806	    if (strstr (input+7, "1-0"))
807	      {
808		if (comp_color == 1)
809		  book_learning(WIN);
810		else
811		  book_learning(LOSS);
812	      }
813	    else if (strstr(input+7, "0-1"))
814	      {
815		if (comp_color == 1)
816		  book_learning(LOSS);
817		else
818		  book_learning(WIN);
819	      }
820	    else if (strstr(input+7, "1/2-1/2"))
821	      {
822		book_learning(DRAW);
823	      };
824	  }
825	}
826      else if (!strncmp (input, "prove", 5)) {
827	printf("\nMax time to search (s): ");
828	start_time = rtime();
829	rinput(readbuff, STR_BUFF, stdin);
830	pn_time = atoi(readbuff) * 100;
831	printf("\n");
832	proofnumbersearch();
833       }
834      else if (!strncmp (input, "ping", 4)) {
835	sscanf (input+5, "%d", &pingnum);
836	printf("pong %d\n", pingnum);
837      }
838      else if (!strncmp (input, "fritz", 5)) {
839	braindeadinterface = TRUE;
840      }
841      else if (!strncmp (input, "reset", 5)) {
842
843	memcpy(material, std_material, sizeof(std_material));
844	Variant = Normal;
845
846	init_game ();
847	initialize_hash();
848
849	clear_tt();
850	init_book();
851	reset_ecache();
852
853	force_mode = FALSE;
854	fixed_time = FALSE;
855
856	root_to_move = WHITE;
857
858	comp_color = 0;
859	move_number = 0;
860	bookidx = 0;
861	my_rating = opp_rating = 2000;
862      }
863      else if (!strncmp (input, "setboard", 8)) {
864	setup_epd_line(input+9);
865      }
866      else if (!strncmp (input, "buildegtb", 9)) {
867        Variant = Suicide;
868	gen_all_tables();
869      }
870      else if (!strncmp (input, "lookup", 6)) {
871	Variant = Suicide;
872        printf("Value : %d\n", egtb(white_to_move));
873      }
874      else if (!strncmp (input, ".", 1)) {
875        /* periodic updating and were not searching */
876	/* most likely due to proven mate */
877	continue;
878      }
879      else if (!strncmp (input, "sd", 2)) {
880	sscanf(input+3, "%d", &maxdepth);
881	printf("New max depth set to: %d\n", maxdepth);
882	continue;
883      }
884      else if (!strncmp (input, "auto", 4)) {
885	automode = 1;
886	continue;
887      }
888      else if (!strncmp (input, "protover", 8)) {
889	printf("feature ping=1 setboard=1 playother=0 san=0 usermove=0 time=1\n");
890	printf("feature draw=0 sigint=0 sigterm=0 reuse=1 analyze=1\n");
891	printf("feature myname=\"Sjeng " VERSION "\"\n");
892	printf("feature variants=\"normal,bughouse,crazyhouse,suicide,giveaway,losers\"\n");
893	printf("feature colors=1 ics=0 name=0 pause=0 done=1\n");
894	xb_mode = 2;
895      }
896      else if (!strncmp (input, "accepted", 8)) {
897	/* do nothing as of yet */
898      }
899      else if (!strncmp (input, "rejected", 8)) {
900	printf("Interface does not support a required feature...expect trouble.\n");
901      }
902      else if (!strncmp (input, "warranty", 8)) {
903	  printf("\n  BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
904		 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n"
905		 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
906		 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
907		 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
908		 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n"
909		 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n"
910		 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
911		 "REPAIR OR CORRECTION.\n"
912		 "\n");
913	  printf("  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
914		 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
915		 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
916		 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
917		 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
918		 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
919		 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
920		 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
921		 "POSSIBILITY OF SUCH DAMAGES.\n\n");
922
923	}
924      else if (!strncmp (input, "distribution", 12)) {
925	printf("\n  You may copy and distribute verbatim copies of the Program's\n"
926	       "source code as you receive it, in any medium, provided that you\n"
927	       "conspicuously and appropriately publish on each copy an appropriate\n"
928	       "copyright notice and disclaimer of warranty; keep intact all the\n"
929	       "notices that refer to this License and to the absence of any warranty;\n"
930	       "and give any other recipients of the Program a copy of this License\n"
931	       "along with the Program.\n"
932	       "\n"
933	       "You may charge a fee for the physical act of transferring a copy, and\n"
934	       "you may at your option offer warranty protection in exchange for a fee.\n\n");
935
936	}
937      else if (!strcmp (input, "help")) {
938	printf ("\n%s\n\n", divider);
939	printf ("diagram/d:       toggle diagram display\n");
940	printf ("exit/quit:       terminate Sjeng\n");
941	printf ("go:              make Sjeng play the side to move\n");
942	printf ("new:             start a new game\n");
943	printf ("level <x>:       the xboard style command to set time\n");
944	printf ("  <x> should be in the form: <a> <b> <c> where:\n");
945	printf ("  a -> moves to TC (0 if using an ICS style TC)\n");
946	printf ("  b -> minutes per game\n");
947	printf ("  c -> increment in seconds\n");
948	printf ("nodes:           outputs the number of nodes searched\n");
949	printf ("nps:             outputs Sjeng's NPS in search\n");
950	printf ("perft <x>:       compute raw nodes to depth x\n");
951	printf ("post:            toggles thinking output\n");
952	printf ("xboard:          put Sjeng into xboard mode\n");
953	printf ("test:            run an EPD testsuite\n");
954	printf ("speed:           test movegen and evaluation speed\n");
955	printf ("warranty:        show warranty details\n");
956	printf ("distribution:    show distribution details\n");
957	printf( "proof:           try to prove or disprove the current pos\n");
958	printf( "sd <x>:          limit thinking to depth x\n");
959	printf( "st <x>:          limit thinking to x centiseconds\n");
960	printf( "setboard <FEN>:  set board to a specified FEN string\n");
961	printf( "undo:            back up a half move\n");
962	printf( "remove:          back up a full move\n");
963	printf( "force:           disable computer moving\n");
964	printf( "auto:            computer plays both sides\n");
965	printf ("\n%s\n\n", divider);
966
967        show_board = 0;
968      }
969      else if (!xb_mode) {
970	printf ("Illegal move: %s\n", input);
971      }
972
973    }
974
975  }
976
977  return 0;
978
979}
980