~ubuntu-branches/ubuntu/precise/gcompris/precise

« back to all changes in this revision

Viewing changes to src/chess_computer-activity/gnuchess/cmd.c

  • Committer: Bazaar Package Importer
  • Author(s): Yann Dirson
  • Date: 2010-06-27 22:51:30 UTC
  • mfrom: (1.1.16 upstream) (5.1.6 sid)
  • Revision ID: james.westby@ubuntu.com-20100627225130-mf7h4m5r8m7bd9fb
Tags: 9.3-1
* New upstream release.
* Drop GTK_DISABLE_DEPRECATED patch, useless for now.
* Provide RELEASE_NOTE_9.3.txt downloaded from sourceforge.
* New voice package for Asturian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GNU Chess 5.0 - cmd.c - command parser
 
2
   Copyright (c) 1999-2002 Free Software Foundation, Inc.
 
3
 
 
4
   GNU Chess is based on the two research programs 
 
5
   Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
 
6
 
 
7
   GNU Chess is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 2, or (at your option)
 
10
   any later version.
 
11
 
 
12
   GNU Chess is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
 
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with GNU Chess; see the file COPYING.  If not, write to
 
19
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
20
   Boston, MA 02111-1307, USA.
 
21
 
 
22
   Contact Info: 
 
23
     bug-gnu-chess@gnu.org
 
24
     cracraft@ai.mit.edu, cracraft@stanfordalumni.org, cracraft@earthlink.net
 
25
*/
 
26
 
 
27
#include <config.h>
 
28
#include <stdio.h>
 
29
#include <stdlib.h>
 
30
#include <string.h>
 
31
#include <unistd.h>
 
32
#include <ctype.h>
 
33
#include <errno.h>
 
34
 
 
35
#include "version.h"
 
36
#include "common.h"
 
37
#include "eval.h"
 
38
 
 
39
static char logfile[MAXSTR];
 
40
static char gamefile[MAXSTR];
 
41
 
 
42
/*
 
43
 * Splitting input is actually not neccessary, but we find
 
44
 * tokens separated by whitespace and put pointers on them.
 
45
 * How many do we need? We just take 3 for now. Check if the
 
46
 * fact that tokens are not 0-terminated but whitespace-terminated
 
47
 * generates bugs. (Already killed one bug in move.c)
 
48
 * We also kill trailing whitespace. (The trailing '\n' might
 
49
 * be really annoying otherwise.)
 
50
 */
 
51
 
 
52
#define TOKENS 3
 
53
 
 
54
static char *token[TOKENS];
 
55
char *endptr;
 
56
 
 
57
static void split_input(void)
 
58
{
 
59
  /* r points to the last non-space character */
 
60
  char *s, *r;
 
61
  int k;
 
62
 
 
63
  for (k = 0, s = r = inputstr; k < TOKENS; ++k) {
 
64
    /* Skip leading whitespace */
 
65
    while (isspace(*s)) s++;
 
66
    token[k] = s;
 
67
    /* Skip token */
 
68
    while (*s && !isspace(*s)) r = s++;
 
69
  }
 
70
  while (*s) {
 
71
    while (isspace(*s)) s++;
 
72
    while (*s && !isspace(*s)) r = s++;
 
73
  }
 
74
  r[1] = '\0';
 
75
}
 
76
 
 
77
/*
 
78
 * Compares two tokens, returns 1 on equality. Tokens
 
79
 * are separated by whitespace.
 
80
 */
 
81
static int tokeneq(const char *s, const char *t)
 
82
{
 
83
  while (*s && *t && !isspace(*s) && !isspace(*t)) {
 
84
    if (*s++ != *t++) return 0;
 
85
  }
 
86
  return (!*s || isspace(*s)) && (!*t || isspace(*t));
 
87
}
 
88
  
 
89
void cmd_accepted(void) {}
 
90
 
 
91
void cmd_activate(void) 
 
92
{
 
93
  CLEAR (flags, TIMEOUT);
 
94
  CLEAR (flags, ENDED);
 
95
}
 
96
 
 
97
void cmd_analyze(void)
 
98
{
 
99
  /*
 
100
   * "analyze" mode is similar to force, hard and post together
 
101
   * in that it produces a text output like post, but must
 
102
   * think indefinitely like ponder.
 
103
   *
 
104
   * Some additional output is expected in command ".\n" but if ignored
 
105
   * this should not be sent any more
 
106
   */
 
107
 
 
108
/* TODO correct output, add fail high low */
 
109
 
 
110
   if (!(flags & ANALYZE)){
 
111
     preanalyze_flags=flags; /* save these flags for exit */
 
112
     SET (flags, ANALYZE);
 
113
     cmd_post();
 
114
     cmd_force();
 
115
     cmd_hard();
 
116
   }
 
117
}
 
118
 
 
119
void cmd_bk(void)
 
120
{
 
121
  /* Print moves from Open Book for Xboard/WinBoard */
 
122
  /* Lines must start with " " and end with blank line */
 
123
  /* No need to test for xboard as it is generally useful */
 
124
  BookQuery(1);
 
125
  printf("\n"); /* Blank line */
 
126
  fflush(stdout);
 
127
}
 
