Subversion Repositories Games.Chess Giants

Rev

Rev 108 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
33 pmbaty 1
#include "chess.h"
2
#include "data.h"
3
/* last modified 02/26/14 */
4
/*
5
 *******************************************************************************
6
 *                                                                             *
7
 *   "annotate" command is used to search through the game in a pgn file, and  *
8
 *   provide a qualitative analysis of each move played and then creating a    *
9
 *   new output file (xxx.can) containing the original game + new commentary.  *
10
 *                                                                             *
11
 *   The normal output of this command is a file, in PGN format, that contains *
12
 *   the moves of the game, along with analysis when Crafty does not think     *
13
 *   that move was the best choice.  The definition of "best choice" is        *
14
 *   somewhat vague, because if the move played is "close" to the best move    *
15
 *   available, Crafty will not comment on the move.  "Close" is defined by    *
16
 *   the <margin> option explained below.  This basic type of annotation works *
17
 *   by first using the normal tree search algorithm to find the best move.    *
18
 *   If this move was the move played, no output is produced.  If a different  *
19
 *   move is considered best, then the actual move played is searched to the   *
20
 *   same depth and if the best move and actual move scores are within         *
21
 *   <margin> of each other, no comment is produced, otherwise Crafty inserts  *
22
 *   the evaluation for the move played, followed by the eval and PV for the   *
23
 *   best continuation it found.  You can enter suggested moves for Crafty to  *
24
 *   analyze at any point by simply entering a move as an analysis-type        *
25
 *   comment using (move) or {move}.  Crafty will search that move in addition *
26
 *   to the move actually played and the move it thinks is best.               *
27
 *                                                                             *
28
 *   The format of the command is as follows:                                  *
29
 *                                                                             *
108 pmbaty 30
 *        annotate filename b|w|bw|name moves margin time [n]                  *
33 pmbaty 31
 *                                                                             *
32
 *   Filename is the input file where Crafty will obtain the moves to          *
33
 *   annotate, and output will be written to file "filename.can".              *
34
 *                                                                             *
108 pmbaty 35
 *        annotateh filename b|w|bw|name moves margin time [n]                 *
33 pmbaty 36
 *                                                                             *
37
 *   Can be used to produce an HTML-compatible file that includes bitmapped    *
38
 *   diagrams of the positions where Crafty provides analysis.  This file can  *
39
 *   be opened by a browser to provide much easier 'reading'.                  *
40
 *                                                                             *
108 pmbaty 41
 *        annotatet filename b|w|bw|name moves margin time [n]                 *
33 pmbaty 42
 *                                                                             *
43
 *   Can be used to produce a LaTeX-compatible file that includes LaTeX chess  *
44
 *   fonts.  This file can be read/printed by any program that can handle      *
45
 *   LaTeX input.                                                              *
46
 *                                                                             *
47
 *   Where b/w/bw indicates whether to annotate only the white side (w), the   *
48
 *   black side (b) or both (bw).  You can also specify a name (or part of a   *
49
 *   name, just be sure it is unique in the name tags for clarity in who you   *
50
 *   mean).                                                                    *
51
 *                                                                             *
52
 *   Moves indicates the move or moves to annotate.  It can be a single move,  *
53
 *   which indicates the starting move number to annotate, or it can be a      *
54
 *   range, which indicates a range of move (1-999 gets the whole game.)       *
55
 *                                                                             *
56
 *   Margin is the difference between Crafty's evaluation for the move         *
57
 *   actually played and for the move Crafty thinks is best, before Crafty     *
58
 *   will generate a comment in the annotation file.  1.0 is a pawn, and will  *
59
 *   only generate comments if the move played is 1.000 (1 pawn) worse than    *
60
 *   the best move found by doing a complete search.                           *
61
 *                                                                             *
62
 *   Time is time per move to search, in seconds.                              *
63
 *                                                                             *
64
 *   [n] is optional and tells Crafty to produce the PV/score for the "n" best *
65
 *   moves.  Crafty stops when the best move reaches the move played in the    *
66
 *   game or after displaying n moves, whichever comes first.  If you use -n,  *
67
 *   then it will display n moves regardless of where the game move ranks.     *
68
 *                                                                             *
69
 *******************************************************************************
70
 */
