💾 Archived View for runjimmyrunrunyoufuckerrun.com › src › games › chessengines › crafty › annotate.… captured on 2021-12-17 at 13:26:06.
-=-=-=-=-=-=-
#include "chess.h" #include "data.h" /* last modified 02/26/14 */ /* ******************************************************************************* * * * "annotate" command is used to search through the game in a pgn file, and * * provide a qualitative analysis of each move played and then creating a * * new output file (xxx.can) containing the original game + new commentary. * * * * The normal output of this command is a file, in PGN format, that contains * * the moves of the game, along with analysis when Crafty does not think * * that move was the best choice. The definition of "best choice" is * * somewhat vague, because if the move played is "close" to the best move * * available, Crafty will not comment on the move. "Close" is defined by * * the <margin> option explained below. This basic type of annotation works * * by first using the normal tree search algorithm to find the best move. * * If this move was the move played, no output is produced. If a different * * move is considered best, then the actual move played is searched to the * * same depth and if the best move and actual move scores are within * * <margin> of each other, no comment is produced, otherwise Crafty inserts * * the evaluation for the move played, followed by the eval and PV for the * * best continuation it found. You can enter suggested moves for Crafty to * * analyze at any point by simply entering a move as an analysis-type * * comment using (move) or {move}. Crafty will search that move in addition * * to the move actually played and the move it thinks is best. * * * * The format of the command is as follows: * * * * annotate filename b|w|bw|name moves margin time [n] * * * * Filename is the input file where Crafty will obtain the moves to * * annotate, and output will be written to file "filename.can". * * * * annotateh filename b|w|bw|name moves margin time [n] * * * * Can be used to produce an HTML-compatible file that includes bitmapped * * diagrams of the positions where Crafty provides analysis. This file can * * be opened by a browser to provide much easier 'reading'. * * * * annotatet filename b|w|bw|name moves margin time [n] * * * * Can be used to produce a LaTeX-compatible file that includes LaTeX chess * * fonts. This file can be read/printed by any program that can handle * * LaTeX input. * * * * Where b/w/bw indicates whether to annotate only the white side (w), the * * black side (b) or both (bw). You can also specify a name (or part of a * * name, just be sure it is unique in the name tags for clarity in who you * * mean). * * * * Moves indicates the move or moves to annotate. It can be a single move, * * which indicates the starting move number to annotate, or it can be a * * range, which indicates a range of move (1-999 gets the whole game.) * * * * Margin is the difference between Crafty's evaluation for the move * * actually played and for the move Crafty thinks is best, before Crafty * * will generate a comment in the annotation file. 1.0 is a pawn, and will * * only generate comments if the move played is 1.000 (1 pawn) worse than * * the best move found by doing a complete search. * * * * Time is time per move to search, in seconds. * * * * [n] is optional and tells Crafty to produce the PV/score for the "n" best * * moves. Crafty stops when the best move reaches the move played in the * * game or after displaying n moves, whichever comes first. If you use -n, * * then it will display n moves regardless of where the game move ranks. * * * ******************************************************************************* */ #define MIN_DECISIVE_ADV 150 #define MIN_MODERATE_ADV 70 #define MIN_SLIGHT_ADV 30 void Annotate() { FILE *annotate_in, *annotate_out; char text[128], tbuffer[4096], colors[32] = { "" }, pname[128] = { ""}; int annotate_margin, annotate_score[100], player_score, best_moves, annotate_wtm; int annotate_search_time_limit, search_player; int twtm, path_len, analysis_printed = 0; int wtm, move_num, line1, line2, move, suggested, i; int searches_done, read_status; PATH temp[100], player_pv; int temp_search_depth; TREE *const tree = block[0]; char html_br[5] = { "" }; int save_swindle_mode; int html_mode = 0; int latex = 0; /* ************************************************************ * * * First, extract the options from the command line to * * determine what the user wanted us to do. * * * ************************************************************ */ save_swindle_mode = swindle_mode; if (!strcmp(args[0], "annotateh")) { html_mode = 1; strcpy(html_br, "<br>"); } if (!strcmp(args[0], "annotatet")) { latex = 1; strcpy(html_br, "\\\\"); } strcpy(tbuffer, buffer); nargs = ReadParse(tbuffer, args, " \t;"); if (nargs < 6) { printf ("usage: annotate <file> <color> <moves> <margin> <time> [nmoves]\n"); return; } annotate_in = fopen(args[1], "r"); if (annotate_in == NULL) { Print(4095, "unable to open %s for input\n", args[1]); return; } nargs = ReadParse(tbuffer, args, " \t;"); strcpy(text, args[1]); if (html_mode == 1) strcpy(text + strlen(text), ".html"); else if (latex == 1) strcpy(text + strlen(text), ".tex"); else strcpy(text + strlen(text), ".can"); annotate_out = fopen(text, "w"); if (annotate_out == NULL) { Print(4095, "unable to open %s for output\n", text); return; } if (html_mode == 1) AnnotateHeaderHTML(text, annotate_out); if (latex == 1) AnnotateHeaderTeX(annotate_out); if (strlen(args[2]) <= 2) strcpy(colors, args[2]); else strcpy(pname, args[2]); line1 = 1; line2 = 999; if (strchr(args[3], 'b')) line2 = -1; if (strchr(args[3], '-')) sscanf(args[3], "%d-%d", &line1, &line2); else { sscanf(args[3], "%d", &line1); line2 = 999; } annotate_margin = atof(args[4]) * PieceValues(white, pawn); annotate_search_time_limit = atof(args[5]) * 100; if (nargs > 6) best_moves = atoi(args[6]); else best_moves = 1; /* ************************************************************ * * * Reset the game to "square 0" to start the annotation * * procedure. Then we read moves from the input file, * * make them on the game board, and annotate if the move * * is for the correct side. If we haven't yet reached the * * starting move to annotate, we skip the Search() stuff * * and read another move. * * * ************************************************************ */ annotate_mode = 1; swindle_mode = 0; ponder = 0; temp_search_depth = search_depth; read_status = ReadPGN(0, 0); read_status = ReadPGN(annotate_in, 0); player_pv.path[1] = 0; while (read_status != -1) { ponder_move = 0; last_pv.pathd = 0; last_pv.pathl = 0; player_pv.pathd = 0; player_pv.pathl = 0; tree->pv[0].pathl = 0; tree->pv[0].pathd = 0; analysis_printed = 0; InitializeChessBoard(tree); tree->status[1] = tree->status[0]; wtm = 1; move_number = 1; /* ************************************************************ * * * Now grab the PGN tag values so they can be copied to * * the .can file for reference. * * * ************************************************************ */ do read_status = ReadPGN(annotate_in, 0); while (read_status == 1); if (read_status == -1) break; if (latex == 0) { fprintf(annotate_out, "[Event \"%s\"]%s\n", pgn_event, html_br); fprintf(annotate_out, "[Site \"%s\"]%s\n", pgn_site, html_br); fprintf(annotate_out, "[Date \"%s\"]%s\n", pgn_date, html_br); fprintf(annotate_out, "[Round \"%s\"]%s\n", pgn_round, html_br); fprintf(annotate_out, "[White \"%s\"]%s\n", pgn_white, html_br); fprintf(annotate_out, "[WhiteElo \"%s\"]%s\n", pgn_white_elo, html_br); fprintf(annotate_out, "[Black \"%s\"]%s\n", pgn_black, html_br); fprintf(annotate_out, "[BlackElo \"%s\"]%s\n", pgn_black_elo, html_br); fprintf(annotate_out, "[Result \"%s\"]%s\n", pgn_result, html_br); fprintf(annotate_out, "[Annotator \"Crafty v%s\"]%s\n", version, html_br); if (strlen(colors) != 0) { if (!strcmp(colors, "bw") || !strcmp(colors, "wb")) fprintf(annotate_out, "{annotating both black and white moves.}%s\n", html_br); else if (strchr(colors, 'b')) fprintf(annotate_out, "{annotating only black moves.}%s\n", html_br); else if (strchr(colors, 'w')) fprintf(annotate_out, "{annotating only white moves.}%s\n", html_br); } else fprintf(annotate_out, "{annotating for player %s}%s\n", pname, html_br); fprintf(annotate_out, "{using a scoring margin of %s pawns.}%s\n", DisplayEvaluationKibitz(annotate_margin, wtm), html_br); fprintf(annotate_out, "{search time limit is %s}%s\n%s\n", DisplayTimeKibitz(annotate_search_time_limit), html_br, html_br); } else { fprintf(annotate_out, "\\textbf{\\sc %s %s -- %s %s}%s\n", pgn_white, pgn_white_elo, pgn_black, pgn_black_elo, html_br); fprintf(annotate_out, "{\\em %s, %s}%s\n", pgn_site, pgn_date, html_br); fprintf(annotate_out, "{\\small %s, Round: %s}%s\n", pgn_event, pgn_round, html_br); fprintf(annotate_out, "\\begin{mainline}{%s}{Crafty v%s}\n", pgn_result, version); } if (strlen(colors)) { if (!strcmp(colors, "w")) annotate_wtm = 1; else if (!strcmp(colors, "b")) annotate_wtm = 0; else if (!strcmp(colors, "wb")) annotate_wtm = 2; else if (!strcmp(colors, "bw")) annotate_wtm = 2; else { Print(4095, "invalid color specification, retry\n"); fclose(annotate_out); return; } } else { if (strstr(pgn_white, pname)) annotate_wtm = 1; else if (strstr(pgn_black, pname)) annotate_wtm = 0; else { Print(4095, "Player name doesn't match any PGN name tag, retry\n"); fclose(annotate_out); return; } } do { fflush(annotate_out); move = ReadNextMove(tree, buffer, 0, wtm); if (move <= 0) break; strcpy(text, OutputMove(tree, 0, wtm, move)); if (history_file) { fseek(history_file, ((move_number - 1) * 2 + 1 - wtm) * 10, SEEK_SET); fprintf(history_file, "%9s\n", text); } if (wtm) Print(4095, "White(%d): %s\n", move_number, text); else Print(4095, "Black(%d): %s\n", move_number, text); if (analysis_printed) fprintf(annotate_out, "%3d.%s%8s\n", move_number, (wtm ? "" : " ..."), text); else { if (wtm) fprintf(annotate_out, "%3d.%8s", move_number, text); else fprintf(annotate_out, "%8s\n", text); } analysis_printed = 0; if (move_number >= line1 && move_number <= line2) { if (annotate_wtm == 2 || annotate_wtm == wtm) { last_pv.pathd = 0; last_pv.pathl = 0; thinking = 1; RootMoveList(wtm); /* ************************************************************ * * * Search the position to see if the move played is the * * best move possible. If not, then search just the move * * played to get a score for it as well, so we can * * determine if annotated output is appropriate. * * * ************************************************************ */ search_time_limit = annotate_search_time_limit; search_depth = temp_search_depth; player_score = -999999; search_player = 1; for (searches_done = 0; searches_done < Abs(best_moves); searches_done++) { if (searches_done > 0) { search_time_limit = 3 * annotate_search_time_limit; search_depth = temp[0].pathd; } Print(4095, "\n Searching all legal moves."); Print(4095, "----------------------------------\n"); tree->status[1] = tree->status[0]; InitializeHashTables(0); annotate_score[searches_done] = Iterate(wtm, annotate, 1); if (tree->pv[0].path[1] == move) { player_score = annotate_score[searches_done]; player_pv = tree->pv[0]; search_player = 0; } temp[searches_done] = tree->pv[0]; for (i = 0; i < n_root_moves; i++) { if (root_moves[i].move == tree->pv[0].path[1]) { for (; i < n_root_moves; i++) root_moves[i] = root_moves[i + 1]; n_root_moves--; break; } } if (n_root_moves == 0 || (annotate_margin >= 0 && player_score + annotate_margin > annotate_score[searches_done] && best_moves > 0)) { if (n_root_moves == 0) searches_done++; break; } } if (search_player) { Print(4095, "\n Searching only the move played in game."); Print(4095, "--------------------\n"); tree->status[1] = tree->status[0]; search_move = move; root_moves[0].move = move; root_moves[0].status = 0; n_root_moves = 1; search_time_limit = 3 * annotate_search_time_limit; search_depth = temp[0].pathd; if (search_depth == temp_search_depth) search_time_limit = annotate_search_time_limit; InitializeHashTables(0); player_score = Iterate(wtm, annotate, 1); player_pv = tree->pv[0]; search_depth = temp_search_depth; search_time_limit = annotate_search_time_limit; search_move = 0; } /* ************************************************************ * * * Output the score/pv for the move played unless it * * matches what Crafty would have played. If it doesn't * * then output the pv for what Crafty thinks is best. * * * ************************************************************ */ thinking = 0; if (player_pv.pathd > 1 && player_pv.pathl >= 1 && player_score + annotate_margin < annotate_score[0] && (temp[0].path[1] != player_pv.path[1] || annotate_margin < 0 || best_moves != 1)) { if (wtm) { analysis_printed = 1; fprintf(annotate_out, "%s\n", html_br); } if (html_mode == 1) AnnotatePositionHTML(tree, wtm, annotate_out); if (latex == 1) { AnnotatePositionTeX(tree, wtm, annotate_out); fprintf(annotate_out, " \\begin{variation}\\{%d:%s\\}", player_pv.pathd, DisplayEvaluationKibitz(player_score, wtm)); } else fprintf(annotate_out, " ({%d:%s}", player_pv.pathd, DisplayEvaluationKibitz(player_score, wtm)); path_len = player_pv.pathl; fprintf(annotate_out, " %s", FormatPV(tree, wtm, player_pv)); if (latex == 1) fprintf(annotate_out, " %s\n \\end{variation}\n", AnnotateVtoNAG(player_score, wtm, html_mode, latex)); else fprintf(annotate_out, " %s)%s\n", AnnotateVtoNAG(player_score, wtm, html_mode, latex), html_br); for (move_num = 0; move_num < searches_done; move_num++) { if (move != temp[move_num].path[1]) { if (latex == 1) fprintf(annotate_out, " \\begin{variation}\\{%d:%s\\}", temp[move_num].pathd, DisplayEvaluationKibitz(annotate_score[move_num], wtm)); else fprintf(annotate_out, " ({%d:%s}", temp[move_num].pathd, DisplayEvaluationKibitz(annotate_score[move_num], wtm)); path_len = temp[move_num].pathl; fprintf(annotate_out, " %s", FormatPV(tree, wtm, temp[move_num])); if (latex == 1) fprintf(annotate_out, " %s\n \\end{variation}\n", AnnotateVtoNAG(annotate_score[move_num], wtm, html_mode, latex)); else fprintf(annotate_out, " %s)%s\n", AnnotateVtoNAG(annotate_score[move_num], wtm, html_mode, latex), html_br); } } if (html_mode == 1) fprintf(annotate_out, "<br>\n"); if (line2 < 0) line2--; } } } /* ************************************************************ * * * Before going on to the next move, see if the user has * * included a set of other moves that require a search. * * If so, search them one at a time and produce the ana- * * lysis for each one. * * * ************************************************************ */ read_status = ReadPGN(annotate_in, 1); while (read_status == 2) { suggested = InputMove(tree, 0, wtm, 1, 0, buffer); if (suggested > 0) { thinking = 1; Print(4095, "\n Searching only the move suggested."); Print(4095, "--------------------\n"); tree->status[1] = tree->status[0]; search_move = suggested; search_time_limit = 3 * annotate_search_time_limit; search_depth = temp[0].pathd; InitializeHashTables(0); annotate_score[0] = Iterate(wtm, annotate, 0); search_depth = temp_search_depth; search_time_limit = annotate_search_time_limit; search_move = 0; thinking = 0; twtm = wtm; path_len = tree->pv[0].pathl; if (tree->pv[0].pathd > 1 && path_len >= 1) { if (wtm && !analysis_printed) { analysis_printed = 1; fprintf(annotate_out, "%s\n", html_br); } fprintf(annotate_out, " ({suggested %d:%s}", tree->pv[0].pathd, DisplayEvaluationKibitz(annotate_score[0], wtm)); for (i = 1; i <= path_len; i++) { fprintf(annotate_out, " %s", OutputMove(tree, i, twtm, tree->pv[0].path[i])); MakeMove(tree, i, twtm, tree->pv[0].path[i]); twtm = Flip(twtm); } for (i = path_len; i > 0; i--) { twtm = Flip(twtm); UnmakeMove(tree, i, twtm, tree->pv[0].path[i]); } fprintf(annotate_out, " %s)%s\n", AnnotateVtoNAG(annotate_score[0], wtm, html_mode, latex), html_br); } } read_status = ReadPGN(annotate_in, 1); if (read_status != 2) break; } if ((analysis_printed) && (latex == 0)) fprintf(annotate_out, "%s\n", html_br); MakeMoveRoot(tree, wtm, move); wtm = Flip(wtm); if (wtm) move_number++; if (read_status != 0) break; if (line2 < -1) break; } while (1); fprintf(annotate_out, " %s %s\n\n", pgn_result, html_br); if (html_mode == 1) { fprintf(annotate_out, "%s\n", html_br); AnnotateFooterHTML(annotate_out); } if (latex == 1) { AnnotatePositionTeX(tree, wtm, annotate_out); fprintf(annotate_out, "\\end{mainline}\n"); if (strlen(colors) != 0) { fprintf(annotate_out, "\\begin{flushright}{\\small "); if (!strcmp(colors, "bw") || !strcmp(colors, "wb")) fprintf(annotate_out, "annotating both black and white moves.%s\n", html_br); else if (strchr(colors, 'b')) fprintf(annotate_out, "annotating only black moves.%s\n", html_br); else if (strchr(colors, 'w')) fprintf(annotate_out, "annotating only white moves.%s\n", html_br); } else fprintf(annotate_out, "annotating for player %s%s\n", pname, html_br); fprintf(annotate_out, "using a scoring margin of %s pawns.%s\n", DisplayEvaluationKibitz(annotate_margin, wtm), html_br); fprintf(annotate_out, "search time limit is %s%s\n", DisplayTimeKibitz(annotate_search_time_limit), html_br); fprintf(annotate_out, " } \\end{flushright}"); AnnotateFooterTeX(annotate_out); } } if (annotate_out) fclose(annotate_out); if (annotate_in) fclose(annotate_in); search_time_limit = 0; annotate_mode = 0; swindle_mode = save_swindle_mode; } /* ******************************************************************************* * * * These functions provide HTML output support interfaces. * * * ******************************************************************************* */ void AnnotateHeaderHTML(char *title_text, FILE * annotate_out) { fprintf(annotate_out, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n"); fprintf(annotate_out, " \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n"); fprintf(annotate_out, "<HTML>\n"); fprintf(annotate_out, "<HEAD><TITLE>%s</TITLE>\n", title_text); fprintf(annotate_out, "<LINK rev=\"made\" href=\"hyatt@cis.uab.edu\"></HEAD>\n"); fprintf(annotate_out, "<BODY BGColor=\"#ffffff\" text=\"#000000\" link=\"#0000ee\"" " vlink=\"#551a8b\">\n"); } void AnnotateFooterHTML(FILE * annotate_out) { fprintf(annotate_out, "</BODY>\n"); fprintf(annotate_out, "</HTML>\n"); } void AnnotatePositionHTML(TREE * RESTRICT tree, int wtm, FILE * annotate_out) { char filename[32], html_piece; char alt[32]; int rank, file; /* Display the board in HTML using table of images. */ fprintf(annotate_out, "<br>\n"); fprintf(annotate_out, "<TABLE Border=1 CellSpacing=0 CellPadding=0>\n\n"); for (rank = RANK8; rank >= RANK1; rank--) { fprintf(annotate_out, "<TR>\n"); for (file = FILEA; file <= FILEH; file++) { strcpy(filename, "bitmaps/"); if ((rank + file) % 2) strcat(filename, "w"); else strcat(filename, "b"); html_piece = translate[PcOnSq((rank << 3) + file) + 6]; switch (html_piece) { case 'p': strcat(filename, "bp"); strcpy(alt, "*P"); break; case 'r': strcat(filename, "br"); strcpy(alt, "*R"); break; case 'n': strcat(filename, "bn"); strcpy(alt, "*N"); break; case 'b': strcat(filename, "bb"); strcpy(alt, "*B"); break; case 'q': strcat(filename, "bq"); strcpy(alt, "*Q"); break; case 'k': strcat(filename, "bk"); strcpy(alt, "*K"); break; case 'P': strcat(filename, "wp"); strcpy(alt, "P"); break; case 'R': strcat(filename, "wr"); strcpy(alt, "R"); break; case 'N': strcat(filename, "wn"); strcpy(alt, "N"); break; case 'B': strcat(filename, "wb"); strcpy(alt, "B"); break; case 'Q': strcat(filename, "wq"); strcpy(alt, "Q"); break; case 'K': strcat(filename, "wk"); strcpy(alt, "K"); break; default: strcat(filename, "sq"); strcpy(alt, " "); break; } strcat(filename, ".gif"); fprintf(annotate_out, "<TD><IMG ALT=\"%s\" SRC=\"%s\"></TD>\n", alt, filename); } fprintf(annotate_out, "</TR>\n\n"); } fprintf(annotate_out, "</TABLE>\n"); if (wtm) fprintf(annotate_out, "<H2>White to move.</H2>\n"); else fprintf(annotate_out, "<H2>Black to move.</H2>\n"); fprintf(annotate_out, "<BR>\n"); } /* ******************************************************************************* * Author : Alexander Wagner * * University of Michigan * * Date : 03.01.04 * * * * Last Modified : 03.01.04 * * * * Based upon the HTML-Code above * * * * These functions provide LaTeX output capability to Crafty. * * * ******************************************************************************* */ void AnnotateHeaderTeX(FILE * annotate_out) { fprintf(annotate_out, "\\documentclass[12pt,twocolumn]{article}\n"); fprintf(annotate_out, "%% This is a LaTeX file generated by Crafty \n"); fprintf(annotate_out, "%% You must have the \"chess12\" package to typeset this file.\n"); fprintf(annotate_out, "\n"); fprintf(annotate_out, "\\usepackage{times}\n"); fprintf(annotate_out, "\\usepackage{a4wide}\n"); fprintf(annotate_out, "\\usepackage{chess}\n"); fprintf(annotate_out, "\\usepackage{bdfchess}\n"); fprintf(annotate_out, "\\usepackage[T1]{fontenc}\n"); fprintf(annotate_out, "\n"); fprintf(annotate_out, "\\setlength{\\columnsep}{7mm}\n"); fprintf(annotate_out, "\\setlength{\\parindent}{0pt}\n"); fprintf(annotate_out, "\n"); fprintf(annotate_out, "%% Macros for variations and diagrams:\n"); fprintf(annotate_out, "\\newenvironment{mainline}[2]{\\bf\\newcommand{\\result}{#1}%%\n"); fprintf(annotate_out, "\\newcommand{\\commentator}{#2}\\begin{chess}}%%\n"); fprintf(annotate_out, "{\\end{chess}\\finito{\\result}{\\commentator}}\n"); fprintf(annotate_out, "\\newenvironment{variation}{[\\begingroup\\rm\\ignorespaces}%%\n"); fprintf(annotate_out, "{\\endgroup]\\ignorespaces\\newline}\n"); fprintf(annotate_out, "\\newcommand{\\finito}[2]{{\\bf\\hfill#1\\hfill[#2]\\par}}\n"); fprintf(annotate_out, "\\setlength{\\parindent}{0pt}\n"); fprintf(annotate_out, "\\newenvironment{diagram}{\\begin{nochess}}" "{$\\showboard$\\end{nochess}}\n"); fprintf(annotate_out, "\n\n\\begin{document}\n\n"); } void AnnotateFooterTeX(FILE * annotate_out) { fprintf(annotate_out, "\n\n\\end{document}\n"); } void AnnotatePositionTeX(TREE * tree, int wtm, FILE * annotate_out) { char filename[32], html_piece; int rank, file; /* Display the board in LaTeX using picture notation, similar to html */ fprintf(annotate_out, "\\begin{diagram}\n\\board\n"); for (rank = RANK8; rank >= RANK1; rank--) { fprintf(annotate_out, " {"); for (file = FILEA; file <= FILEH; file++) { if ((rank + file) % 2) strcpy(filename, " "); else strcpy(filename, "*"); html_piece = translate[PcOnSq((rank << 3) + file) + 6]; switch (html_piece) { case 'p': strcpy(filename, "p"); break; case 'r': strcpy(filename, "r"); break; case 'n': strcpy(filename, "n"); break; case 'b': strcpy(filename, "b"); break; case 'q': strcpy(filename, "q"); break; case 'k': strcpy(filename, "k"); break; case 'P': strcpy(filename, "P"); break; case 'R': strcpy(filename, "R"); break; case 'N': strcpy(filename, "N"); break; case 'B': strcpy(filename, "B"); break; case 'Q': strcpy(filename, "Q"); break; case 'K': strcpy(filename, "K"); break; default: break; } fprintf(annotate_out, "%s", filename); } fprintf(annotate_out, "}\n"); } fprintf(annotate_out, "\\end{diagram}\n"); fprintf(annotate_out, "\\begin{center} \\begin{nochess}\n {\\small "); if (wtm) fprintf(annotate_out, "White to move.\n"); else fprintf(annotate_out, "Black to move.\n"); fprintf(annotate_out, "}\n \\end{nochess}\\end{center} \n\n"); fprintf(annotate_out, "\n"); } char *AnnotateVtoNAG(int value, int wtm, int html_mode, int latex) { static char buf[64]; if (!wtm) value = -value; if (value > MIN_DECISIVE_ADV) strcpy(buf, html_mode ? "+-" : "$18"); else if (value > MIN_MODERATE_ADV) strcpy(buf, html_mode ? "+/-" : "$16"); else if (value > MIN_SLIGHT_ADV) strcpy(buf, html_mode ? "+=" : "$14"); else if (value < -MIN_DECISIVE_ADV) strcpy(buf, html_mode ? "-+" : "$19"); else if (value < -MIN_MODERATE_ADV) strcpy(buf, html_mode ? "-/+" : "$17"); else if (value < -MIN_SLIGHT_ADV) strcpy(buf, html_mode ? "=+" : "$15"); else strcpy(buf, html_mode ? "=" : "$10"); if (latex == 1) { if (value > MIN_DECISIVE_ADV) strcpy(buf, "\\wdecisive"); else if (value > MIN_MODERATE_ADV) strcpy(buf, "\\wupperhand"); else if (value > MIN_SLIGHT_ADV) strcpy(buf, "\\wbetter"); else if (value < -MIN_DECISIVE_ADV) strcpy(buf, "\\bdecisive"); else if (value < -MIN_MODERATE_ADV) strcpy(buf, "\\bupperhand"); else if (value < -MIN_SLIGHT_ADV) strcpy(buf, "\\bbetter"); else strcpy(buf, "\\equal"); } return buf; }