128
 
 
129
void cmd_black(void) 
 
130
{
 
131
 /* 
 
132
  * No longer used by Xboard but requested as a feature
 
133
  */
 
134
 
 
135
  NewPosition(); /* Reset some flags and settings */
 
136
  CLEAR ( flags, THINK);
 
137
  CLEAR ( flags, MANUAL);
 
138
  CLEAR (flags, TIMEOUT);   
 
139
  computer = white;
 
140
  if ( board.side == white ) {
 
141
    board.side = black;
 
142
    board.ep = -1; 
 
143
  }
 
144
}
 
145
 
 
146
void cmd_book(void)
 
147
{
 
148
  if (tokeneq(token[1], "add")) {
 
149
    if (access(token[2], F_OK) < 0) {
 
150
      printf("The syntax to add a new book is:\n\n\tbook add file.pgn\n");
 
151
    } else {
 
152
      BookPGNReadFromFile (token[2]);
 
153
    }
 
154
  } else if (tokeneq (token[1], "on") || tokeneq(token[1], "prefer")) {
 
155
    bookmode = BOOKPREFER;
 
156
    printf("book now on.\n");
 
157
  } else if (tokeneq (token[1], "off")) {
 
158
    bookmode = BOOKOFF;
 
159
    printf("book now off.\n");
 
160
  } else if (tokeneq (token[1], "best")) {
 
161
    bookmode = BOOKBEST;
 
162
    printf("book now best.\n");
 
163
  } else if (tokeneq (token[1], "worst")) {
 
164
    bookmode = BOOKWORST;
 
165
    printf("book now worst.\n");
 
166
  } else if (tokeneq (token[1], "random")) {
 
167
    bookmode = BOOKRAND;
 
168
    printf("book now random.\n");
 
169
  }
 
170
}
 
171
 
 
172
/* Our opponent is a computer */
 
173
void cmd_computer(void) {}
 
174
 
 
175
void cmd_depth(void)
 
176
{
 
177
  SearchDepth = atoi (token[1]);
 
178
  printf("Search to a depth of %d\n",SearchDepth);
 
179
}
 
180
 
 
181
/* Ignore draw offers */
 
182
void cmd_draw(void) {}
 
183
 
 
184
void cmd_easy(void) { CLEAR (flags, HARD); }
 
185
 
 
186
/* Predecessor to setboard */
 
187
void cmd_edit(void) 
 
188
{
 
189
  if ( flags & XBOARD ) {
 
190
    printf("tellusererror command 'edit' not implemented\n");
 
191
    fflush(stdout);
 
192
  }
 
193
}
 
194
 
 
195
void cmd_epd(void)
 
196
{
 
197
  ParseEPD (token[1]);
 
198
  NewPosition();
 
199
  ShowBoard();
 
200
  printf ("\n%s : Best move = %s\n", id, solution); 
 
201
}
 
202
 
 
203
void cmd_exit(void) 
 
204
 
205
  /*
 
206
   * "exit" is a synonym for quit except in engine mode
 
207
   * when it means leave analyze mode
 
208
   */
 
209
 
 
210
  if ( flags & ANALYZE ){
 
211
        flags = preanalyze_flags ; /* this implicitly clears ANALYZE flag */
 
212
  } else {
 
213
    cmd_quit(); 
 
214
  }
 
215
   
 
216
 
 
217
}
 
218
 
 
219
void cmd_force(void) { SET (flags, MANUAL); }
 
220
 
 
221
void cmd_go(void)
 
222
{
 
223
  SET (flags, THINK);
 
224
  CLEAR (flags, MANUAL);
 
225
  CLEAR (flags, TIMEOUT);
 
226
  CLEAR (flags, ENDED);
 
227
  computer = board.side;
 
228
}
 
229
 
 
230
void cmd_hard(void) { SET (flags, HARD); }
 
231
 
 
232
void cmd_hash(void)
 
233
{
 
234
  if (tokeneq (token[1], "off"))
 
235
    CLEAR (flags, USEHASH);
 
236
  else if (tokeneq (token[1], "on"))
 
237
    SET (flags, USEHASH);
 
238
  printf ("Hashing %s\n", flags & USEHASH ? "on" : "off");
 
239
}
 
240
 
 
241
void cmd_hashsize(void)
 
242
{
 
243
  if (token[1][0] == 0) {
 
244
    printf("Current HashSize is %d slots\n", HashSize);
 
245
  } else {
 
246
    int i;
 
247
    /* i = atoi (token[1]); */
 
248
    errno = 0;
 
249
    i = strtol (token[1], &endptr, 10);
 
250
    if ( errno != 0 || *endptr != '\0' ){
 
251
      printf("Hashsize out of Range or Invalid\n");
 
252
    }
 
253
    else {
 
254
     CalcHashSize(i);
 
255
     InitHashTable (); 
 
256
    }
 
257
  }
 
258
}
 
259
 
 
260
/* Give a possible move for the player to play */
 
261
void cmd_hint(void)
 
