R
Rafael Villarroel Flores
The following script already does what I want it to do, but I would
appreciate if the experts here share any comment they may have that
would help improve my Perl skills
#!/usr/bin/perl
# The purpose of this script is to typeset annotations done by the
# chess program Crafty (ftp://ftp.cis.uab.edu/pub/hyatt/), in LaTeX
# (http://www.latex-project.org/). Crafty already has a command to
# produce LaTeX annotations, but this script gives much prettier
# results!
# It requires the Perl module Chess:GN:arse, the non-standard
# LaTeX packages skak, chess-workshop-symbols, wrapfig, fullpage and
# needspace, which are available at CTAN, crafty and latex (of
# course), and the pgn-extract utility.
# To use it: starting with, say, games.pgn, use Crafty's annotate
# feature to get games.pgn.can. Then you will want to preprocess this
# file using pgn-extract
# (ftp://ftp.cs.ukc.ac.uk/pub/djb/Extract/About.html) in order to add
# an ECO (opening classification code) tag to each game and get the
# file back into standard PGN notation. You get then gamesann.pgn. You
# should then delete all instances of the comments of the like of
# {annotating both black and white moves.} {using a scoring margin of
# +0.20 pawns.} {search time limit is 1.00}, since they confuse the
# Chess:GN:arse module. Say you have now a file gamesann.pgn, you
# are now ready to apply this script, say 'perl skakify.pl
# gamesann.pgn', to obtain gamesann.pgn.tex which you can now process
# with LaTeX
use warnings;
use strict;
use Chess:GN:arse;
my $preamble='\documentclass[twocolumn]{article}
\usepackage[T1]{fontenc}
\usepackage{fullpage,ifthen}
\usepackage{skak,chess-workshop-symbols}
\usepackage{wrapfig,needspace}
\setlength{\columnsep}{7mm}
\setlength{\parindent}{0pt}
\setlength{\intextsep}{0pt}
\makeatletter
\newcommand{\@event}{} \newcommand{\@site}{} \newcommand{\@dategame}{}
\newcommand{\@round}{} \newcommand{\@whiteplayer}{}
\newcommand{\@blackplayer}{} \newcommand{\thisresult}{}
\newcommand{\@eco}{}
\newcommand{\event}[1]{\renewcommand{\@event}{#1}}
\newcommand{\site}[1]{\renewcommand{\@site}{#1}}
\newcommand{\dategame}[1]{\renewcommand{\@dategame}{#1}}
\newcommand{\round}[1]{\renewcommand{\@round}{#1}}
\newcommand{\whiteplayer}[1]{\renewcommand{\@whiteplayer}{#1}}
\newcommand{\blackplayer}[1]{\renewcommand{\@blackplayer}{#1}}
\newcommand{\result}[1]{\renewcommand{\thisresult}{#1}}
\newcommand{\eco}[1]{\renewcommand{\@eco}{#1}}
\setlength{\parindent}{0pt}
\newcounter{gameno}
\setcounter{gameno}{1}
\newcommand{\gameheader}%
{\parbox{\linewidth}{%
\begin{center}
\textbf{\thegameno.}
\end{center}
\begin{flushleft}
$\circ$ \textsc{\@whiteplayer}\par%
$\bullet$ \textsc{\@blackplayer}\par%
\smallskip%
\@event \ifthenelse{\equal{\@round}{}}%
{}{, Round \@round}\hspace{\stretch{1}}\textit{\@eco}\par%
\@site\hspace{\stretch{1}}\@dategame\par
\end{flushleft}
\nopagebreak
}% END PARBOX
\addtocontents{toc}{\thegameno. \@whiteplayer--\@blackplayer\dotfill\thepage\par}
\addtocounter{gameno}{1}
\renewcommand{\@event}{} \renewcommand{\@site}{} \renewcommand{\@dategame}{}
\renewcommand{\@round}{} \renewcommand{\@whiteplayer}{}
\renewcommand{\@blackplayer}{}
}% END GAMEHEADER
% this next macro by Donald Arsenau, see
% <[email protected]>
\def\wrapfill{\par
\ifx\parshape\WF@fudgeparshape
\nobreak
\ifnum\c@WF@wrappedlines>\@ne
\advance\c@WF@wrappedlines\m@ne
\vskip\c@WF@wrappedlines\baselineskip
\global\c@WF@wrappedlines\z@
\fi
\allowbreak
\WF@finale
\fi
}
\makeatother
\begin{document}
\tinyboard
\notationOff
\tableofcontents
';
my $enddoc='\end{document}';
my $pgnfile = shift || die "filename required\n";
my $pgn = new Chess:GN:arse $pgnfile
or die "can't open $pgnfile\n";
my $output = "$pgnfile.tex";
sub printboard
{
print OUT "\n\n\\smallskip\n".
"\\needspace{50pt}\n".
"\\begin{wrapfigure}[8]{r}{78pt}\n".
"\\showboard\n".
"\\end{wrapfigure}\n";
}
# In this subroutine, we want to convert a string like: "({7:+0.42} 10. ... c6 11. O-O-O
# $14) ({0:+0.00} 10. ... dxc4 $10)" into
# \textit{[7:+0.42]} \movecomment{ 10... c6 11. O-O-O }\wbetter
# \textit{[0:+0.00]} \movecomment{ 10... dxc4 }\equalp
sub fix_variation
{
$_=$_[0];
s/\({/{/g;
s/}/}\(/g;
s/{/\\textit{\[/g;
s/}/\]}/g;
s/\[ /\[/g;
s/ \]/\]/g;
s/\(/ \\movecomment{/g;
s/\)/}\n/g;
s/}\n \\textit{/} \n\n \\textit{/g;
s/ }/}/g;
s/\$18}/}\\wdecisive/g;
s/\$16}/}\\wupperhand/g;
s/\$14}/}\\wbetter/g;
s/\$19}/}\\bdecisive/g;
s/\$17}/}\\bupperhand/g;
s/\$15}/}\\bbetter/g;
s/\$10}/}\\equalp/g;
return $_;
}
open(OUT, ">$output");
print OUT "$preamble";
while ($pgn->read_game()){
$pgn->parse_game({save_comments => 'yes'});
my $comments = $pgn->comments;
print OUT "\\event{",$pgn->event,"}\n"; # NOT "\\event{$pgn->event}\n";
print OUT "\\site{",$pgn->site,"}\n";
print OUT "\\dategame{",$pgn->date,"}\n";
print OUT "\\round{",$pgn->round,"}\n";
print OUT "\\whiteplayer{",$pgn->white,"}\n";
print OUT "\\blackplayer{",$pgn->black,"}\n";
print OUT "\\result{",$pgn->result,"}\n\n";
print OUT "\\eco{",$pgn->eco,"}\n\n";
print OUT '\\gameheader
\newgame
\mainline{';
my $total_plys= @{$pgn->moves};
my $ply =0;
while ($ply<$total_plys) {
my $move = int($ply/2)+1;
if (!($ply % 2)) # ply corresponds to a white move
{
print OUT "$move. @{$pgn->moves}[$ply] ";
if ($$comments{"${move}w"})
{
print OUT "}";
&printboard;
print OUT &fix_variation($$comments{"${move}w"});
print OUT "\\wrapfill\n\n";
}
}
else
{
if ($$comments{"${move}w"}) {
print OUT "\\smallskip\n\\mainline{$move... @{$pgn->moves}[$ply] "}
else {
print OUT "@{$pgn->moves}[$ply] "
}
if ($$comments{"${move}b"})
{
print OUT "}";
&printboard;
print OUT &fix_variation($$comments{"${move}b"});
print OUT "\\wrapfill\n";
print OUT "\\smallskip\n\\mainline{"
}
}
++$ply;
}
print OUT "}\\hspace{\\stretch{1}} \\textbf{[\\thisresult]}\n\n";
}
print OUT "\n$enddoc";
close(OUT);
appreciate if the experts here share any comment they may have that
would help improve my Perl skills
#!/usr/bin/perl
# The purpose of this script is to typeset annotations done by the
# chess program Crafty (ftp://ftp.cis.uab.edu/pub/hyatt/), in LaTeX
# (http://www.latex-project.org/). Crafty already has a command to
# produce LaTeX annotations, but this script gives much prettier
# results!
# It requires the Perl module Chess:GN:arse, the non-standard
# LaTeX packages skak, chess-workshop-symbols, wrapfig, fullpage and
# needspace, which are available at CTAN, crafty and latex (of
# course), and the pgn-extract utility.
# To use it: starting with, say, games.pgn, use Crafty's annotate
# feature to get games.pgn.can. Then you will want to preprocess this
# file using pgn-extract
# (ftp://ftp.cs.ukc.ac.uk/pub/djb/Extract/About.html) in order to add
# an ECO (opening classification code) tag to each game and get the
# file back into standard PGN notation. You get then gamesann.pgn. You
# should then delete all instances of the comments of the like of
# {annotating both black and white moves.} {using a scoring margin of
# +0.20 pawns.} {search time limit is 1.00}, since they confuse the
# Chess:GN:arse module. Say you have now a file gamesann.pgn, you
# are now ready to apply this script, say 'perl skakify.pl
# gamesann.pgn', to obtain gamesann.pgn.tex which you can now process
# with LaTeX
use warnings;
use strict;
use Chess:GN:arse;
my $preamble='\documentclass[twocolumn]{article}
\usepackage[T1]{fontenc}
\usepackage{fullpage,ifthen}
\usepackage{skak,chess-workshop-symbols}
\usepackage{wrapfig,needspace}
\setlength{\columnsep}{7mm}
\setlength{\parindent}{0pt}
\setlength{\intextsep}{0pt}
\makeatletter
\newcommand{\@event}{} \newcommand{\@site}{} \newcommand{\@dategame}{}
\newcommand{\@round}{} \newcommand{\@whiteplayer}{}
\newcommand{\@blackplayer}{} \newcommand{\thisresult}{}
\newcommand{\@eco}{}
\newcommand{\event}[1]{\renewcommand{\@event}{#1}}
\newcommand{\site}[1]{\renewcommand{\@site}{#1}}
\newcommand{\dategame}[1]{\renewcommand{\@dategame}{#1}}
\newcommand{\round}[1]{\renewcommand{\@round}{#1}}
\newcommand{\whiteplayer}[1]{\renewcommand{\@whiteplayer}{#1}}
\newcommand{\blackplayer}[1]{\renewcommand{\@blackplayer}{#1}}
\newcommand{\result}[1]{\renewcommand{\thisresult}{#1}}
\newcommand{\eco}[1]{\renewcommand{\@eco}{#1}}
\setlength{\parindent}{0pt}
\newcounter{gameno}
\setcounter{gameno}{1}
\newcommand{\gameheader}%
{\parbox{\linewidth}{%
\begin{center}
\textbf{\thegameno.}
\end{center}
\begin{flushleft}
$\circ$ \textsc{\@whiteplayer}\par%
$\bullet$ \textsc{\@blackplayer}\par%
\smallskip%
\@event \ifthenelse{\equal{\@round}{}}%
{}{, Round \@round}\hspace{\stretch{1}}\textit{\@eco}\par%
\@site\hspace{\stretch{1}}\@dategame\par
\end{flushleft}
\nopagebreak
}% END PARBOX
\addtocontents{toc}{\thegameno. \@whiteplayer--\@blackplayer\dotfill\thepage\par}
\addtocounter{gameno}{1}
\renewcommand{\@event}{} \renewcommand{\@site}{} \renewcommand{\@dategame}{}
\renewcommand{\@round}{} \renewcommand{\@whiteplayer}{}
\renewcommand{\@blackplayer}{}
}% END GAMEHEADER
% this next macro by Donald Arsenau, see
% <[email protected]>
\def\wrapfill{\par
\ifx\parshape\WF@fudgeparshape
\nobreak
\ifnum\c@WF@wrappedlines>\@ne
\advance\c@WF@wrappedlines\m@ne
\vskip\c@WF@wrappedlines\baselineskip
\global\c@WF@wrappedlines\z@
\fi
\allowbreak
\WF@finale
\fi
}
\makeatother
\begin{document}
\tinyboard
\notationOff
\tableofcontents
';
my $enddoc='\end{document}';
my $pgnfile = shift || die "filename required\n";
my $pgn = new Chess:GN:arse $pgnfile
or die "can't open $pgnfile\n";
my $output = "$pgnfile.tex";
sub printboard
{
print OUT "\n\n\\smallskip\n".
"\\needspace{50pt}\n".
"\\begin{wrapfigure}[8]{r}{78pt}\n".
"\\showboard\n".
"\\end{wrapfigure}\n";
}
# In this subroutine, we want to convert a string like: "({7:+0.42} 10. ... c6 11. O-O-O
# $14) ({0:+0.00} 10. ... dxc4 $10)" into
# \textit{[7:+0.42]} \movecomment{ 10... c6 11. O-O-O }\wbetter
# \textit{[0:+0.00]} \movecomment{ 10... dxc4 }\equalp
sub fix_variation
{
$_=$_[0];
s/\({/{/g;
s/}/}\(/g;
s/{/\\textit{\[/g;
s/}/\]}/g;
s/\[ /\[/g;
s/ \]/\]/g;
s/\(/ \\movecomment{/g;
s/\)/}\n/g;
s/}\n \\textit{/} \n\n \\textit{/g;
s/ }/}/g;
s/\$18}/}\\wdecisive/g;
s/\$16}/}\\wupperhand/g;
s/\$14}/}\\wbetter/g;
s/\$19}/}\\bdecisive/g;
s/\$17}/}\\bupperhand/g;
s/\$15}/}\\bbetter/g;
s/\$10}/}\\equalp/g;
return $_;
}
open(OUT, ">$output");
print OUT "$preamble";
while ($pgn->read_game()){
$pgn->parse_game({save_comments => 'yes'});
my $comments = $pgn->comments;
print OUT "\\event{",$pgn->event,"}\n"; # NOT "\\event{$pgn->event}\n";
print OUT "\\site{",$pgn->site,"}\n";
print OUT "\\dategame{",$pgn->date,"}\n";
print OUT "\\round{",$pgn->round,"}\n";
print OUT "\\whiteplayer{",$pgn->white,"}\n";
print OUT "\\blackplayer{",$pgn->black,"}\n";
print OUT "\\result{",$pgn->result,"}\n\n";
print OUT "\\eco{",$pgn->eco,"}\n\n";
print OUT '\\gameheader
\newgame
\mainline{';
my $total_plys= @{$pgn->moves};
my $ply =0;
while ($ply<$total_plys) {
my $move = int($ply/2)+1;
if (!($ply % 2)) # ply corresponds to a white move
{
print OUT "$move. @{$pgn->moves}[$ply] ";
if ($$comments{"${move}w"})
{
print OUT "}";
&printboard;
print OUT &fix_variation($$comments{"${move}w"});
print OUT "\\wrapfill\n\n";
}
}
else
{
if ($$comments{"${move}w"}) {
print OUT "\\smallskip\n\\mainline{$move... @{$pgn->moves}[$ply] "}
else {
print OUT "@{$pgn->moves}[$ply] "
}
if ($$comments{"${move}b"})
{
print OUT "}";
&printboard;
print OUT &fix_variation($$comments{"${move}b"});
print OUT "\\wrapfill\n";
print OUT "\\smallskip\n\\mainline{"
}
}
++$ply;
}
print OUT "}\\hspace{\\stretch{1}} \\textbf{[\\thisresult]}\n\n";
}
print OUT "\n$enddoc";
close(OUT);