71
#define MIN_DECISIVE_ADV 150
72
#define MIN_MODERATE_ADV  70
73
#define MIN_SLIGHT_ADV    30
74
void Annotate() {
75
  FILE *annotate_in, *annotate_out;
76
  char text[128], tbuffer[4096], colors[32] = { "" }, pname[128] = {
77
  ""};
78
  int annotate_margin, annotate_score[100], player_score, best_moves,
79
      annotate_wtm;
80
  int annotate_search_time_limit, search_player;
81
  int twtm, path_len, analysis_printed = 0;
82
  int wtm, move_num, line1, line2, move, suggested, i;
83
  int searches_done, read_status;
84
  PATH temp[100], player_pv;
85
  int temp_search_depth;
86
  TREE *const tree = block[0];
87
  char html_br[5] = { "" };
88
  int save_swindle_mode;
89
  int html_mode = 0;
90
  int latex = 0;
91
 
92
/*
93
 ************************************************************
94
 *                                                          *
95
 *  First, extract the options from the command line to     *
96
 *  determine what the user wanted us to do.                *
97
 *                                                          *
98
 ************************************************************
99
 */
100
  save_swindle_mode = swindle_mode;
101
  if (!strcmp(args[0], "annotateh")) {
102
    html_mode = 1;
103
    strcpy(html_br, "<br>");
104
  }
105
  if (!strcmp(args[0], "annotatet")) {
106
    latex = 1;
107
    strcpy(html_br, "\\\\");
108
  }
109
  strcpy(tbuffer, buffer);
108 pmbaty 110
  nargs = ReadParse(tbuffer, args, " \t;");
33 pmbaty 111
  if (nargs < 6) {
112
    printf
113
        ("usage: annotate <file> <color> <moves> <margin> <time> [nmoves]\n");
114
    return;
115
  }
116
  annotate_in = fopen(args[1], "r");
117
  if (annotate_in == NULL) {
118
    Print(4095, "unable to open %s for input\n", args[1]);
119
    return;
120
  }
108 pmbaty 121
  nargs = ReadParse(tbuffer, args, " \t;");
33 pmbaty 122
  strcpy(text, args[1]);
123
  if (html_mode == 1)
124
    strcpy(text + strlen(text), ".html");
125
  else if (latex == 1)
126
    strcpy(text + strlen(text), ".tex");
127
  else
128
    strcpy(text + strlen(text), ".can");
129
  annotate_out = fopen(text, "w");
130
  if (annotate_out == NULL) {
131
    Print(4095, "unable to open %s for output\n", text);
132
    return;
133
  }
134
  if (html_mode == 1)
135
    AnnotateHeaderHTML(text, annotate_out);
136
  if (latex == 1)
137
    AnnotateHeaderTeX(annotate_out);
138
  if (strlen(args[2]) <= 2)
139
    strcpy(colors, args[2]);
140
  else
141
    strcpy(pname, args[2]);
142
  line1 = 1;
143
  line2 = 999;
144
  if (strchr(args[3], 'b'))
145
    line2 = -1;
146
  if (strchr(args[3], '-'))
147
    sscanf(args[3], "%d-%d", &line1, &line2);
148
  else {
149
    sscanf(args[3], "%d", &line1);
150
    line2 = 999;
151
  }
154 pmbaty 152
  annotate_margin = atof(args[4]) * PieceValues(white, pawn);
153
  annotate_search_time_limit = atof(args[5]) * 100;
33 pmbaty 154
  if (nargs > 6)
155
    best_moves = atoi(args[6]);
156
  else
157
    best_moves = 1;
158
/*
159
 ************************************************************
160
 *                                                          *
161
 *  Reset the game to "square 0" to start the annotation    *
162
 *  procedure.  Then we read moves from the input file,     *
163
 *  make them on the game board, and annotate if the move   *
164
 *  is for the correct side.  If we haven't yet reached the *
165
 *  starting move to annotate, we skip the Search() stuff   *
166
 *   and read another move.                                 *
167
 *                                                          *
168
 ************************************************************
169
 */
170
  annotate_mode = 1;
171
  swindle_mode = 0;
172
  ponder = 0;
173
  temp_search_depth = search_depth;
174
  read_status = ReadPGN(0, 0);
175
  read_status = ReadPGN(annotate_in, 0);
176
  player_pv.path[1] = 0;
177
  while (read_status != -1) {
178
    ponder_move = 0;
179
    last_pv.pathd = 0;
180
    last_pv.pathl = 0;
181
    player_pv.pathd = 0;
182
    player_pv.pathl = 0;
183
    tree->pv[0].pathl = 0;
184
    tree->pv[0].pathd = 0;
185
    analysis_printed = 0;
186
    InitializeChessBoard(tree);
187
    tree->status[1] = tree->status[0];
188
    wtm = 1;
189
    move_number = 1;
190
/*
191
 ************************************************************
192
 *                                                          *
193
 *  Now grab the PGN tag values so they can be copied to    *
194
 *  the .can file for reference.                            *
195
 *                                                          *
196
 ************************************************************
197
 */
198
    do
199
      read_status = ReadPGN(annotate_in, 0);
200
    while (read_status == 1);
201
    if (read_status == -1)
202
      break;
203
    if (latex == 0) {
204
      fprintf(annotate_out, "[Event \"%s\"]%s\n", pgn_event, html_br);
205
      fprintf(annotate_out, "[Site \"%s\"]%s\n", pgn_site, html_br);
206
      fprintf(annotate_out, "[Date \"%s\"]%s\n", pgn_date, html_br);
207
      fprintf(annotate_out, "[Round \"%s\"]%s\n", pgn_round, html_br);
208
      fprintf(annotate_out, "[White \"%s\"]%s\n", pgn_white, html_br);
209
      fprintf(annotate_out, "[WhiteElo \"%s\"]%s\n", pgn_white_elo, html_br);
210
      fprintf(annotate_out, "[Black \"%s\"]%s\n", pgn_black, html_br);
211
      fprintf(annotate_out, "[BlackElo \"%s\"]%s\n", pgn_black_elo, html_br);
212
      fprintf(annotate_out, "[Result \"%s\"]%s\n", pgn_result, html_br);
213
      fprintf(annotate_out, "[Annotator \"Crafty v%s\"]%s\n", version,
214
          html_br);
215
      if (strlen(colors) != 0) {
216
        if (!strcmp(colors, "bw") || !strcmp(colors, "wb"))
217
          fprintf(annotate_out,
218
              "{annotating both black and white moves.}%s\n", html_br);
219
        else if (strchr(colors, 'b'))
220
          fprintf(annotate_out, "{annotating only black moves.}%s\n",
221
              html_br);
222
        else if (strchr(colors, 'w'))
223
          fprintf(annotate_out, "{annotating only white moves.}%s\n",
224
              html_br);
225
      } else
226
        fprintf(annotate_out, "{annotating for player %s}%s\n", pname,
227
            html_br);
228
      fprintf(annotate_out, "{using a scoring margin of %s pawns.}%s\n",
229
          DisplayEvaluationKibitz(annotate_margin, wtm), html_br);
230
      fprintf(annotate_out, "{search time limit is %s}%s\n%s\n",
231
          DisplayTimeKibitz(annotate_search_time_limit), html_br, html_br);
232
    } else {
233
      fprintf(annotate_out, "\\textbf{\\sc %s %s -- %s %s}%s\n", pgn_white,
234
          pgn_white_elo, pgn_black, pgn_black_elo, html_br);
235
      fprintf(annotate_out, "{\\em %s, %s}%s\n", pgn_site, pgn_date, html_br);
236
      fprintf(annotate_out, "{\\small %s, Round: %s}%s\n", pgn_event,
237
          pgn_round, html_br);
238
      fprintf(annotate_out, "\\begin{mainline}{%s}{Crafty v%s}\n", pgn_result,
239
          version);
240
    }
241
    if (strlen(colors)) {
242
      if (!strcmp(colors, "w"))
243
        annotate_wtm = 1;
244
      else if (!strcmp(colors, "b"))
245
        annotate_wtm = 0;
246
      else if (!strcmp(colors, "wb"))
247
        annotate_wtm = 2;
248
      else if (!strcmp(colors, "bw"))
249
        annotate_wtm = 2;
250
      else {
251
        Print(4095, "invalid color specification, retry\n");
252
        fclose(annotate_out);
253
        return;
254
      }
255
    } else {
256
      if (strstr(pgn_white, pname))
257
        annotate_wtm = 1;
258
      else if (strstr(pgn_black, pname))
259
        annotate_wtm = 0;
260
      else {
261
        Print(4095, "Player name doesn't match any PGN name tag, retry\n");
262
        fclose(annotate_out);
263
        return;
264
      }
265
    }
154 pmbaty 266
    while (FOREVER) {
33 pmbaty 267
      fflush(annotate_out);
268
      move = ReadNextMove(tree, buffer, 0, wtm);
269
      if (move <= 0)
270
        break;
108 pmbaty 271
      strcpy(text, OutputMove(tree, 0, wtm, move));
33 pmbaty 272
      if (history_file) {
273
        fseek(history_file, ((move_number - 1) * 2 + 1 - wtm) * 10, SEEK_SET);
274
        fprintf(history_file, "%9s\n", text);
275
      }
276
      if (wtm)
277
        Print(4095, "White(%d): %s\n", move_number, text);
278
      else
279
        Print(4095, "Black(%d): %s\n", move_number, text);
280
      if (analysis_printed)
281
        fprintf(annotate_out, "%3d.%s%8s\n", move_number,
282
            (wtm ? "" : "     ..."), text);
283
      else {
284
        if (wtm)
285
          fprintf(annotate_out, "%3d.%8s", move_number, text);
286
        else
287
          fprintf(annotate_out, "%8s\n", text);
288
      }
289
      analysis_printed = 0;
290
      if (move_number >= line1 && move_number <= line2) {
291
        if (annotate_wtm == 2 || annotate_wtm == wtm) {
292
          last_pv.pathd = 0;
293
          last_pv.pathl = 0;
294
          thinking = 1;
295
          RootMoveList(wtm);
296
/*
297
 ************************************************************
298
 *                                                          *
299
 *  Search the position to see if the move played is the    *
300
 *  best move possible.  If not, then search just the move  *
301
 *  played to get a score for it as well, so we can         *
302
 *  determine if annotated output is appropriate.           *
303
 *                                                          *
304
 ************************************************************
305
 */
306
          search_time_limit = annotate_search_time_limit;
307
          search_depth = temp_search_depth;
308
          player_score = -999999;
309
          search_player = 1;
310
          for (searches_done = 0; searches_done < Abs(best_moves);
311
              searches_done++) {
312
            if (searches_done > 0) {
313
              search_time_limit = 3 * annotate_search_time_limit;
314
              search_depth = temp[0].pathd;
315
            }
316
            Print(4095, "\n              Searching all legal moves.");
317
            Print(4095, "----------------------------------\n");
318
            tree->status[1] = tree->status[0];
108 pmbaty 319
            InitializeHashTables(0);
33 pmbaty 320
            annotate_score[searches_done] = Iterate(wtm, annotate, 1);
321
            if (tree->pv[0].path[1] == move) {
322
              player_score = annotate_score[searches_done];
323
              player_pv = tree->pv[0];
324
              search_player = 0;
325
            }
326
            temp[searches_done] = tree->pv[0];
327
            for (i = 0; i < n_root_moves; i++) {
328
              if (root_moves[i].move == tree->pv[0].path[1]) {
329
                for (; i < n_root_moves; i++)
330
                  root_moves[i] = root_moves[i + 1];
331
                n_root_moves--;
332
                break;
333
              }
334
            }
335
            if (n_root_moves == 0 || (annotate_margin >= 0 &&
336
                    player_score + annotate_margin >
337
                    annotate_score[searches_done]
338
                    && best_moves > 0)) {
339
              if (n_root_moves == 0)
340
                searches_done++;
341
              break;
342
            }
343
          }
344
          if (search_player) {
345
            Print(4095,
346
                "\n              Searching only the move played in game.");
347
            Print(4095, "--------------------\n");
348
            tree->status[1] = tree->status[0];
349
            search_move = move;
350
            root_moves[0].move = move;
351
            root_moves[0].status = 0;
352
            n_root_moves = 1;
353
            search_time_limit = 3 * annotate_search_time_limit;
354
            search_depth = temp[0].pathd;
355
            if (search_depth == temp_search_depth)
356
              search_time_limit = annotate_search_time_limit;
108 pmbaty 357
            InitializeHashTables(0);
33 pmbaty 358
            player_score = Iterate(wtm, annotate, 1);
359
            player_pv = tree->pv[0];
360
            search_depth = temp_search_depth;
361
            search_time_limit = annotate_search_time_limit;
362
            search_move = 0;
363
          }
364
/*
365
 ************************************************************
366
 *                                                          *
367
 *  Output the score/pv for the move played unless it       *
368
 *  matches what Crafty would have played.  If it doesn't   *
369
 *  then output the pv for what Crafty thinks is best.      *
370
 *                                                          *
371
 ************************************************************
372
 */
373
          thinking = 0;
374
          if (player_pv.pathd > 1 && player_pv.pathl >= 1 &&
375
              player_score + annotate_margin < annotate_score[0]
376
              && (temp[0].path[1] != player_pv.path[1]
377
                  || annotate_margin < 0 || best_moves != 1)) {
378
            if (wtm) {
379
              analysis_printed = 1;
380
              fprintf(annotate_out, "%s\n", html_br);
381
            }
382
            if (html_mode == 1)
383
              AnnotatePositionHTML(tree, wtm, annotate_out);
384
            if (latex == 1) {
385
              AnnotatePositionTeX(tree, wtm, annotate_out);
386
              fprintf(annotate_out, "   \\begin{variation}\\{%d:%s\\}",
387
                  player_pv.pathd, DisplayEvaluationKibitz(player_score,
388
                      wtm));
389
            } else
390
              fprintf(annotate_out, "                ({%d:%s}",
391
                  player_pv.pathd, DisplayEvaluationKibitz(player_score,
392
                      wtm));
393
            path_len = player_pv.pathl;
394
            fprintf(annotate_out, " %s", FormatPV(tree, wtm, player_pv));
395
            if (latex == 1)
396
              fprintf(annotate_out, " %s\n   \\end{variation}\n",
397
                  AnnotateVtoNAG(player_score, wtm, html_mode, latex));
398
            else
399
              fprintf(annotate_out, " %s)%s\n", AnnotateVtoNAG(player_score,
400
                      wtm, html_mode, latex), html_br);
401
            for (move_num = 0; move_num < searches_done; move_num++) {
402
              if (move != temp[move_num].path[1]) {
403
                if (latex == 1)
404
                  fprintf(annotate_out, "   \\begin{variation}\\{%d:%s\\}",
405
                      temp[move_num].pathd,
406
                      DisplayEvaluationKibitz(annotate_score[move_num], wtm));
407
                else
408
                  fprintf(annotate_out, "                ({%d:%s}",
409
                      temp[move_num].pathd,
410
                      DisplayEvaluationKibitz(annotate_score[move_num], wtm));
411
                path_len = temp[move_num].pathl;
412
                fprintf(annotate_out, " %s", FormatPV(tree, wtm,
413
                        temp[move_num]));
414
                if (latex == 1)
415
                  fprintf(annotate_out, " %s\n   \\end{variation}\n",
416
                      AnnotateVtoNAG(annotate_score[move_num], wtm, html_mode,
417
                          latex));
418
                else
419
                  fprintf(annotate_out, " %s)%s\n",
420
                      AnnotateVtoNAG(annotate_score[move_num], wtm, html_mode,
421
                          latex), html_br);
422
              }
423
            }
424
            if (html_mode == 1)
425
              fprintf(annotate_out, "<br>\n");
426
            if (line2 < 0)
427
              line2--;
428
          }
429
        }
430
      }
431
/*
432
 ************************************************************
433
 *                                                          *
434
 *  Before going on to the next move, see if the user has   *
435
 *  included a set of other moves that require a search.    *
436
 *  If so, search them one at a time and produce the ana-   *
437
 *  lysis for each one.                                     *
438
 *                                                          *
439
 ************************************************************
440
 */
441
      read_status = ReadPGN(annotate_in, 1);
442
      while (read_status == 2) {
108 pmbaty 443
        suggested = InputMove(tree, 0, wtm, 1, 0, buffer);
33 pmbaty 444
        if (suggested > 0) {
445
          thinking = 1;
446
          Print(4095, "\n              Searching only the move suggested.");
447
          Print(4095, "--------------------\n");
448
          tree->status[1] = tree->status[0];
449
          search_move = suggested;
450
          search_time_limit = 3 * annotate_search_time_limit;
451
          search_depth = temp[0].pathd;
108 pmbaty 452
          InitializeHashTables(0);
33 pmbaty 453
          annotate_score[0] = Iterate(wtm, annotate, 0);
454
          search_depth = temp_search_depth;
455
          search_time_limit = annotate_search_time_limit;
456
          search_move = 0;
457
          thinking = 0;
458
          twtm = wtm;
459
          path_len = tree->pv[0].pathl;
460
          if (tree->pv[0].pathd > 1 && path_len >= 1) {
461
            if (wtm && !analysis_printed) {
462
              analysis_printed = 1;
463
              fprintf(annotate_out, "%s\n", html_br);
464
            }
465
            fprintf(annotate_out, "                ({suggested %d:%s}",
466
                tree->pv[0].pathd, DisplayEvaluationKibitz(annotate_score[0],
467
                    wtm));
468
            for (i = 1; i <= path_len; i++) {
108 pmbaty 469
              fprintf(annotate_out, " %s", OutputMove(tree, i, twtm,
470
                      tree->pv[0].path[i]));
471
              MakeMove(tree, i, twtm, tree->pv[0].path[i]);
33 pmbaty 472
              twtm = Flip(twtm);
473
            }
474
            for (i = path_len; i > 0; i--) {
475
              twtm = Flip(twtm);
108 pmbaty 476
              UnmakeMove(tree, i, twtm, tree->pv[0].path[i]);
33 pmbaty 477
            }
478
            fprintf(annotate_out, " %s)%s\n",
479
                AnnotateVtoNAG(annotate_score[0], wtm, html_mode, latex),
480
                html_br);
481
          }
482
        }
483
        read_status = ReadPGN(annotate_in, 1);
484
        if (read_status != 2)
485
          break;
486
      }
487
      if ((analysis_printed) && (latex == 0))
488
        fprintf(annotate_out, "%s\n", html_br);
108 pmbaty 489
      MakeMoveRoot(tree, wtm, move);
33 pmbaty 490
      wtm = Flip(wtm);
491
      if (wtm)
492
        move_number++;
493
      if (read_status != 0)
494
        break;
495
      if (line2 < -1)
496
        break;
154 pmbaty 497
    }
108 pmbaty 498
    fprintf(annotate_out, "  %s %s\n\n", pgn_result, html_br);
33 pmbaty 499
    if (html_mode == 1) {
500
      fprintf(annotate_out, "%s\n", html_br);
501
      AnnotateFooterHTML(annotate_out);
502
    }
503
    if (latex == 1) {
504
      AnnotatePositionTeX(tree, wtm, annotate_out);
505
      fprintf(annotate_out, "\\end{mainline}\n");
506
      if (strlen(colors) != 0) {
507
        fprintf(annotate_out, "\\begin{flushright}{\\small ");
508
        if (!strcmp(colors, "bw") || !strcmp(colors, "wb"))
509
          fprintf(annotate_out, "annotating both black and white moves.%s\n",
510
              html_br);
511
        else if (strchr(colors, 'b'))
512
          fprintf(annotate_out, "annotating only black moves.%s\n", html_br);
513
        else if (strchr(colors, 'w'))
514
          fprintf(annotate_out, "annotating only white moves.%s\n", html_br);
515
      } else
516
        fprintf(annotate_out, "annotating for player %s%s\n", pname, html_br);
517
      fprintf(annotate_out, "using a scoring margin of %s pawns.%s\n",
518
          DisplayEvaluationKibitz(annotate_margin, wtm), html_br);
519
      fprintf(annotate_out, "search time limit is %s%s\n",
520
          DisplayTimeKibitz(annotate_search_time_limit), html_br);
521
      fprintf(annotate_out, " } \\end{flushright}");
522
      AnnotateFooterTeX(annotate_out);
523
    }
524
  }
525
  if (annotate_out)
526
    fclose(annotate_out);
527
  if (annotate_in)
528
    fclose(annotate_in);
529
  search_time_limit = 0;
530
  annotate_mode = 0;
531
  swindle_mode = save_swindle_mode;
532
}
533
 