262
{
 
263
  if ( flags & ENDED ){
 
264
    printf("The game is over.\n");
 
265
  } else {
 
266
    int HintMove;
 
267
    HintMove = TreePtr[1]->move; /* Pick first move in tree */
 
268
    if (IsLegalMove(HintMove)){
 
269
      GenMoves(1);
 
270
      SANMove(TreePtr[1]->move,1);
 
271
      printf("Hint: %s\n", SANmv);
 
272
    } else {
 
273
      printf("No hint available at this time\n");
 
274
    }
 
275
  }
 
276
  fflush(stdout);
 
277
}
 
278
 
 
279
void cmd_level(void)
 
280
{
 
281
  SearchDepth = 0;
 
282
  sscanf (token[1], "%d %f %d", &TCMove, &TCTime, &TCinc);
 
283
  if (TCMove == 0) {
 
284
    TCMove =  35 /* MIN((5*(GameCnt+1)/2)+1,60) */;
 
285
    printf("TCMove = %d\n",TCMove);
 
286
    suddendeath = 1;
 
287
  } else
 
288
    suddendeath = 0;
 
289
  if (TCTime == 0) {
 
290
    SET (flags, TIMECTL);
 
291
    SearchTime = TCinc / 2.0f ;
 
292
    printf("Fischer increment of %d seconds\n",TCinc);
 
293
  } else {
 
294
    SET (flags, TIMECTL);
 
295
    MoveLimit[white] = MoveLimit[black] = TCMove - (GameCnt+1)/2;
 
296
    TimeLimit[white] = TimeLimit[black] = TCTime * 60;
 
297
    if (!(flags & XBOARD)) {
 
298
      printf ("Time Control: %d moves in %.2f secs\n", 
 
299
              MoveLimit[white], TimeLimit[white]);
 
300
      printf("Fischer increment of %d seconds\n",TCinc);
 
301
    }
 
302
  }
 
303
}
 
304
 
 
305
void cmd_list(void)
 
306
{
 
307
  if (token[1][0] == '?') {
 
308
    printf("name    - list known players alphabetically\n");
 
309
    printf("score   - list by GNU best result first \n");
 
310
    printf("reverse - list by GNU worst result first\n");
 
311
  } else {
 
312
    if (token[1][0] == '\0') DBListPlayer("rscore");
 
313
    else DBListPlayer(token[1]);
 
314
  }
 
315
}
 
316
 
 
317
void cmd_load(void)
 
318
{
 
319
  LoadEPD (token[1]);
 
320
  if (!ValidateBoard()) {
 
321
    SET (flags, ENDED);
 
322
    printf ("Board is wrong!\n");
 
323
  }
 
324
}
 
325
 
 
326
void cmd_manual(void) { SET (flags, MANUAL); }
 
327
 
 
328
/* Move now, not applicable */
 
329
void cmd_movenow(void) {}
 
330
 
 
331
/*
 
332
 * TODO: Add a logpath variable or macro, not always dump into current
 
333
 * dir. Again, how does one handle paths portably across Unix/Windows?
 
334
 *   -- Lukas 
 
335
 */
 
336
void cmd_name(void)
 
337
{
 
338
  int suffix = 0;
 
339
 
 
340
  /* name[sizeof name - 1] should always be 0 */
 
341
  strncpy(name, token[1], sizeof name - 1);
 
342
  for (suffix = 0; suffix < 1000; suffix++) {
 
343
    sprintf(logfile,"log.%03d",suffix);
 
344
    sprintf(gamefile,"game.%03d",suffix);
 
345
    /*
 
346
     * There is an obvious race condition here but who cares, we just
 
347
     * bail out in case of failure... --Lukas 
 
348
     */
 
349
    if (access(logfile,F_OK) < 0) {
 
350
      ofp = fopen(logfile,"w");
 
351
      if (ofp == NULL) {
 
352
        ofp = stdout;
 
353
        fprintf(stderr, "Failed to open %s for writing: %s\n", 
 
354
                logfile, strerror(errno));
 
355
      }
 
356
      return;
 
357
    }
 
358
  }
 
359
  fprintf(stderr, "Could not create logfile, all slots occupied.\n");
 
360
  fprintf(stderr, "You may consider deleting or renaming your existing logfiles.\n");
 
361
}
 
362
 
 
363
void cmd_new(void)
 
364
{
 
365
  InitVars ();
 
366
  NewPosition ();
 
367
  /* Protocol specification for ANALYZE says "new" does not end analysis */
 
368
  if (!(flags & ANALYZE))
 
369
    CLEAR (flags, MANUAL);
 
370
  CLEAR (flags, THINK);
 
371
  myrating = opprating = 0;
 
372
}
 
373
 
 
374
void cmd_nopost(void) { CLEAR (flags, POST); }
 
375
 
 
376
void cmd_null(void)
 
377
{
 
378
  if (tokeneq (token[1], "off"))
 
379
    CLEAR (flags, USENULL);
 
380
  else if (tokeneq (token[1], "on"))
 
381
    SET (flags, USENULL);
 
382
  printf ("Null moves %s\n", flags & USENULL ? "on" : "off");
 
383
}
 
384
 
 
385
void cmd_otim(void) {}
 
386
 
 
387
void cmd_pgnload(void) { PGNReadFromFile (token[1]); }
 
388
 
 
389
/*
 
390
 * XXX - Filenames with spaces will break here,
 
391
 * do we want to support them? I vote for "no" 
 
392
 *   - Lukas
 
393
 */
 
394
void cmd_pgnsave(void)
 
395
{
 
396
  if ( strlen(token[1]) > 0 )
 
397
    PGNSaveToFile (token[1], "");
 
398
  else
 
399
    printf("Invalid filename.\n");
 
400
}
 
401
 
 
402
void cmd_ping(void)
 
403
{
 
404
  /* If ping is received when we are on move, we are supposed to 
 
405
     reply only after moving.  In this version of GNU Chess, we
 
406
     never read commands while we are on move, so we don't have to
 
407
     worry about that here. */
 
408
  printf("pong %s\n", token[1]);
 
409
  fflush(stdout);
 
410
}
 
411
 
 
412
void cmd_post(void) { SET (flags, POST); }
 
413
 
 
414
void cmd_protover(void)
 
415
{
 
416
  if (flags & XBOARD) {
 
417
    /* Note: change this if "draw" command is added, etc. */
 
418
    printf("feature setboard=1 analyze=1 ping=1 draw=0 sigint=0"
 
419
           " variants=\"normal\" myname=\"%s %s\" done=1\n",
 
420
           PROGRAM, VERSION);
 
421
    fflush(stdout);
 
422
  }
 
423
}
 
424
 
 
425
void cmd_quit(void) { SET (flags, QUIT); }
 
426
 
 
427
void cmd_random(void) {}
 
428
 
 
429
void cmd_rating(void)
 
430
{
 
431
  myrating = atoi(token[1]);
 
432
  opprating = atoi(token[2]);
 
433
  fprintf(ofp,"my rating = %d, opponent rating = %d\n",myrating,opprating); 
 
434
  /* Change randomness of book based on opponent rating. */
 
435
  /* Basically we play narrower book the higher the opponent */
 
436
  if (opprating >= 1700) bookfirstlast = 2;
 
437
  else if (opprating >= 1700) bookfirstlast = 2;
 
438
  else bookfirstlast = 2;
 
439
}
 
440
 
 
441
void cmd_rejected(void) {}
 
442
 
 
443
void cmd_remove(void)
 
444
{
 
445
  if (GameCnt >= 0) {
 
446
    CLEAR (flags, ENDED);
 
447
    CLEAR (flags, TIMEOUT);
 
448
    UnmakeMove (board.side, &Game[GameCnt].move);
 
449
    if (GameCnt >= 0) {
 
450
      UnmakeMove (board.side, &Game[GameCnt].move);
 
451
      if (!(flags & XBOARD))
 
452
           ShowBoard ();
 
453
    }
 
454
    PGNSaveToFile ("game.log","");
 
455
  } else
 
456
    printf ("No moves to undo! \n");
 
457
}
 
458
 
 
459
void cmd_result(void)
 
460
{
 
461
  if (ofp != stdout) {  
 
462
    fprintf(ofp, "result: %s\n",token[1]);
 
463
    fclose(ofp); 
 
464
    ofp = stdout;
 
465
    printf("Save to %s\n",gamefile);
 
466
    PGNSaveToFile (gamefile, token[1]);
 
467
    DBUpdatePlayer (name, token[1]);
 
468
  }
 
469
}
 
470
        
 
471
void cmd_save(void)
 
472
{  
 
473
  if ( strlen(token[1]) > 0 )
 
474
    SaveEPD (token[1]);
 
475
  else
 
476
    printf("Invalid filename.\n");
 
477
}
 
478
 
 
479
void cmd_setboard(void)
 
480
{
 
481
  /* setboard uses FEN, not EPD, but ParseEPD will accept FEN too */
 
482
  ParseEPD (token[1]);
 
483
  NewPosition();
 
484
}
 
485
 
 
486
void cmd_solve(void) { Solve (token[1]); }
 
487
 
 
488
/* Set total time for move to be N seconds is "st N" */
 
489
void cmd_st(void) 
 
490
{
 
491
  /* Approximately level 1 0 N */
 
492
  sscanf(token[1],"%d",&TCinc);
 
493
  suddendeath = 0 ;
 
494
  /* Allow a little fussiness for failing low etc */
 
495
  SearchTime = TCinc * 0.90f ;
 
496
  CLEAR (flags, TIMECTL);
 
497
}
 
498
 
 
499
void cmd_switch(void)
 
500
{
 
501
  board.side = 1^board.side;
 
502
  board.ep = -1 ; /* Enpassant doesn't apply after switch */
 
503
  printf ("%s to move\n", board.side == white ? "White" : "Black");
 
504
}
 
505
 
 
506
void cmd_time(void)
 
507
{
 
508
  TimeLimit[1^board.side] = atoi(token[1]) / 100.0f ;
 
509
}
 
510
 
 
511
void cmd_undo(void)
 