534
/*
535
 *******************************************************************************
536
 *                                                                             *
537
 *   These functions provide HTML output support interfaces.                   *
538
 *                                                                             *
539
 *******************************************************************************
540
 */
541
void AnnotateHeaderHTML(char *title_text, FILE * annotate_out) {
542
  fprintf(annotate_out,
543
      "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
544
  fprintf(annotate_out,
545
      "          \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
546
  fprintf(annotate_out, "<HTML>\n");
547
  fprintf(annotate_out, "<HEAD><TITLE>%s</TITLE>\n", title_text);
548
  fprintf(annotate_out,
549
      "<LINK rev=\"made\" href=\"hyatt@cis.uab.edu\"></HEAD>\n");
550
  fprintf(annotate_out,
551
      "<BODY BGColor=\"#ffffff\" text=\"#000000\" link=\"#0000ee\""
552
      " vlink=\"#551a8b\">\n");
553
}
554
 
555
void AnnotateFooterHTML(FILE * annotate_out) {
556
  fprintf(annotate_out, "</BODY>\n");
557
  fprintf(annotate_out, "</HTML>\n");
558
}
559
void AnnotatePositionHTML(TREE * RESTRICT tree, int wtm, FILE * annotate_out) {
560
  char filename[32], html_piece;
561
  char alt[32];
562
  int rank, file;
563
 
564
/*  Display the board in HTML using table of images.          */
565
  fprintf(annotate_out, "<br>\n");
566
  fprintf(annotate_out, "<TABLE Border=1 CellSpacing=0 CellPadding=0>\n\n");
567
  for (rank = RANK8; rank >= RANK1; rank--) {
568
    fprintf(annotate_out, "<TR>\n");
569
    for (file = FILEA; file <= FILEH; file++) {
108 pmbaty 570
      strcpy(filename, "bitmaps/");
33 pmbaty 571
      if ((rank + file) % 2)
108 pmbaty 572
        strcat(filename, "w");
33 pmbaty 573
      else
108 pmbaty 574
        strcat(filename, "b");
33 pmbaty 575
      html_piece = translate[PcOnSq((rank << 3) + file) + 6];
576
      switch (html_piece) {
577
        case 'p':
108 pmbaty 578
          strcat(filename, "bp");
579
          strcpy(alt, "*P");
33 pmbaty 580
          break;
581
        case 'r':
108 pmbaty 582
          strcat(filename, "br");
583
          strcpy(alt, "*R");
33 pmbaty 584
          break;
585
        case 'n':
108 pmbaty 586
          strcat(filename, "bn");
587
          strcpy(alt, "*N");
33 pmbaty 588
          break;
589
        case 'b':
108 pmbaty 590
          strcat(filename, "bb");
591
          strcpy(alt, "*B");
33 pmbaty 592
          break;
593
        case 'q':
108 pmbaty 594
          strcat(filename, "bq");
595
          strcpy(alt, "*Q");
33 pmbaty 596
          break;
597
        case 'k':
108 pmbaty 598
          strcat(filename, "bk");
599
          strcpy(alt, "*K");
33 pmbaty 600
          break;
601
        case 'P':
108 pmbaty 602
          strcat(filename, "wp");
603
          strcpy(alt, "P");
33 pmbaty 604
          break;
605
        case 'R':
108 pmbaty 606
          strcat(filename, "wr");
607
          strcpy(alt, "R");
33 pmbaty 608
          break;
609
        case 'N':
108 pmbaty 610
          strcat(filename, "wn");
611
          strcpy(alt, "N");
33 pmbaty 612
          break;
613
        case 'B':
108 pmbaty 614
          strcat(filename, "wb");
615
          strcpy(alt, "B");
33 pmbaty 616
          break;
617
        case 'Q':
108 pmbaty 618
          strcat(filename, "wq");
619
          strcpy(alt, "Q");
33 pmbaty 620
          break;
621
        case 'K':
108 pmbaty 622
          strcat(filename, "wk");
623
          strcpy(alt, "K");
33 pmbaty 624
          break;
625
        default:
108 pmbaty 626
          strcat(filename, "sq");
627
          strcpy(alt, " ");
33 pmbaty 628
          break;
629
      }
108 pmbaty 630
      strcat(filename, ".gif");
33 pmbaty 631
      fprintf(annotate_out, "<TD><IMG ALT=\"%s\" SRC=\"%s\"></TD>\n", alt,
632
          filename);
633
    }
634
    fprintf(annotate_out, "</TR>\n\n");
635
  }
636
  fprintf(annotate_out, "</TABLE>\n");
637
  if (wtm)
638
    fprintf(annotate_out, "<H2>White to move.</H2>\n");
639
  else
640
    fprintf(annotate_out, "<H2>Black to move.</H2>\n");
641
  fprintf(annotate_out, "<BR>\n");
642
}
643
 
644
/*
645
 *******************************************************************************
646
 * Author         : Alexander Wagner                                           *
108 pmbaty 647
 *                  University of Michigan                                     *
33 pmbaty 648
 * Date           : 03.01.04                                                   *
649
 *                                                                             *
650
 * Last Modified  : 03.01.04                                                   *
651
 *                                                                             *
652
 * Based upon the HTML-Code above                                              *
653
 *                                                                             *
654
 * These functions provide LaTeX output capability to Crafty.                  *
655
 *                                                                             *
656
 *******************************************************************************
657
 */
658
void AnnotateHeaderTeX(FILE * annotate_out) {
659
  fprintf(annotate_out, "\\documentclass[12pt,twocolumn]{article}\n");
660
  fprintf(annotate_out, "%% This is a LaTeX file generated by Crafty \n");
661
  fprintf(annotate_out,
662
      "%% You must have the \"chess12\" package to typeset this file.\n");
663
  fprintf(annotate_out, "\n");
664
  fprintf(annotate_out, "\\usepackage{times}\n");
665
  fprintf(annotate_out, "\\usepackage{a4wide}\n");
666
  fprintf(annotate_out, "\\usepackage{chess}\n");
667
  fprintf(annotate_out, "\\usepackage{bdfchess}\n");
668
  fprintf(annotate_out, "\\usepackage[T1]{fontenc}\n");
669
  fprintf(annotate_out, "\n");
670
  fprintf(annotate_out, "\\setlength{\\columnsep}{7mm}\n");
671
  fprintf(annotate_out, "\\setlength{\\parindent}{0pt}\n");
672
  fprintf(annotate_out, "\n");
673
  fprintf(annotate_out, "%% Macros for variations and diagrams:\n");
674
  fprintf(annotate_out,
675
      "\\newenvironment{mainline}[2]{\\bf\\newcommand{\\result}{#1}%%\n");
676
  fprintf(annotate_out, "\\newcommand{\\commentator}{#2}\\begin{chess}}%%\n");
677
  fprintf(annotate_out, "{\\end{chess}\\finito{\\result}{\\commentator}}\n");
678
  fprintf(annotate_out,
679
      "\\newenvironment{variation}{[\\begingroup\\rm\\ignorespaces}%%\n");
680
  fprintf(annotate_out, "{\\endgroup]\\ignorespaces\\newline}\n");
681
  fprintf(annotate_out,
682
      "\\newcommand{\\finito}[2]{{\\bf\\hfill#1\\hfill[#2]\\par}}\n");
683
  fprintf(annotate_out, "\\setlength{\\parindent}{0pt}\n");
684
  fprintf(annotate_out,
685
      "\\newenvironment{diagram}{\\begin{nochess}}"
686
      "{$$\\showboard$$\\end{nochess}}\n");
687
  fprintf(annotate_out, "\n\n\\begin{document}\n\n");
688
}
689
 
690
void AnnotateFooterTeX(FILE * annotate_out) {
691
  fprintf(annotate_out, "\n\n\\end{document}\n");
692
}
693
void AnnotatePositionTeX(TREE * tree, int wtm, FILE * annotate_out) {
694
  char filename[32], html_piece;
695
  int rank, file;
696
 
697
/*  Display the board in LaTeX using picture notation, similar to html */
698
  fprintf(annotate_out, "\\begin{diagram}\n\\board\n");
699
  for (rank = RANK8; rank >= RANK1; rank--) {
700
    fprintf(annotate_out, "   {");
701
    for (file = FILEA; file <= FILEH; file++) {
702
      if ((rank + file) % 2)
108 pmbaty 703
        strcpy(filename, " ");
33 pmbaty 704
      else
108 pmbaty 705
        strcpy(filename, "*");
33 pmbaty 706
      html_piece = translate[PcOnSq((rank << 3) + file) + 6];
707
      switch (html_piece) {
708
        case 'p':
709
          strcpy(filename, "p");
710
          break;
711
        case 'r':
712
          strcpy(filename, "r");
713
          break;
714
        case 'n':
715
          strcpy(filename, "n");
716
          break;
717
        case 'b':
718
          strcpy(filename, "b");
719
          break;
720
        case 'q':
721
          strcpy(filename, "q");
722
          break;
723
        case 'k':
724
          strcpy(filename, "k");
725
          break;
726
        case 'P':
727
          strcpy(filename, "P");
728
          break;
729
        case 'R':
730
          strcpy(filename, "R");
731
          break;
732
        case 'N':
733
          strcpy(filename, "N");
734
          break;
735
        case 'B':
736
          strcpy(filename, "B");
737
          break;
738
        case 'Q':
739
          strcpy(filename, "Q");
740
          break;
741
        case 'K':
742
          strcpy(filename, "K");
743
          break;
744
        default:
745
          break;
746
      }
747
      fprintf(annotate_out, "%s", filename);
748
    }
749
    fprintf(annotate_out, "}\n");
750
  }
751
  fprintf(annotate_out, "\\end{diagram}\n");
752
  fprintf(annotate_out, "\\begin{center} \\begin{nochess}\n  {\\small ");
753
  if (wtm)
754
    fprintf(annotate_out, "White to move.\n");
755
  else
756
    fprintf(annotate_out, "Black to move.\n");
757
  fprintf(annotate_out, "}\n \\end{nochess}\\end{center} \n\n");
758
  fprintf(annotate_out, "\n");
759
}
760
char *AnnotateVtoNAG(int value, int wtm, int html_mode, int latex) {
761
  static char buf[64];
762
 
763
  if (!wtm)
764
    value = -value;
765
  if (value > MIN_DECISIVE_ADV)
766
    strcpy(buf, html_mode ? "+-" : "$18");
767
  else if (value > MIN_MODERATE_ADV)
768
    strcpy(buf, html_mode ? "+/-" : "$16");
769
  else if (value > MIN_SLIGHT_ADV)
770
    strcpy(buf, html_mode ? "+=" : "$14");
771
  else if (value < -MIN_DECISIVE_ADV)
772
    strcpy(buf, html_mode ? "-+" : "$19");
773
  else if (value < -MIN_MODERATE_ADV)
774
    strcpy(buf, html_mode ? "-/+" : "$17");
775
  else if (value < -MIN_SLIGHT_ADV)
776
    strcpy(buf, html_mode ? "=+" : "$15");
777
  else
778
    strcpy(buf, html_mode ? "=" : "$10");
779
  if (latex == 1) {
780
    if (value > MIN_DECISIVE_ADV)
781
      strcpy(buf, "\\wdecisive");
782
    else if (value > MIN_MODERATE_ADV)
783
      strcpy(buf, "\\wupperhand");
784
    else if (value > MIN_SLIGHT_ADV)
785
      strcpy(buf, "\\wbetter");
786
    else if (value < -MIN_DECISIVE_ADV)
787
      strcpy(buf, "\\bdecisive");
788
    else if (value < -MIN_MODERATE_ADV)
789
      strcpy(buf, "\\bupperhand");
790
    else if (value < -MIN_SLIGHT_ADV)
791
      strcpy(buf, "\\bbetter");
792
    else
793
      strcpy(buf, "\\equal");
794
  }
795
  return buf;
796
}