512
{
 
513
  if (GameCnt >= 0)
 
514
    UnmakeMove (board.side, &Game[GameCnt].move);
 
515
  else
 
516
    printf ("No moves to undo! \n");
 
517
  MoveLimit[board.side]++;
 
518
  TimeLimit[board.side] += Game[GameCnt+1].et;
 
519
  if (!(flags & XBOARD)) ShowBoard ();
 
520
}
 
521
 
 
522
void cmd_usage(void) 
 
523
{
 
524
      printf (
 
525
     "\n"
 
526
     " Usage: %s [OPTION]\n"
 
527
     "\n"
 
528
     " -h, --help         display this help and exit\n"
 
529
     " -v, --version      display version information and exit\n" 
 
530
     "\n"
 
531
     " -x, --xboard       start in engine mode\n"
 
532
     " -p, --post          start up showing thinking\n"
 
533
     " -e, --easy          disable thinking in opponents time\n"
 
534
     " -m, --manual        enable manual mode\n"
 
535
     " -s size, --hashsize=size   specify hashtable size in slots\n"
 
536
     "\n"
 
537
     " Options xboard and post are accepted without leading dashes\n"
 
538
     " for backward compatibility\n"
 
539
     "\n"
 
540
     "Report bugs to <bug-gnu-chess@gnu.org>.\n"
 
541
     "\n", progname);
 
542
     }
 
543
 
 
544
 
 
545
/* Play variant, we instruct interface in protover we play normal */
 
546
void cmd_variant(void) {}
 
547
 
 
548
void cmd_version(void)
 
549
{
 
550
   if (!(flags & XBOARD))
 
551
     printf ("%s %s\n", PROGRAM, VERSION);
 
552
   else
 
553
     printf ("Chess\n");
 
554
}
 
555
 
 
556
void cmd_white(void) 
 
557
{
 
558
 /* 
 
559
  * No longer used by Xboard but requested as a feature
 
560
  */
 
561
 
 
562
  NewPosition(); /* Reset some flags and settings */
 
563
  CLEAR ( flags, THINK);
 
564
  CLEAR ( flags, MANUAL);
 
565
  CLEAR (flags, TIMEOUT);   
 
566
  computer = black;
 
567
  if ( board.side == black ){
 
568
    board.side = white;
 
569
    board.ep = -1; /* Hack to fixed appearing pawn bug */
 
570
  }
 
571
}
 
572
 
 
573
void cmd_xboard(void)
 
574
{
 
575
  if (tokeneq (token[1], "off"))
 
576
    CLEAR (flags, XBOARD);
 
577
  else if (tokeneq (token[1], "on"))
 
578
    SET (flags, XBOARD);
 
579
  else if (!(flags & XBOARD)) { /* set if unset and only xboard called */
 
580
    SET (flags, XBOARD);            /* like in xboard/winboard usage */
 
581
  }
 
582
}
 
583
 
 
584
/*
 
585
 * Command with subcommands, could write secondary method
 
586
 * tables here
 
587
 */
 
588
 
 
589
void cmd_show (void)
 
590
/************************************************************************
 
591
 *
 
592
 *  The show command driver section.
 
593
 *
 
594
 ************************************************************************/
 
595
{
 
596
   if (tokeneq (token[1], "board"))
 
597
      ShowBoard ();
 
598
   else if (tokeneq (token[1], "rating"))
 
599
   {
 
600
      printf("My rating = %d\n",myrating);
 
601
      printf("Opponent rating = %d\n",opprating);
 
602
   } 
 
603
   else if (tokeneq (token[1], "time"))
 
604
      ShowTime ();
 
605
   else if (tokeneq (token[1], "moves")) {
 
606
      GenCnt = 0;
 
607
      TreePtr[2] = TreePtr[1];
 
608
      GenMoves (1);      
 
609
      ShowMoveList (1);
 
610
      printf ("No. of moves generated = %ld\n", GenCnt);
 
611
   }
 
612
   else if (tokeneq (token[1], "escape")) {
 
613
      GenCnt = 0;
 
614
      TreePtr[2] = TreePtr[1];
 
615
      GenCheckEscapes (1);      
 
616
      ShowMoveList (1);
 
617
      printf ("No. of moves generated = %ld\n", GenCnt);
 
618
   }
 
619
   else if (tokeneq (token[1], "noncapture"))
 
620
   {
 
621
      GenCnt = 0;
 
622
      TreePtr[2] = TreePtr[1];
 
623
      GenNonCaptures (1);      
 
624
      FilterIllegalMoves (1);
 
625
      ShowMoveList (1);
 
626
      printf ("No. of moves generated = %ld\n", GenCnt);
 
627
   }
 
628
   else if (tokeneq (token[1], "capture"))
 
629
   {
 
630
      GenCnt = 0;
 
631
      TreePtr[2] = TreePtr[1];
 
632
      GenCaptures (1);      
 
633
      FilterIllegalMoves (1);
 
634
      ShowMoveList (1);
 
635
      printf ("No. of moves generated = %ld\n", GenCnt);
 
636
   }
 
637
   else if (tokeneq (token[1], "eval") || tokeneq (token[1], "score"))
 
638
   {
 
639
      int s, wp, bp, wk, bk;
 
640
      BitBoard *b;
 
641
 
 
642
      phase = PHASE;
 
643
      GenAtaks ();
 
644
      FindPins (&pinned);
 
645
      hunged[white] = EvalHung(white);
 
646
      hunged[black] = EvalHung(black);
 
647
      b = board.b[white];
 
648
      pieces[white] = b[knight] | b[bishop] | b[rook] | b[queen]; 
 
649
      b = board.b[black];
 
650
      pieces[black] = b[knight] | b[bishop] | b[rook] | b[queen]; 
 
651
      wp = ScoreP (white);
 
652
      bp = ScoreP (black);
 
653
      wk = ScoreK (white);
 
654
      bk = ScoreK (black);
 
655
      printf ("White:  Mat:%4d/%4d  P:%d  N:%d  B:%d  R:%d  Q:%d  K:%d  Dev:%d  h:%d x:%d\n",
 
656
        board.pmaterial[white], board.material[white], wp, ScoreN(white), 
 
657
        ScoreB(white), ScoreR(white), ScoreQ(white), wk, 
 
658
        ScoreDev(white), hunged[white], ExchCnt[white]);
 
659
      printf ("Black:  Mat:%4d/%4d  P:%d  N:%d  B:%d  R:%d  Q:%d  K:%d  Dev:%d  h:%d x:%d\n",
 
660
        board.pmaterial[black], board.material[black], bp, ScoreN(black), 
 
661
        ScoreB(black), ScoreR(black), ScoreQ(black), bk,
 
662
        ScoreDev(black), hunged[black], ExchCnt[black]);
 
663
      printf ("Phase: %d\t", PHASE);
 
664
      s = ( EvaluateDraw () ? DRAWSCORE : Evaluate (-INFINITY, INFINITY));
 
665
      printf ("score = %d\n", s);
 
666
      printf ("\n");
 
667
   }
 
668
   else if (tokeneq (token[1], "game"))
 
669
     ShowGame ();
 
670
   else if (tokeneq (token[1], "pin"))
 
671
   {
 
672
      BitBoard b;
 
673
      GenAtaks ();
 
674
      FindPins (&b);
 
675
      ShowBitBoard (&b);
 
676
   }
 
677
}
 
678
 
 
679
void cmd_test (void)
 
680
/*************************************************************************
 
681
 *
 
682
 *  The test command driver section.
 
683
 *
 
684
 *************************************************************************/
 
685
{
 
686
  if (tokeneq (token[1], "movelist"))
 
687
    TestMoveList ();
 
688
  else if (tokeneq (token[1], "capture"))
 
689
    TestCaptureList ();
 
690
  else if (tokeneq (token[1], "movegenspeed"))
 
691
    TestMoveGenSpeed ();
 
692
  else if (tokeneq (token[1], "capturespeed"))
 
693
    TestCaptureGenSpeed ();
 
694
  else if (tokeneq (token[1], "eval"))
 
695
    TestEval ();
 
696
  else if (tokeneq (token[1], "evalspeed"))
 
697
    TestEvalSpeed ();
 
698
}
 
699
 
 
700
/*
 
701
 * This is more or less copied from the readme, and the
 
702
 * parser is not very clever, so the lines containing
 
703
 * command names should not be indented, the lines with
 
704
 * explanations following them should be indented. Do not
 
705
 * use tabs for indentation, only spaces. CAPITALS are
 
706
 * reserved for parameters in the command names. The
 
707
 * array must be terminated by two NULLs.
 
708
 * 
 
709
 * This one should be integrated in the method table.
 
710
 * (Very much like docstrings in Lisp.)
 
711
 */
 
712
 
 
713
static const char * const helpstr[] = {
 
714
   "^C",
 
715
   " Typically the interrupt key stops a search in progress,",
 
716
   " makes the move last considered best and returns to the",
 
717
   " command prompt",
 
718
   "quit",
 
719
   " quit the program.",
 
720
   "exit",
 
721
   " In analysis mode this stops analysis, otherwise it quits the program.",
 
722
   "help",
 
723
   " Produces a help blurb corresponding to this list of commands.",
 
724
   "book",
 
725
   " add - compiles book.dat from book.pgn",
 
726
   " on - enables use of book",
 
727
   " off - disables use of book",
 
728
   " worst - play worst move from book",
 
729
   " best - play best move from book",
 
730
   " prefer - default, same as 'book on'",
 
731
   " random - play any move from book",
 
732
   "version",
 
733
   " prints out the version of this program",
 
734
   "pgnsave FILENAME",
 
735
   " saves the game so far to the file from memory",
 
736
   "pgnload FILENAME",
 
737
   " loads the game in the file into memory",
 
738
   "force",
 
739
   "manual",
 
740
   " Makes the program stop moving. You may now enter moves",
 
741
   " to reach some position in the future.",
 
742
   " ",
 
743
   "white",
 
744
   " Program plays white",
 
745
   "black",
 
746
   " Program plays black",
 
747
   "go",
 
748
   " Computer takes whichever side is on move and begins its",
 
749
   " thinking immediately",
 
750
   "post",
 
751
   " Arranges for verbose thinking output showing variation, score,",
 
752
   " time, depth, etc.",
 
753
   "nopost",
 
754
   " Turns off verbose thinking output",
 
755
   "name NAME",
 
756
   " Lets you input your name. Also writes the log.nnn and a",
 
757
   " corresponding game.nnn file. For details please see",
 
758
   " auxillary file format sections.",
 
759
   "result",
 
760
   " Mostly used by Internet Chess server.",
 
761
   "activate",
 
762
   " This command reactivates a game that has been terminated automatically",
 
763
   " due to checkmate or no more time on the clock. However, it does not",
 
764
   " alter those conditions. You would have to undo a move or two or",
 
765
   " add time to the clock with level or time in that case.",
 
766
   "rating COMPUTERRATING OPPONENTRATING",
 
767
   " Inputs the estimated rating for computer and for its opponent",
 
768
   "new",
 
769
   " Sets up new game (i.e. positions in original positions)",
 
770
   "time",
 
771
   " Inputs time left in game for computer in hundredths of a second.",
 
772
   " Mostly used by Internet Chess server.",
 
773
   "hash",
 
774
   " on - enables using the memory hash table to speed search",
 
775
   " off - disables the memory hash table",
 
776
   "hashsize N",
 
777
   " Sets the hash table to permit storage of N positions",
 
778
   "null",
 
779
   " on - enables using the null move heuristic to speed search",
 
780
   " off - disables using the null move heuristic",
 
781
   "xboard",
 
782
   " on - enables use of xboard/winboard",
 
783
   " off - disables use of xboard/winboard",
 
784
   "depth N",
 
785
   " Sets the program to look N ply (half-moves) deep for every",
 
786
   " search it performs. If there is a checkmate or other condition",
 
787
   " that does not allow that depth, then it will not be ",
 
788
   "level MOVES MINUTES INCREMENT",
 
789
   " Sets time control to be MOVES in MINUTES with each move giving",
 
790
   " an INCREMENT (in seconds, i.e. Fischer-style clock).",
 
791
   "load",
 
792
   "epdload",
 
793
   " Loads a position in EPD format from disk into memory.",
 
794
   "save",
 
795
   "epdsave",
 
796
   " Saves game position into EPD format from memory to disk.",
 
797
   "switch",
 
798
   " Switches side to move",
 
799
   "solve FILENAME",
 
800
   "solveepd FILENAME",
 
801
   " Solves the positions in FILENAME",
 
802
   "remove",
 
803
   " Backs up two moves in game history",
 
804
   "undo",
 
805
   " Backs up one move in game history",
 
806
   "usage",
 
807
   " Display command line syntax",
 
808
   "show",
 
809
   " board - displays the current board",
 
810
   " time - displays the time settings",
 
811
   " moves - shows all moves using one call to routine",
 
812
   " escape - shows moves that escape from check using one call to routine",
 
813
   " noncapture - shows non-capture moves",
 
814
   " capture - shows capture moves",
 
815
   " eval [or score] - shows the evaluation per piece and overall",
 
816
   " game - shows moves in game history",
 
817
   " pin - shows pinned pieces",
 
818
   "test",
 
819
   " movelist - reads in an epd file and shows legal moves for its entries",
 
820
   " capture - reads in an epd file and shows legal captures for its entries",
 
821
   " movegenspeed - tests speed of move generator",
 
822
   " capturespeed - tests speed of capture move generator",
 
823
   " eval - reads in an epd file and shows evaluation for its entries",
 
824
   " evalspeed tests speed of the evaluator",
 
825
   "bk",
 
826
   " show moves from opening book.",
 
827
   NULL,
 
828
   NULL
 
829
};
 
830
 
 
831
void cmd_help (void)
 
832
/**************************************************************************
 
833
 *
 
834
 *  Display all the help commands.
 
835
 *
 
836
 **************************************************************************/
 
837
{
 
838
   const char * const *p;
 
839
   int count, len;
 
840
 
 
841
   if (strlen(token[1])>0) {
 
842
      for (p=helpstr, count=0; *p; p++) {
 
843
         if  (strncmp(*p, token[1], strlen(token[1])) == 0) {
 
844
            puts(*p);
 
845
            while (*++p && **p != ' ') /* Skip aliases */ ;
 
846
            for (; *p && **p == ' '; p++) {
 
847
               puts(*p);
 
848
            }
 
849
            return;
 
850
         }
 
851
      }
 
852
      printf("Help for command %s not found\n\n", token[1]);
 
853
   }
 
854
   printf("List of commands: (help COMMAND to get more help)\n");
 
855
   for (p=helpstr, count=0; *p; p++) {
 
856
      len = strcspn(*p, " ");
 
857
      if (len > 0) {
 
858
         count += printf("%.*s  ", len, *p);
 
859
         if (count > 60) {
 
860
            count = 0;
 
861
            puts("");
 
862
         }
 
863
      }
 
864
   }
 
865
   puts("");
 
866
}
 
867
 
 
868
/*
 
869
 * Try a method table, one could also include the documentation
 
870
 * strings here
 
871
 */
 
872
 
 
873
struct methodtable {
 
874
  const char *name;
 
875
  void (*method) (void);
 
876
};
 
877
 
 
878
/* Last entry contains to NULL pointers */
 
879
 
 
880
/* List commands we don't implement to avoid illegal moving them */
 
881
 
 
882
const struct methodtable commands[] = {
 
883
  { "?", cmd_movenow },
 
884
  { "accepted", cmd_accepted },
 
885
  { "activate", cmd_activate },
 
886
  { "analyze", cmd_analyze },
 
887
  { "bk", cmd_bk },
 
888
  { "black", cmd_black },
 
889
  { "book", cmd_book },
 
890
  { "computer", cmd_computer },
 
891
  { "depth", cmd_depth },
 
892
  { "draw", cmd_draw },
 
893
  { "easy", cmd_easy },
 
894
  { "edit", cmd_edit },
 
895
  { "epd", cmd_epd },
 
896
  { "epdload", cmd_load },
 
897
  { "epdsave", cmd_save },
 
898
  { "exit", cmd_exit },
 
899
  { "force", cmd_force },
 
900
  { "go", cmd_go },
 
901
  { "hard", cmd_hard },
 
902
  { "hash", cmd_hash },
 
903
  { "hashsize", cmd_hashsize },
 
904
  { "help", cmd_help },
 
905
  { "hint", cmd_hint },
 
906
  { "level", cmd_level },
 
907
  { "list", cmd_list },
 
908
  { "load", cmd_load },
 
909
  { "manual", cmd_manual },
 
910
  { "name", cmd_name },
 
911
  { "new", cmd_new },
 
912
  { "nopost", cmd_nopost },
 
913
  { "null", cmd_null },
 
914
  { "otim", cmd_otim },
 
915
  { "pgnload", cmd_pgnload },
 
916
  { "pgnsave", cmd_pgnsave },
 
917
  { "ping", cmd_ping },
 
918
  { "post", cmd_post },
 
919
  { "protover", cmd_protover },
 
920
  { "quit", cmd_quit },
 
921
  { "random", cmd_random },
 
922
  { "rating", cmd_rating },
 
923
  { "rejected", cmd_rejected },
 
924
  { "remove", cmd_remove },
 
925
  { "result", cmd_result },
 
926
  { "save", cmd_save },
 
927
  { "setboard", cmd_setboard },
 
928
  { "show", cmd_show },
 
929
  { "solve", cmd_solve },
 
930
  { "solveepd", cmd_solve },
 
931
  { "st", cmd_st },
 
932
  { "switch", cmd_switch },
 
933
  { "test", cmd_test },
 
934
  { "time", cmd_time },
 
935
  { "undo", cmd_undo },
 
936
  { "usage", cmd_usage },
 
937
  { "variant", cmd_variant },
 
938
  { "version", cmd_version },
 
939
  { "white", cmd_white },
 
940
  { "xboard", cmd_xboard },
 
941
  { NULL, NULL }
 
942
};
 
943
 
 
944
void parse_input(void)
 
945
/*************************************************************************
 
946
 *
 
947
 *  This is the main user command interface driver.
 
948
 *
 
949
 *************************************************************************/
 
950
{
 
951
   leaf *ptr; 
 
952
   const struct methodtable * meth;
 
953
 
 
954
   dbg_printf("parse_input() called, inputstr = *%s*\n", inputstr);
 
955
   
 
956
   split_input();
 
957
 
 
958
   for (meth = commands; meth->name != NULL; meth++) {
 
959
     if (tokeneq(token[0], meth->name)) {
 
960
       meth->method();
 
961
       return;
 
962
     }
 
963
   }
 
964
 
 
965
   /* OK, no known command, this should be a move */
 
966
   ptr = ValidateMove (token[0]);
 
967
   if (ptr != NULL) {
 
968
     SANMove (ptr->move, 1);
 
969
     MakeMove (board.side, &ptr->move);
 
970
     strcpy (Game[GameCnt].SANmv, SANmv);
 
971
     printf("%d. ",GameCnt/2+1);
 
972
     printf("%s",token[0]);
 
973
     if (ofp != stdout) {
 
974
       fprintf(ofp,"%d. ",GameCnt/2+1);
 
975
       fprintf(ofp,"%s",token[0]);
 
976
     }
 
977
     putchar('\n');
 
978
     fflush(stdout);
 
979
     if (ofp != stdout) {
 
980
       fputc('\n',ofp);
 
981
       fflush(ofp);
 
982
     }
 
983
     if (!(flags & XBOARD)) ShowBoard (); 
 
984
     SET (flags, THINK);
 
985
   }
 
986
   else {
 
987
     /*
 
988
      * Must Output Illegal move to prevent Xboard accepting illegal
 
989
      * en passant captures and other subtle mistakes
 
990
      */
 
991
     printf("Illegal move: %s\n",token[0]);
 
992
     fflush(stdout);
 
993
   }  
 
994
}
 
995