\NeedsTeXFormat{LaTeX2e} \ProvidesPackage{skak}[2018/01/08 v1.5.3 Chess typesetting] \DeclareOption{tiny}{\AtEndOfClass{\tinyboard}} \DeclareOption{small}{\AtEndOfClass{\smallboard}} \DeclareOption{normal}{\AtEndOfClass{\normalboard}} \DeclareOption{large}{\AtEndOfClass{\largeboard}} \DeclareOption{notation}{\AtEndOfClass{\notationOn}} \DeclareOption{mover}{\AtEndOfClass{\showmoverOn}} \DeclareOption{moveroff}{\AtEndOfClass{\showmoverOff}} \DeclareOption{notationoff}{\AtEndOfClass{\notationOff}} \DeclareOption{ps}{\def\ps@on{\True}} \DeclareOption{psoff}{\def\ps@on{\False}} \DeclareOption{english}{\AtEndOfClass{\skaklanguage[english]}} \DeclareOption{styleA}{\AtEndOfClass{\styleA}} \DeclareOption{styleB}{\AtEndOfClass{\styleB}} \DeclareOption{styleC}{\AtEndOfClass{\styleC}} \DeclareOption{skaknew}{% \PassOptionsToPackage{skaknew}{chessfss}} \ExecuteOptions{notation,normal,psoff,english,moveroff,styleB} \ProcessOptions \RequirePackage{chessfss} %% changed by UF to stop a clash with \And of amsmath, %% also changed every occurance of \And to %% \LambdaAnd in this sty-file. \let\Ori@nd\And \RequirePackage{lambda,ifthen,calc,textcomp} \let\LambdaAnd\And \let\And\Ori@nd %% end of change \ps@on{\RequirePackage{pstricks,pst-node}\SpecialCoor% \newpsstyle{psskak}{arrowinset=0,nodesep=.25,armA=.75,arrowsize=.2 1, linearc=.2,arrowlength=1.25,linewidth=0.04, doubleline=true,doublesep=.06}}{} % to avoid problems when switching back from styleC \def\normalstyles{% \def\mainlinestyle{\bfseries}% could also contain % definitions of the % various style options \def\variationstyle{}% as with mainlinestyle } \def\styleC@on{\False} % list related functions \def\IsNil#1{#1{\False}{\True}} \def\Member#1#2#3% ('a -> 'a -> bool) -> 'a -> 'a list -> bool {#3{\MemberA{#1}{#2}}{\False}} \def\MemberA#1#2#3#4% {#1{#2}{#3}% {\True}% {\Member{#1}{#2}{#4}}} % Explode: string -> char list \def\Explode#1{\EqStr{Z}{#1}{\Nil}{\ExplodeA#1Z}} \def\ExplodeA#1#2Z{\EqStr{Z}{#2}% {\Singleton{#1}}% {\Cons{#1}{\ExplodeA#2Z}}} \def\BoolToString#1{% bool -> string #1{True}{False}} % the basic manipulation of the board \def\Set#1#2{% square -> piece -> unit \expandafter\xdef\csname#1\endcsname{#2}} \def\Get#1{% square -> piece \csname#1\endcsname} \def\StoreBool#1#2{% \expandafter\def\csname#1\endcsname{#2}} \def\GetBool#1{% \csname#1\endcsname} \def\PieceNames{\Listize[K,Q,R,B,N,p]} \def\FileNames{\Listize[a,b,c,d,e,f,g,h]} \def\RankNames{\Listize[1,2,3,4,5,6,7,8]} \def\showonly#1{\expandafter\def\csname ShowOnlyList\endcsname{\Listize[#1]}} \def\showall{\showonly{K,Q,R,B,N,P,k,q,r,b,n,p}} \showall \def\showonlywhite{\showonly{K,Q,R,B,N,P}} \def\showonlyblack{\showonly{k,q,r,b,n,p}} \def\showonlypawns{\showonly{p,P}} \def\NotMember#1#2{% a list -> a -> bool \Not{\Member{\EqStr}{#2}{#1}}} \def\showallbut#1{% \expandafter\def\csname ShowOnlyList\endcsname{% \Filter{\NotMember{\Listize[#1]}}% {\Listize[K,Q,R,B,N,P,k,q,r,b,n,p]}}} %%% \def\TeXifx#1#2#3% {#1\def\next{#2}\else\def\next{#3}\fi \next} \def\EqStr#1#2{% % has to be changed \TeXif{\if#1#2}} \def\EqPiece#1#2{\TeXif{\if#1#2}} \def\RankOf(#1){\Second{#1}} \def\FileOf(#1){\First{#1}} \def\EqSquare#1#2{% \ifthenelse{\equal{#1}{#2}}{\True}{\False}} %% is this really necessary???? \def\MySecond(#1#2){#2} \def\MyFirst(#1#2){#1} \def\MyEqual#1#2{% string -> string -> bool \xdef\arga{#1}\xdef\argb{#2}% \TeXif{\ifx\arga\argb }} \def\MyEqualB#1#2#3#4{% \ifthenelse{\equal{#1}{#2}}{#3}{#4}} \def\myrightfile#1#2{% filediscriminator -> square -> bool \Member{\MyEqual}{#2}{\File{#1}}} \def\RightRank(#1){%square -> bool \EqStr{\RankDiscriminator}{Z}% {\True}% {\Member{\MyEqual}{#1}{\Rank{\RankDiscriminator}}}} \def\RightFile(#1){%square -> bool \EqStr{\FileDiscriminator}{Z}% {\True}% {\Member{\MyEqual}{#1}{\File{\FileDiscriminator}}}} \def\Glue#1#2% 'a -> 'b -> 'ab , eg. a -> 1 -> a1 {#1#2} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%% adding ornaments to a board %%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % PSTricks addon that allows hollow arrowheads \ps@on{% \edef\pst@arrowtable{\pst@arrowtable,<|-|>} \def\tx@ArrowTriangleA{ArrowTriangleA } \def\tx@ArrowTriangleB{ArrowTriangleB } \@namedef{psas@|>}{% /ArrowTriangleA { CLW dup 3.5 div SLW mul add dup 2 div /w ED mul dup /h ED mul /a ED 0 h a sub moveto w h L 0 0 L w neg h L 0 h a sub L gsave 1 setgray fill grestore gsave stroke grestore } def \psk@arrowinset \psk@arrowlength \psk@arrowsize \tx@ArrowTriangleA} \@namedef{psas@<|}{% /ArrowTriangle { CLW dup 2 div SLW mul add dup 2 div /w ED mul dup /h ED mul /a ED { 0 h T 1 -1 scale } if w neg h moveto 0 0 L w h L w neg a neg rlineto w neg a rlineto w 0 rmoveto gsave stroke grestore } def true \psk@arrowinset \psk@arrowlength \psk@arrowsize \tx@ArrowTriangleB} % end of PSTricks addon } {} %% Converts a file letter like `e' to its coordinate %% number, which would be `5' in this example. \def\file@from@letter#1{% \EqStr{#1}{a}{1} {\EqStr{#1}{b}{2} {\EqStr{#1}{c}{3} {\EqStr{#1}{d}{4} {\EqStr{#1}{e}{5} {\EqStr{#1}{f}{6} {\EqStr{#1}{g}{7} {\EqStr{#1}{h}{8}{}}}}}}}}} %% Several new counters for calculating the translation %% to an arbitrary square from the ``board marker''. \newcounter{fileFrom} \newcounter{rankFrom} \newcounter{fileTo} \newcounter{rankTo} \newcounter{ps@inverse} \newcounter{ps@knightangle} %% Computes the ``translation'' from the board marker %% `BM' to the given square and stores the results %% in `fileTo' and `rankTo' \def\get@translation#1#2{% \ifnum\value{ps@inverse}=0% \setcounter{fileTo}{8}% \setcounter{rankTo}{#2}% \addtocounter{fileTo}{-\file@from@letter{#1}}% \addtocounter{rankTo}{-1}% \else% \setcounter{fileTo}{\file@from@letter{#1}}% \setcounter{rankTo}{8}% \addtocounter{fileTo}{-1}% \addtocounter{rankTo}{-#2}% \fi} %% Sets the PostScript origin to the ``board marker'' %% first. Then the coordinate system is translated %% to the specified square. \def\skak@translate#1#2{% \get@translation#1#2% \translate(BM)% \translate(-\arabic{fileTo}.0,\arabic{rankTo}.0)} %% Computes the ``file angle'' for the two %% given files of a valid knight move and adds %% the value to the counter `ps@knightangle'. \def\add@fileangle#1#2{% \setcounter{fileTo}{\file@from@letter{#1}}% \setcounter{rankTo}{\file@from@letter{#2}}% \addtocounter{rankTo}{-\value{fileTo}}% \ifnum\value{rankTo}=1% \else% \ifnum\value{rankTo}=-1% \else% \ifnum\value{rankTo}=2% \else% \ifnum\value{rankTo}=-2% \addtocounter{ps@knightangle}{180}% \else% \errmessage{Files #1 and #2 do not belong to a valid knight move}% \fi% \fi% \fi% \fi} %% Computes the ``rank angle'' for the two %% given ranks of a valid knight move and adds %% the value to the counter `ps@knightangle'. \def\add@rankangle#1#2{% \setcounter{fileTo}{#1}% \setcounter{rankTo}{#2}% \addtocounter{rankTo}{-\value{fileTo}}% \ifnum\value{rankTo}=1% \else% \ifnum\value{rankTo}=-1% \else% \ifnum\value{rankTo}=2% \addtocounter{ps@knightangle}{90}% \else% \ifnum\value{rankTo}=-2% \addtocounter{ps@knightangle}{270}% \else% \errmessage{Ranks #1 and #2 do not belong to a valid knight move}% \fi% \fi% \fi% \fi} %% Prints the ``file angle'' for the given %% files of a valid knight move (for testing purposes). \def\printfileangle#1#2{% fileangle: % \setcounter{ps@knightangle}{0}% \add@fileangle{#1}{#2}% \arabic{ps@knightangle}} %% Prints the ``rank angle'' for the given %% ranks of a valid knight move (for testing purposes). \def\printrankangle#1#2{% rankangle: % \setcounter{ps@knightangle}{0}% \add@rankangle{#1}{#2}% \arabic{ps@knightangle}} %% Multiplies the counter with the given name %% by the current length of a board square. \def\multiply@by@sqlength#1{% \count255=\value{#1}% \multiply\count255 by \square@multiplier% \setcounter{#1}{\the\count255}} %% Multiplies the counters for the ``from'' %% and ``to'' squares by the current length %% of a board square. \def\convert@to@pt{% \multiply@by@sqlength{fileFrom}% \multiply@by@sqlength{rankFrom}% \multiply@by@sqlength{fileTo}% \multiply@by@sqlength{rankTo}} %% Sets the special markers ``From'' and ``To'' by %% directly outputting PS commands. \def\set@special@psmarkers#1#2{% \get@translation#1% \setcounter{fileFrom}{\value{fileTo}}% \setcounter{rankFrom}{\value{rankTo}}% \get@translation#2% \convert@to@pt% \special{ps: tx@Dict begin gsave STP newpath tx@NodeDict begin tx@NodeDict /N@BM known { /N@BM load GetCenter } { 0 0 } ifelse moveto {-\arabic{fileFrom}.0 \arabic{rankFrom}.0} false /N@From 10 {InitPnode } NewNode {-\arabic{fileTo}.0 \arabic{rankTo}.0} false /N@To 10 {InitPnode } NewNode end grestore end}} %% Outputs a ``knight move'' arrow from the first %% square to the second. \def\printknightmove#1#2{% \setcounter{ps@knightangle}{0}% \add@fileangle{\First#1}{\First#2}% \add@rankangle{\Second#1}{\Second#2}% \addtocounter{ps@knightangle}{\value{ps@inverse}}% \set@special@psmarkers{#1}{#2}% \ncdiagg[style=psskak,angleA=\arabic{ps@knightangle}]{-|>}{From}{To}} %% Outputs an arrow from the first board %% square to the second. \def\printarrow#1#2{% \set@special@psmarkers{#1}{#2}% \ncline[style=psskak]{-|>}{From}{To}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%% Highlighting squares, including the %%%%%%%%%%%%%%% %%%%% support for marker pieces (db <2002-11-12>) %%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \def\ps@markersquare#1{% \pscustom[linewidth=.06]{\skak@translate#1\psframe(-.5,-.5)(.5,.5)}} \def\ps@markerx#1{% \pscustom[linewidth=.06]{\skak@translate#1% \psline{-}(-.3,-.3)(.3,.3)}% \pscustom[linewidth=.06]{\skak@translate#1% \psline{-}(-.3,.3)(.3,-.3)}} \def\ps@markero#1{% \pscustom[linewidth=.06]{\skak@translate#1% \pscircle{.35}}} \def\ps@markerX#1{% \pscustom[linewidth=.06]{\skak@translate#1% \psline{-}(-.5,-.5)(.5,.5)}% \pscustom[linewidth=.06]{\skak@translate#1% \psline{-}(-.5,.5)(.5,-.5)}} \def\ps@markerO#1{% \pscustom[linewidth=.06]{\skak@translate#1% \pscircle{.7}}} %% %% The definitions of the next macros follow: %% Bechtolsheim, Stephan v.: "A tutorial on \futurelet" in: %% TUG: "TUGboat. The TeX Users Group Newsletter", Vol. 9, 1988, pp. 276 %% \def\highlight@WithOpt[#1]#2{% \EqStr{#1}{x}{\Apply{\ps@markerx}{\Listize[#2]}}% {\EqStr{#1}{o}{\Apply{\ps@markero}{\Listize[#2]}}% {\EqStr{#1}{X}{\Apply{\ps@markerX}{\Listize[#2]}}% {\EqStr{#1}{O}{\Apply{\ps@markerO}{\Listize[#2]}}% {\Apply{\ps@markersquare}{\Listize[#2]}}}}}% } \def\highlight@NoOpt#1{\Apply{\ps@markersquare}{\Listize[#1]}} \def\highlight@Decide{\ifx\highlight@Look [ \let\next=\highlight@WithOpt \else \let\next=\highlight@NoOpt \fi \next} % Usage: Either "\highlight{CSLS}" or "\highlight[MS]{CSLS}" % where CSLS is the comma separated list of squares % and MS is the marker symbol ("x", "X", "o" or "O") that % is used. \def\highlight{\futurelet\highlight@Look\highlight@Decide} %%%%% end of adding ornaments to a board %%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%% support for other languages %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \uc@king queen rook bishop knight pawn holds the letters % representinng the pieces in the current language % \skak@currentPieceNames : char list, holds the current piece names % \def\skak@pieceToEnglish#1{% string -> string, (pgn(curr. lang) -> pgn(eng)) % \skak@piece@toEnglish(#1Z)} \def\skak@piece@toEnglish#1{% \EqPiece{#1}{\uc@king}% {K}% {\EqPiece{#1}{\uc@queen}% {Q}% {\EqPiece{#1}{\uc@rook}% {R}% {\EqPiece{#1}{\uc@bishop}% {B}% {\EqPiece{#1}{\uc@knight}% {N}% {\EqPiece{#1}{\uc@pawn}% added 2005.03.30 UF {p}% {\errmessage{not a valid piece name in the current language:#1}}}}}}}} \def\skak@englishToEnglish#1{#1} \def\skak@definepieces#1#2#3#4#5#6{% \edef\uc@king{#1} \edef\uc@queen{#2} \edef\uc@rook{#3} \edef\uc@bishop{#4} \edef\uc@knight{#5} \edef\uc@pawn{#6}} \def\newskaklanguage#1#2{% \expandafter\xdef\csname skaklanguage.#1\endcsname{#2}} \newcommand{\skaklanguage}[1][english]{% \def\currentlanguage{#1}% \ifthenelse{\equal{#1}{english}}% {\let\skak@pieceToEnglish=\skak@englishToEnglish% \def\PieceNames{\Listize[K,Q,R,B,N,p]}} {\edef\temp@lang{\csname skaklanguage.#1\endcsname} \expandafter\skak@definepieces\temp@lang% \let\skak@pieceToEnglish=\skak@piece@toEnglish% \def\PieceNames{% \Listize[\uc@king,\uc@queen,\uc@rook,\uc@bishop,\uc@knight,\uc@pawn]}}} \def\showskaklanguage{% (\uc@king)(\uc@queen)(\uc@rook)(\uc@bishop)(\uc@knight)(\uc@pawn)} %%%%% end of language support %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%% parsing macros %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \def\IsPieceName#1{\Member{\EqPiece}{#1}\PieceNames} \def\IsFile#1% char -> bool {\Member{\EqStr}{#1}\FileNames} \def\IsRank#1% char -> bool {\Member{\EqStr}{#1}\RankNames} \def\IsCapture#1% char -> bool {\EqStr{#1}{x}} \def\IsPromotion#1% char -> bool {\EqStr{#1}{=}} \def\IsDash#1% char -> bool {\EqStr{#1}{-}} \def\IsO#1% char -> bool {\EqStr{#1}{O}} \def\File#1% file -> square list, eg. a -> [a1,a2,...,a8] {\Map{\Glue{#1}}{\RankNames}} \def\Rank#1% rank -> square list, eg. 1 -> [a1,b1,...,h1] {\Map{\Twiddle\Glue{#1}}{\FileNames}} % Compose: ('b -> 'c) -> ('a -> 'b) -> ('a -> c') % Second: 'a -> 'b -> 'b % f: 'a -> unit % Compose Second f: 'a -> ('a -> 'b -> unit) % \def\Apply#1#2% ('a -> unit) -> ('a list -> unit) % {\Force{\Map{#1}{#2}}} % \def\Force#1{#1\ForceA{}} % \def\ForceA#1{#1\Foldr\DoIt{}} % \def\DoIt#1#2{#1#2} \def\Sideeffect#1#2#3{% ('a -> unit) -> ('a -> 'b -> unit) #1{#2}#3} \def\Apply#1#2{% ('a -> unit) -> 'a list -> unit \Foldr{\Sideeffect{#1}}{\relax}{#2}} \def\EmptyBoard% {\Apply{\Twiddle\Set{E}}{\Rank{1}} \Apply{\Twiddle\Set{E}}{\Rank{2}} \Apply{\Twiddle\Set{E}}{\Rank{3}} \Apply{\Twiddle\Set{E}}{\Rank{4}} \Apply{\Twiddle\Set{E}}{\Rank{5}} \Apply{\Twiddle\Set{E}}{\Rank{6}} \Apply{\Twiddle\Set{E}}{\Rank{7}} \Apply{\Twiddle\Set{E}}{\Rank{8}}} \def\FenConvert#1{% \EqStr{8}{#1}% {EEEEEEEE}% {\EqStr{7}{#1}% {EEEEEEE}% {\EqStr{6}{#1}% {EEEEEE}% {\EqStr{5}{#1}% {EEEEE}% {\EqStr{4}{#1}% {EEEE}% {\EqStr{3}{#1}% {EEE}% {\EqStr{2}{#1}% {EE}% {\EqStr{1}{#1}% {E}% {#1}}}}}}}}} \def\ParseFenRank#1{\ParseFenRankA(#1Z)} \def\ParseFenRankA(#1#2){% \EqStr{Z}{#1}% {}% {\FenConvert{#1}\ParseFenRankA(#2)}} \def\SetCheckKing#1#2{% square -> piece -> unit \EqStr{K}{#2}% {\edef\WhiteKingSquare{#1}}% {\EqStr{k}{#2}% {\edef\BlackKingSquare{#1}}% {}}% \Set{#1}{#2}} \def\InitRank#1#2#3#4#5#6#7#8#9{% \SetCheckKing{a#9}{#1}% \SetCheckKing{b#9}{#2}% \SetCheckKing{c#9}{#3}% \SetCheckKing{d#9}{#4}% \SetCheckKing{e#9}{#5}% \SetCheckKing{f#9}{#6}% \SetCheckKing{g#9}{#7}% \SetCheckKing{h#9}{#8}} \def\SetRank#1#2{% rank -> fenrank -> unit \edef\pap{\ParseFenRank{#2}}% \expandafter\InitRank\pap#1} \def\InitBoard(#1/#2/#3/#4/#5/#6/#7/#8){% \SetRank{8}{#1}% \SetRank{7}{#2}% \SetRank{6}{#3}% \SetRank{5}{#4}% \SetRank{4}{#5}% \SetRank{3}{#6}% \SetRank{2}{#7}% \SetRank{1}{#8}% } \def\WhiteCastling{-} \def\BlackCastling{-} \def\ExtractWhiteCastling#1{\def\tempCastling{-}% \ExtractWhiteCastlingA(#1Z)% \edef\WhiteCastling{\tempCastling}} \def\ExtractWhiteCastlingA(#1#2){% \EqStr{Z}{#1}% {}% {\Or{\EqPiece{K}{#1}}{\EqPiece{Q}{#1}}% {\EqStr{-}{\tempCastling}% {\edef\tempCastling{#1}\ExtractWhiteCastlingA(#2)}% {\edef\tempCastling{\tempCastling#1}}}% {\ExtractWhiteCastlingA(#2)}}} \def\ExtractBlackCastling#1{\def\tmpCastling{-}% \ExtractBlackCastlingA(#1Z)% \edef\BlackCastling{\tmpCastling}} \def\ExtractBlackCastlingA(#1#2){% \EqStr{Z}{#1}% {}% {\Or{\EqPiece{k}{#1}}{\EqPiece{q}{#1}}% {\EqStr{-}{\tmpCastling}% {\edef\tmpCastling{#1}\ExtractBlackCastlingA(#2)}% {\edef\tmpCastling{\tmpCastling#1}}}% {\ExtractBlackCastlingA(#2)}}} \newcounter{halfmove} \newcounter{move} \def\@fenboard#1{\FenBoard#1)} \def\FenBoard#1 #2 #3 #4 #5 #6){% \InitBoard(#1)% \EqStr{w}{#2}% {\gdef\WhiteToMove{\True}}% {\gdef\WhiteToMove{\False}}%\EqStr{w}{#2}}% \ExtractWhiteCastling{#3}%} \ExtractBlackCastling{#3}%} \edef\EnPassantSquare{#4}% \setcounter{halfmove}{#5}% \setcounter{move}{#6}} \def\fenboard#1{% % \@fenboard#1% \FenBoard#1)% \@initstorage} \newcounter{helpgobble} \def\PieceToFen#1{% \EqPiece{E}{#1}% {1}{#1}} \def\Fen@RawRank#1{\PieceToFen{\Get{a#1}}\PieceToFen{\Get{b#1}}% \PieceToFen{\Get{c#1}}\PieceToFen{\Get{d#1}}% \PieceToFen{\Get{e#1}}\PieceToFen{\Get{f#1}}% \PieceToFen{\Get{g#1}}\PieceToFen{\Get{h#1}}} \def\PrintCastling{% \EqStr{-}{\WhiteCastling}% {\BlackCastling}% {\WhiteCastling% \EqStr{-}{\BlackCastling}% {-}% {\BlackCastling}}} \def\Fen@handlenumbers#1#2#3#4#5#6#7#8{\setcounter{helpgobble}{0}% \Fen@handleA(#1#2#3#4#5#6#7#8Z)} \def\Fen@handleA(#1#2){% \EqStr{Z}{#1}% {\ifnum0=\thehelpgobble% \else\edef\temp@rank{\temp@rank\arabic{helpgobble}}\fi}% {\EqPiece{1}{#1}% {\stepcounter{helpgobble}\Fen@handleA(#2)}% {\ifnum0=\thehelpgobble\edef\temp@rank{\temp@rank#1}\Fen@handleA(#2)% \else\edef\temp@rank{\temp@rank\arabic{helpgobble}#1}% \setcounter{helpgobble}{0}\Fen@handleA(#2)\fi}}} \def\Fen@Rank#1{\edef\temp@rank{}\edef\temp@rankA{\Fen@RawRank{#1}}% \expandafter\Fen@handlenumbers\temp@rankA} \def\Fen@calculate{% \Fen@Rank{8}\edef\temp@board{\temp@rank/}% \Fen@Rank{7}\edef\temp@board{\temp@board\temp@rank/}% \Fen@Rank{6}\edef\temp@board{\temp@board\temp@rank/}% \Fen@Rank{5}\edef\temp@board{\temp@board\temp@rank/}% \Fen@Rank{4}\edef\temp@board{\temp@board\temp@rank/}% \Fen@Rank{3}\edef\temp@board{\temp@board\temp@rank/}% \Fen@Rank{2}\edef\temp@board{\temp@board\temp@rank/}% \Fen@Rank{1}\edef\temp@board{\temp@board\temp@rank}% \edef\temp@board{\temp@board\space\WhiteToMove{w}{b}}% \edef\temp@board{\temp@board\space\PrintCastling\space\EnPassantSquare}% \edef\temp@board{\temp@board\space\arabic{halfmove}\space\arabic{move}}} \def\boardasfen{\Fen@calculate\temp@board} % if someone wants fen in % their document %%%%% manipulation of the board state % the special out-of-bounds square \Set{Offboard}{X} % note: no piece is named X \def\EnPassantSquare{-}% updated by ExecuteMove \def\WhiteToMove{\True} \xdef\WhiteKingSquare% unit -> square {e1} \xdef\BlackKingSquare% unit -> square {e8} \def\KingSquare#1{% bool -> square #1\WhiteKingSquare\BlackKingSquare} \def\SetKingSquare#1#2{% bool -> square -> unit #1{\xdef\WhiteKingSquare{#2}}{\xdef\BlackKingSquare{#2}}} % neighbours of a square \def\SetNeighbour#1#2#3% direction -> square -> square -> unit, #2's % neighbour in direction #1 is #3 {\expandafter\xdef\csname#1.#2\endcsname{#3}} \def\GetNeighbour#1#2% direction -> square -> square {\csname#1.#2\endcsname} % all the hard work: % first we deal with the board border \def\FF#1#2{\SetNeighbour{#1}{#2}{Offboard}} \def\ForwardDirection#1% bool -> direction; up for white, down for black {#1{up}{down}} \def\BackwardDirection#1% bool -> direction {#1{down}{up}} \def\LeftDirection#1% bool -> direction {#1{left}{right}} \def\RightDirection#1% bool -> direction {#1{right}{left}} \Apply{\FF{left}}{\File{a}} \Apply{\FF{upleft}}{\File{a}} \Apply{\FF{downleft}}{\File{a}} \Apply{\FF{right}}{\File{h}} \Apply{\FF{upright}}{\File{h}} \Apply{\FF{downright}}{\File{h}} \Apply{\FF{up}}{\Rank{8}} \Apply{\FF{upleft}}{\Rank{8}} \Apply{\FF{upright}}{\Rank{8}} \Apply{\FF{down}}{\Rank{1}} \Apply{\FF{downleft}}{\Rank{1}} \Apply{\FF{downright}}{\Rank{1}} \def\SetUpNeighbour#1#2#3% direction -> rank -> rank -> unit {\SetNeighbour{#1}{a#2}{a#3}% \SetNeighbour{#1}{b#2}{b#3}% \SetNeighbour{#1}{c#2}{c#3}% \SetNeighbour{#1}{d#2}{d#3}% \SetNeighbour{#1}{e#2}{e#3}% \SetNeighbour{#1}{f#2}{f#3}% \SetNeighbour{#1}{g#2}{g#3}% \SetNeighbour{#1}{h#2}{h#3}} \let\SetDownNeighbour=\SetUpNeighbour% \SetUpNeighbour{up}{1}{2} \SetUpNeighbour{up}{2}{3} \SetUpNeighbour{up}{3}{4} \SetUpNeighbour{up}{4}{5} \SetUpNeighbour{up}{5}{6} \SetUpNeighbour{up}{6}{7} \SetUpNeighbour{up}{7}{8} \SetDownNeighbour{down}{2}{1} \SetDownNeighbour{down}{3}{2} \SetDownNeighbour{down}{4}{3} \SetDownNeighbour{down}{5}{4} \SetDownNeighbour{down}{6}{5} \SetDownNeighbour{down}{7}{6} \SetDownNeighbour{down}{8}{7} \def\SetUpRightNeighbour#1#2#3% direction -> rank -> rank -> unit {\SetNeighbour{#1}{a#2}{b#3}% \SetNeighbour{#1}{b#2}{c#3}% \SetNeighbour{#1}{c#2}{d#3}% \SetNeighbour{#1}{d#2}{e#3}% \SetNeighbour{#1}{e#2}{f#3}% \SetNeighbour{#1}{f#2}{g#3}% \SetNeighbour{#1}{g#2}{h#3}% \SetNeighbour{#1}{h#2}{Offboard}} \let\SetDownRightNeighbour=\SetUpRightNeighbour \SetUpRightNeighbour{upright}{1}{2} \SetUpRightNeighbour{upright}{2}{3} \SetUpRightNeighbour{upright}{3}{4} \SetUpRightNeighbour{upright}{4}{5} \SetUpRightNeighbour{upright}{5}{6} \SetUpRightNeighbour{upright}{6}{7} \SetUpRightNeighbour{upright}{7}{8} \SetDownRightNeighbour{downright}{2}{1} \SetDownRightNeighbour{downright}{3}{2} \SetDownRightNeighbour{downright}{4}{3} \SetDownRightNeighbour{downright}{5}{4} \SetDownRightNeighbour{downright}{6}{5} \SetDownRightNeighbour{downright}{7}{6} \SetDownRightNeighbour{downright}{8}{7} \def\SetUpLeftNeighbour#1#2#3% direction -> rank -> rank -> unit {\SetNeighbour{#1}{a#2}{Offboard}% \SetNeighbour{#1}{b#2}{a#3}% \SetNeighbour{#1}{c#2}{b#3}% \SetNeighbour{#1}{d#2}{c#3}% \SetNeighbour{#1}{e#2}{d#3}% \SetNeighbour{#1}{f#2}{e#3}% \SetNeighbour{#1}{g#2}{f#3}% \SetNeighbour{#1}{h#2}{g#3}} \let\SetDownLeftNeighbour=\SetUpLeftNeighbour \SetUpLeftNeighbour{upleft}{1}{2} \SetUpLeftNeighbour{upleft}{2}{3} \SetUpLeftNeighbour{upleft}{3}{4} \SetUpLeftNeighbour{upleft}{4}{5} \SetUpLeftNeighbour{upleft}{5}{6} \SetUpLeftNeighbour{upleft}{6}{7} \SetUpLeftNeighbour{upleft}{7}{8} \SetDownLeftNeighbour{downleft}{2}{1} \SetDownLeftNeighbour{downleft}{3}{2} \SetDownLeftNeighbour{downleft}{4}{3} \SetDownLeftNeighbour{downleft}{5}{4} \SetDownLeftNeighbour{downleft}{6}{5} \SetDownLeftNeighbour{downleft}{7}{6} \SetDownLeftNeighbour{downleft}{8}{7} \def\SetLeftNeighbour#1#2#3% direction -> file -> file -> unit {\SetNeighbour{#1}{#21}{#31}% \SetNeighbour{#1}{#22}{#32}% \SetNeighbour{#1}{#23}{#33}% \SetNeighbour{#1}{#24}{#34}% \SetNeighbour{#1}{#25}{#35}% \SetNeighbour{#1}{#26}{#36}% \SetNeighbour{#1}{#27}{#37}% \SetNeighbour{#1}{#28}{#38}} \let\SetRightNeighbour=\SetLeftNeighbour \SetLeftNeighbour{left}{b}{a} \SetLeftNeighbour{left}{c}{b} \SetLeftNeighbour{left}{d}{c} \SetLeftNeighbour{left}{e}{d} \SetLeftNeighbour{left}{f}{e} \SetLeftNeighbour{left}{g}{f} \SetLeftNeighbour{left}{h}{g} \SetRightNeighbour{right}{a}{b} \SetRightNeighbour{right}{b}{c} \SetRightNeighbour{right}{c}{d} \SetRightNeighbour{right}{d}{e} \SetRightNeighbour{right}{e}{f} \SetRightNeighbour{right}{f}{g} \SetRightNeighbour{right}{g}{h} % the knight needs special attention \def\KnightSquares#1% square -> square list {\csname#1.knight\endcsname} \def\SetKnightSquares#1#2% square -> square list -> unit {\expandafter\def\csname#1.knight\endcsname{#2}} % a file \SetKnightSquares{a1}{\Listize[b3,c2]} \SetKnightSquares{a2}{\Listize[b4,c3,c1]} \SetKnightSquares{a3}{\Listize[b5,c4,c2,b1]} \SetKnightSquares{a4}{\Listize[b6,c5,c3,b2]} \SetKnightSquares{a5}{\Listize[b7,c6,c4,b3]} \SetKnightSquares{a6}{\Listize[b8,c7,c5,b4]} \SetKnightSquares{a7}{\Listize[c8,c6,b5]} \SetKnightSquares{a8}{\Listize[c7,b6]} % b file %Typo corrected at b6 \SetKnightSquares{b1}{\Listize[a3,c3,d2]} \SetKnightSquares{b2}{\Listize[a4,c4,d3,d1]} \SetKnightSquares{b3}{\Listize[a5,c5,d4,d2,a1,c1]} \SetKnightSquares{b4}{\Listize[a6,c6,d5,d3,a2,c2]} \SetKnightSquares{b5}{\Listize[a7,c7,d6,d4,a3,c3]} \SetKnightSquares{b6}{\Listize[a8,c8,d7,d5,a4,c4]} \SetKnightSquares{b7}{\Listize[d8,d6,a5,c5]} \SetKnightSquares{b8}{\Listize[d7,a6,c6]} % c file \SetKnightSquares{c1}{\Listize[a2,b3,d3,e2]} \SetKnightSquares{c2}{\Listize[a1,a3,b4,d4,e3,e1]} \SetKnightSquares{c3}{\Listize[a2,a4,b1,b5,d1,d5,e2,e4]} \SetKnightSquares{c4}{\Listize[a3,a5,b2,b6,d2,d6,e3,e5]} \SetKnightSquares{c5}{\Listize[a4,a6,b3,b7,d3,d7,e4,e6]} \SetKnightSquares{c6}{\Listize[a5,a7,b4,b8,d4,d8,e5,e7]} \SetKnightSquares{c7}{\Listize[a6,a8,b5,d5,e6,e8]} \SetKnightSquares{c8}{\Listize[a7,b6,d6,e7]} % d file \SetKnightSquares{d1}{\Listize[b2,c3,e3,f2]} \SetKnightSquares{d2}{\Listize[b1,b3,c4,e4,f3,f1]} \SetKnightSquares{d3}{\Listize[b2,b4,c1,c5,e1,e5,f2,f4]} \SetKnightSquares{d4}{\Listize[b3,b5,c2,c6,e2,e6,f3,f5]} \SetKnightSquares{d5}{\Listize[b4,b6,c3,c7,e3,e7,f4,f6]} \SetKnightSquares{d6}{\Listize[b5,b7,c4,c8,e4,e8,f5,f7]} \SetKnightSquares{d7}{\Listize[b6,b8,c5,e5,f6,f8]} \SetKnightSquares{d8}{\Listize[b7,c6,e6,f7]} % e file \SetKnightSquares{e1}{\Listize[c2,d3,f3,g2]} \SetKnightSquares{e2}{\Listize[c1,c3,d4,f4,g3,g1]} \SetKnightSquares{e3}{\Listize[c2,c4,d1,d5,f1,f5,g2,g4]} \SetKnightSquares{e4}{\Listize[c3,c5,d2,d6,f2,f6,g3,g5]} \SetKnightSquares{e5}{\Listize[c4,c6,d3,d7,f3,f7,g4,g6]} \SetKnightSquares{e6}{\Listize[c5,c7,d4,d8,f4,f8,g5,g7]} \SetKnightSquares{e7}{\Listize[c6,c8,d5,f5,g6,g8]} \SetKnightSquares{e8}{\Listize[c7,d6,f6,g7]} % f file \SetKnightSquares{f1}{\Listize[d2,e3,g3,h2]} \SetKnightSquares{f2}{\Listize[d1,d3,e4,g4,h3,h1]} \SetKnightSquares{f3}{\Listize[d2,d4,e1,e5,g1,g5,h2,h4]} \SetKnightSquares{f4}{\Listize[d3,d5,e2,e6,g2,g6,h3,h5]} \SetKnightSquares{f5}{\Listize[d4,d6,e3,e7,g3,g7,h4,h6]} \SetKnightSquares{f6}{\Listize[d5,d7,e4,e8,g4,g8,h5,h7]} \SetKnightSquares{f7}{\Listize[d6,d8,e5,g5,h6,h8]} \SetKnightSquares{f8}{\Listize[d7,e6,g6,h7]} % g file \SetKnightSquares{g1}{\Listize[h3,f3,e2]} \SetKnightSquares{g2}{\Listize[h4,f4,e3,e1]} \SetKnightSquares{g3}{\Listize[h5,f5,e4,e2,h1,f1]} \SetKnightSquares{g4}{\Listize[h6,f6,e5,e3,h2,f2]} \SetKnightSquares{g5}{\Listize[h7,f7,e6,e4,h3,f3]} \SetKnightSquares{g6}{\Listize[h8,f8,e7,e5,h4,f4]} \SetKnightSquares{g7}{\Listize[e8,e6,h5,f5]} \SetKnightSquares{g8}{\Listize[h6,f6,e7]} % h file \SetKnightSquares{h1}{\Listize[g3,f2]} \SetKnightSquares{h2}{\Listize[g4,f3,f1]} \SetKnightSquares{h3}{\Listize[g5,f4,f2,g1]} \SetKnightSquares{h4}{\Listize[g6,f5,f3,g2]} \SetKnightSquares{h5}{\Listize[g7,f6,f4,g3]} \SetKnightSquares{h6}{\Listize[g8,f7,f5,g4]} \SetKnightSquares{h7}{\Listize[f8,f6,g5]} \SetKnightSquares{h8}{\Listize[f7,g6]} % StringToTokens: string -> string list, cut at spaces \def\StringToTokens#1% {\ifthenelse{\equal{#1}{}}{\Nil}{\StrToTokens(#1 )}} \def\StrToTokens (#1 #2){% \EqStr{#1}{}% {\Nil}% \Cons{#1}{\EqStr{#2}{} {\Nil} {\StrToTokens(#2)}}} \def\BlackPiece#1% char -> piece {\EqStr{#1}{K}% {k}% {\EqStr{#1}{Q}% {q}% {\EqStr{#1}{R}% {r}% {\EqStr{#1}{B}% {b}% {\EqStr{#1}{N}% {n}% {p}}}}}} \def\PieceNameToPiece#1#2% piecename -> bool -> piece {#2{#1}{\BlackPiece{#1}}} % setting up variables for ParseMove \def\ParseMoveInit{% \gdef\MoveToRank{Z}\gdef\MoveToFile{Z}% \gdef\RankDiscriminator{Z}\gdef\FileDiscriminator{Z}% \gdef\PieceNameToMove{Z}% \gdef\Capture{\False}% \gdef\Promotion{\False}\gdef\PromotionPieceName{Z}% \gdef\Castling{\False}\gdef\LongCastling{\False}% \gdef\CheckTest{}% \gdef\MateTest{}% \gdef\MoveRest{}} \def\ParseMove#1{% string -> unit \StoreLastMove{\gdef\LastMoveString{#1}}{}% usualy only done for mainline. \ParseMoveA(#1)} \DeclareRobustCommand{\lastmove}{{\def\variationstyle{}% \styleC@on{\let\skak@ensuremath=\ensuremath}{\let\skak@ensuremath=\relax}% \WhiteToMove{% \addtocounter{move}{-1}% \skak@ensuremath\beforenumber\arabic{move}\blackopen\skak@ensuremath% \beforeblack% \addtocounter{move}{1}}% {\skak@ensuremath\beforenumber\arabic{move}\skak@ensuremath\whiteopen% \skak@ensuremath\beforewhite}% \expandafter\wmove\expandafter{\LastMoveString}}} \def\ParseMoveA(#1#2){% char -> string -> unit \IsPieceName{#1}% {\gdef\PieceNameToMove{\skak@pieceToEnglish{#1}}% \gdef\PieceToMove{\PieceNameToPiece{\PieceNameToMove}{\WhiteToMove}}% \ParseCoordinates(#2Z)% \gdef\MoveTo{\MoveToFile\MoveToRank}}% {\IsO{#1}% {\def\Castling{\True}% \ParseCastling(#2Z)}% {\ParseCoordinates(#1#2Z)% \gdef\MoveTo{\MoveToFile\MoveToRank}}}} \def\FirstChar(#1#2){#1} \def\FirstChar(#1#2){#1} \def\RestChars(#1#2){\gdef\@restchars{#2}} \def\ParseCoordinates(#1#2){% char -> string -> unit \EqStr{Z}{#1}% {}% we are done! {\IsFile{#1}% {\EqStr{\MoveToFile}{Z}% {}% first File name in move so nothing to do {\xdef\FileDiscriminator{\MoveToFile}}% \gdef\MoveToFile{#1}% \ParseCoordinates(#2)}% {\IsRank{#1}% {\EqStr{\MoveToRank}{Z}% {}% {\xdef\RankDiscriminator{\MoveToRank}}% \gdef\MoveToRank{#1}% \ParseCoordinates(#2)}% {\IsCapture{#1}% {\gdef\Capture{\True}% \ParseCoordinates(#2)}% {\IsPromotion{#1}% {\gdef\Promotion{\True}% \gdef\PromotionPieceName{\skak@pieceToEnglish{\FirstChar(#2)}}% \RestChars(#2)% sets \@restchars \expandafter\ParseCoordinates\expandafter(\@restchars)}% {\EqStr{#1}{+}% {\protected@xdef\CheckTest{\checksymbol}\ParseCoordinates(#2)}% {\EqStr{#1}{##}% {\protected@xdef\MateTest{\mate}\ParseCoordinates(#2)}% {\@setmoverest(#1#2)}}}}}}}} \def\@setmoverest(#1Z){\gdef\MoveRest{#1}} % help for \ParseCastling \def\ParseCastlingA(#1#2#3){% \MyEqualB{#1#2}{-O}% {\gdef\LongCastling{\True}}% {}} \def\ParseCastling(-O#1){% strip the first -O, at least Z is left \ParseCastlingA(#1VW)} % for testing purposes \def\ShowParseInfo% { %MoveTo: \MoveTo MoveToRank: \MoveToRank, MoveToFile: \MoveToFile, \\ RankDiscriminator: \RankDiscriminator, FileDiscriminator: \FileDiscriminator, \\ Promotion: \BoolToString{\Promotion}, PromotionPieceName: \PromotionPieceName Capture: \BoolToString{\Capture}, \\ PieceNameToMove: \PieceNameToMove, \\ Castling: \BoolToString{\Castling}, LongCastling: \BoolToString{\LongCastling}} % castling, with preparation for eg, FisheRandom %\def\WhiteShortRook{h1} %\def\WhiteLongRook{a1} %\def\BlackShortRook{h8} %\def\WhiteLong \def\FirstRank#1{% bool -> rank #1{1}{8}} \def\CastleKingFile#1{% bool -> file, LongCastling is used as argument #1{c}{g}} \def\CastleRookToFile#1{% #1{d}{f}} \def\CastleRookFromFile#1{% #1{a}{h}} \def\CastleDone#1{% bool -> unit #1{\gdef\WhiteCastling{-}}{\gdef\BlackCastling{-}}} \def\ExecuteCastling{% relies on \ParseMove \stepcounter{halfmove}% \gdef\MoveTo{\CastleKingFile{\LongCastling}\FirstRank{\WhiteToMove}}% \ExecuteKingMove% \gdef\MoveTo{\CastleRookToFile{\LongCastling}\FirstRank{\WhiteToMove}}% \DoTheMove{\CastleRookFromFile{\LongCastling}\FirstRank{\WhiteToMove}}% \CastleDone{\WhiteToMove}} %%% after ParseMove has gathered info we find the piece to move % LookFor looks in one direction, stopping if a non-empty square is % found \def\LookFor#1#2#3{% (piece -> bool) -> square -> direction -> square list \LookForA{#1}{\GetNeighbour{#3}{#2}}{#3}} % we have to skip the % first square!!! \def\LookForA#1#2#3{% (piece -> bool) -> square -> direction -> square list #1{\Get{#2}}% {\Singleton{#2}}% {\EqPiece{E}{\Get{#2}}% empty square => continue in the given direction {\LookForA{#1}{\GetNeighbour{#3}{#2}}{#3}}% {\Nil}}} % IsRightPiece is true if a piece matching #1 is on square#2 \def\IsRightPiece#1#2{% piece -> square -> bool \EqPiece{#1}{\Get{#2}}} \def\IsRookQueen#1#2{% bool -> piece -> bool \Or{\EqPiece{#2}{\PieceNameToPiece{R}{#1}}}% {\EqPiece{#2}{\PieceNameToPiece{Q}{#1}}}% } \def\IsBishopQueen#1#2{% bool -> piece -> bool \Or{\EqPiece{#2}{\PieceNameToPiece{B}{#1}}}% {\EqPiece{#2}{\PieceNameToPiece{Q}{#1}}}% } % (piece-> bool) -> square -> direction list -> square list \def\ScanDirections#1#2#3{\Foldr{\Compose\Cat{\LookFor{#1}{#2}}}\Nil{#3}} % relies on the info gathered by ParseMove \def\FindPieceSquares#1#2{% bool -> square -> square list \EqPiece{\PieceNameToMove}{R}% {\ScanDirections% {\EqPiece{\PieceToMove}}{#2}{\Listize[up,down,left,right]}}% {\EqPiece{\PieceNameToMove}{B}% {\ScanDirections% {\EqPiece{\PieceToMove}}{#2}% {\Listize[upright,downright,downleft,upleft]}}% {\EqPiece{\PieceNameToMove}{Q}% {\ScanDirections% {\EqPiece{\PieceToMove}}{#2}% {\Listize[up,down,left,right,upleft,upright,downleft,downright]}}% {\Filter{\IsRightPiece{\PieceToMove}}{\KnightSquares{#2}}}}}} \def\UniqueMove% bool, if the descriminators <> Z {\LambdaAnd% {\Not{\EqStr{\RankDiscriminator}{Z}}}% {\Not{\EqStr{\FileDiscriminator}}{Z}}} \def\DoTheMove#1{% move the piece from #1 to \MoveToFile\MoveToRank \edef\oldpiece{\Get{\MoveToFile\MoveToRank}}% \Set{\MoveTo}{\Get{#1}}\Set{#1}{E}% \edef\MoveFrom{#1}} \def\DoTheMoveList#1{\DoTheMove{\Head{#1}}} % undoes the move to #1 \def\UndoMove#1{% square -> unit, relies on \oldpiece and \MoveToFile/Rank \Set{#1}{\Get{\MoveToFile\MoveToRank}}\Set{\MoveToFile\MoveToRank}{\oldpiece}% \Or{\EqPiece{\PieceToMove}{K}}{\EqPiece{\PieceToMove}{k}}% {\SetKingSquare{\WhiteToMove}{#1}}% {}} \def\NoEnemiesFound{% bool \IsNil{\Cat{\ScanDirections{\IsRookQueen{\Not\WhiteToMove}}% {\KingSquare{\WhiteToMove}}{\Listize[up,down,left,right]}}% {\ScanDirections{\IsBishopQueen{\Not\WhiteToMove}}% {\KingSquare{\WhiteToMove}}% {\Listize[upleft,downright,downleft,upright]}}}} \newboolean{helplegal} \def\LegalMove#1{% square -> bool, is the move possible to do? \DoTheMove{#1}% \NoEnemiesFound% {\UndoMove{#1}\True}% {\UndoMove{#1}\False}}% % relies on \ParseMove \def\TrimMoveList#1{% square -> bool \gdef\trimhelp{#1}%( \LambdaAnd{\RightRank(\trimhelp)}{\LambdaAnd{\RightFile(\trimhelp)}{\LegalMove{\trimhelp}}}} \def\ExecuteKingMove{% relies on ParseMove, WhiteToMove \DoTheMove{\KingSquare{\WhiteToMove}}% \SetKingSquare{\WhiteToMove}{\MoveTo}% \WhiteToMove% {\edef\WhiteCastling{-}}% {\edef\BlackCastling{-}}} % used by UpdateCastling \def\RemoveLongCastling{% relies on \WhiteToMove \WhiteToMove% {\ifthenelse{\equal{KQ}{\WhiteCastling}}% {\gdef\WhiteCastling{K}}% {\ifthenelse{\equal{Q}{\WhiteCastling}}% {\gdef\WhiteCastling{-}}% {}}}% {\ifthenelse{\equal{kq}{\BlackCastling}}% {\gdef\BlackCastling{k}}% {\ifthenelse{\equal{q}{\BlackCastling}}% {\edef\BlackCastling{-}}% {}}}}% % used by UpdateCastling \def\RemoveShortCastling{% relies on \WhiteToMove \WhiteToMove% {\ifthenelse{\equal{KQ}{\WhiteCastling}}% %\EqStr{KQ}{\WhiteCastling}% {\gdef\WhiteCastling{Q}}% {\ifthenelse{\equal{K}{\WhiteCastling}} {\gdef\WhiteCastling{-}}% {}}}% {\ifthenelse{\equal{kq}{\BlackCastling}}% %\EqStr{kq}{\BlackCastling}% {\gdef\BlackCastling{q}}% {\EqStr{k}{\BlackCastling}% {\gdef\BlackCastling{-}}% {}}}} \def\UpdateCastling{% relies on \ParseMove \EqPiece{R}{\PieceNameToMove}% {\EqSquare{\MoveFrom}{\CastleRookFromFile{\True}\FirstRank{\WhiteToMove}}% {\RemoveLongCastling}% {\EqSquare{\MoveFrom}{\CastleRookFromFile{\False}\FirstRank{\WhiteToMove}}% {\RemoveShortCastling}% {}}}% {}}% non rook moves will not change the castling possibilities \def\ExecutePieceMove{% relies on the info gathered by ParseMove \Capture{\setcounter{halfmove}{0}}{\stepcounter{halfmove}}% \UniqueMove% {\DoTheMove{\FileDiscriminator\RankDiscriminator}}% {\EqPiece{K}{\PieceNameToMove}% {\ExecuteKingMove}% {% % (\Unlistize{\FindPieceSquares{\WhiteToMove}{\MoveTo}},% % \Unlistize{\Filter{\TrimMoveList}% % {\FindPieceSquares{\WhiteToMove}{\MoveTo}}})% \Apply{\DoTheMove}{\Filter{\TrimMoveList}% {\FindPieceSquares{\WhiteToMove}{\MoveTo}}}}% }% \UpdateCastling} \def\FromRank{% \EqStr{1}{\MoveToRank}% {\WhiteToMove{0}{2}}% {\EqStr{2}{\MoveToRank}% {\WhiteToMove{1}{3}}% {\EqStr{3}{\MoveToRank}% {\WhiteToMove{2}{4}}% {\EqStr{4}{\MoveToRank}% {\WhiteToMove{3}{5}}% {\EqStr{5}{\MoveToRank}% {\WhiteToMove{4}{6}}% {\EqStr{6}{\MoveToRank}% {\WhiteToMove{5}{7}}% {\EqStr{7}{\MoveToRank}% {\WhiteToMove{6}{8}}% {\EqStr{8}{\MoveToRank}% {\WhiteToMove{7}{9}}% {}}}}}}}}} \def\InitialRank{\WhiteToMove{2}{7}} % \def\ExecutePawnMove{% relies on the info obtained by ParseMove % \setcounter{halfmove}{0}% % \Capture% % {\EqPiece{E}{\Get{\MoveTo}}% % {\Set{\MoveToFile\FromRank}{E}}% % {}% % \DoTheMove{\FileDiscriminator\FromRank}% % \xdef\EnPassantSquare{-}}% % {\EqPiece{E}{\Get{\MoveToFile\FromRank}}% % {\xdef\EnPassantSquare{\MoveToFile\FromRank}% two square move % \DoTheMove{\MoveToFile\InitialRank}}% % {\xdef\EnPassantSquare{-}% % \DoTheMove{\MoveToFile\FromRank}% one square move % }}% % \Promotion% % {\Set{\MoveTo}{\PieceNameToPiece{\PromotionPieceName}{\WhiteToMove}}}% % {}} % Bug-fix for longmove \def\ExecutePawnMove{% relies on the info obtained by ParseMove \setcounter{halfmove}{0}% \Capture% {\EqPiece{E}{\Get{\MoveTo}}% {\Set{\MoveToFile\FromRank}{E}}% {}% \xdef\PawnFrom{\FileDiscriminator\FromRank}% \DoTheMove{\PawnFrom}% \xdef\EnPassantSquare{-}}% {\EqPiece{E}{\Get{\MoveToFile\FromRank}}% {\xdef\EnPassantSquare{\MoveToFile\FromRank}% two square move \xdef\PawnFrom{\MoveToFile\InitialRank}% \DoTheMove{\PawnFrom}}% {\xdef\EnPassantSquare{-}% \xdef\PawnFrom{\MoveToFile\FromRank}% \DoTheMove{\PawnFrom}% one square move }}% \Promotion% {\Set{\MoveTo}{\PieceNameToPiece{\PromotionPieceName}{\WhiteToMove}}}% {}} \def\MakeMove#1{% string -> unit \ParseMoveInit% \ParseMove{#1}% % check if there is a piece of own colour on \MoveToFile\MoveToRank % THIS CHECK HAS TO BE IMPLEMENTED! \ExecuteMoves% {\EqPiece{Z}{\PieceNameToMove}% {\Castling% {\gdef\EnPassantSquare{-}\ExecuteCastling}% {\ExecutePawnMove}}% {\gdef\EnPassantSquare{-}% \ExecutePieceMove}% \WhiteToMove% {\gdef\WhiteToMove{\False}}% {\gdef\WhiteToMove{\True}\addtocounter{move}{1}}}% {}% moves are not executed \printmove} \def\mainline{\begingroup\catcode`\#=12 \@mainline} % \def\@mainline#1{\endgroup\gdef\NumberNext{\True}% % \gdef\AfterBlack{\False}% % \gdef\PrintMoves{\True}% % \gdef\ExecuteMoves{\True}% % \gdef\StoreLastMove{\True}% % {\mainlinestyle\opencommands% % \Mainline(#1 Z )% % \closecommands}} % new version of @mainline \def\@mainline#1{\endgroup\gdef\NumberNext{\True}% \let\currentstyle=\mainlinestyle% \gdef\PrintMoves{\True}% \gdef\ExecuteMoves{\True}% \gdef\StoreLastMove{\True}% \@restoremainline% \runmoves{#1}% \@storemainline} \def\@restoremainline{% \@restoregame{skak.mainline.previous}% \@storegame{skak.temp.previous}% \@restoregame{skak.mainline}} \def\hidemoves{\begingroup\catcode`\#=12 \@hidemoves} % \def\@hidemoves#1{\endgroup\gdef\NumberNext{\True}% % \gdef\AfterBlack{\False}% % \gdef\PrintMoves{\False}% % \gdef\ExecuteMoves{\True}% % \gdef\StoreLastMove{\True}% just in case you want to refer to the last move. % {\relax@typesetting% % \Mainline(#1 Z )}} % new version af @hidemoves \def\@hidemoves#1{\endgroup\gdef\NumberNext{\True}% \gdef\PrintMoves{\False}% \gdef\ExecuteMoves{\True}% \gdef\StoreLastMove{\True}% just in case you want to refer to the last move. \let\currentstyle=\relax@typesetting% \@restoremainline% \runmoves{#1}% \@storemainline} \newcounter{helpnumber} \newcounter{helpnumberMove} \def\EatNumber#1{% \setcounter{helpnumberMove}{\arabic{move}}% \setcounter{helpnumber}{0}% \AfterBlack{\afterblack}{}% \gdef\AfterBlack{\True}% \beforenumber\EatNumberA(#1WXYZ)} \def\EatNumberA(#1.#2){% \PrintMoves{#1}{}% \ExecuteMoves% {\setcounter{helpnumber}{#1}% \ifthenelse{\value{helpnumberMove}=\value{helpnumber}}% {\LookForMove(.#2)}% sets \ExpectedColour and \CurrentMove {\errmessage{mainline: #1 is not the correct move number}}}% {\LookForMove(.#2)}% } \def\LookForMove(#1#2#3#4){% \EqStr{.}{#2}% ... after the move number {\blackopen% \gdef\AfterWhite{\False}% \gdef\ExpectedColour{\False}% \HandleMove(#4)}% {\whiteopen% \gdef\AfterWhite{\True}% \gdef\ExpectedColour{\True}% \HandleMove(#2#3#4)}}% \def\HandleMove(#1XYZ){% executes move if one is found \EqStr{W}{#1}% {\gdef\NumberNext{\False}}% {\StripMove(#1)}} \def\StripMove(#1W){% handles things like 1.e4 \@storegame{skak.temp.previous}% store the previous position % TO-DO: need a more effective way of going a move back. \MakeMoveMainline{#1}} % The tricky part! Has to integrate \typeset@A@move \def\MakeMoveMainline#1{% {\ExpectedColour% {\WhiteToMove% {\MakeMove{#1}% \gdef\ExpectedColour{\False}% \gdef\NumberNext{\False}}% {\errmessage{mainline: black, not white, to move (#1)}}}% {\WhiteToMove% {\errmessage{mainline: white, not black, to move (#1)}}% {\MakeMove{#1}\gdef\NumberNext{\True}}}}} \def\MakeMoveMainline#1{% \ExecuteMoves% {\ExpectedColour% {\WhiteToMove{}{\errmessage{mainline: black, not white, to move (#1)}}}% {\WhiteToMove{\errmessage{mainline: white, not black, to move (#1)}}{}}} {}% % regardless of the moves are executed or not: \ExpectedColour% {\beforewhite\MakeMove{#1}% \gdef\ExpectedColour{\False}% \gdef\NumberNext{\False}}% {\AfterWhite{\afterwhite}{}% \beforeblack\MakeMove{#1}\gdef\NumberNext{\True}}} % \def\Mainline(#1 #2){% % \EqStr{ }{#1}% % {\Mainline(#2)}% % {% % \EqStr{Z}{#1}% % {}% % {\NumberNext% % {\EatNumber{#1}% sets \NumberOK, \ExpectedColour % % executes a move not separated from the % % number with a space, eg, 1.e4 % %{\gdef\NumberNext{\False}\Mainline(#2)}% % %\gdef\NumberNext{\False}% % \Mainline(#2)}% % {\MakeMoveMainline{#1}% % \Mainline(#2)}}}} % New version for longmoves in variation \def\Mainline(#1 #2){% \EqStr{ }{#1}% {\Mainline(#2)}% {% \EqStr{Z}{#1}% {}% {\NumberNext% {\EatNumber{#1}% sets \NumberOK, \ExpectedColour % executes a move not separated from the % number with a space, eg, 1.e4 % {\gdef\NumberNext{\False}\Mainline(#2)}% %\gdef\NumberNext{\False}% \Mainline(#2)}% {\@storegame{skak.temp.previous}% store the previous position % TO-DO: need a more effective way of going a move back. \MakeMoveMainline{#1}% \Mainline(#2)}}}} %%%%% typesetting % depends on the info gathered by \ParseMove \def\printmove@san{% \EqPiece{Z}{\PieceNameToMove}% {\Castling% {\LongCastling{\castlingchar\castlinghyphen}{}% \castlingchar\castlinghyphen\castlingchar}% {%pawn move \Capture{\FileDiscriminator\capturesymbol}{}% \MoveToFile\MoveToRank% \Promotion{\cfss@textsymfigsymbol{\PromotionPieceName}}{}}}% {% piece move \cfss@textsymfigsymbol{\PieceNameToMove}% \EqStr{Z}{\FileDiscriminator}{}{\FileDiscriminator}% \EqStr{Z}{\RankDiscriminator}{}{\RankDiscriminator}% \Capture{\capturesymbol}{}% \MoveToFile\MoveToRank}% % for all moves: \CheckTest\MateTest\MoveRest} \DeclareRobustCommand{\movehyphen}{-} % depends on the info gathered by \ParseMove \def\printmove@algebraic{% \EqPiece{Z}{\PieceNameToMove}% {\Castling% {\LongCastling{\castlingchar\castlinghyphen}{}% \castlingchar\castlinghyphen\castlingchar}% {%pawn move \MoveFrom% \Capture{\capturesymbol}{\movehyphen}% \MoveToFile\MoveToRank% \Promotion{\cfss@textsymfigsymbol{\PromotionPieceName}}{}}}% {% piece move \cfss@textsymfigsymbol{\PieceNameToMove}% \MoveFrom% \Capture{\capturesymbol}{\movehyphen}% \MoveToFile\MoveToRank}% % for all moves: \CheckTest\MateTest\MoveRest} \def\longmoves{% \let\printmove=\printmove@algebraic} \def\shortmoves{% \let\printmove=\printmove@san} \shortmoves% this is default \def\relax@typesetting{% \let\opencommands=\relax \let\closecommands=\relax \let\whiteopen=\relax \let\blackopen=\relax \let\beforenumber=\relax \let\beforewhite=\relax \let\afterwhite=\relax \let\beforeblack=\relax \let\afterblack=\relax \let\printmove=\relax } \def\styleA@opencommands{} \def\styleA@closecommands{} \def\styleA@whiteopen{.} \def\styleA@blackopen{. -} \def\styleA@beforenumber{} \def\styleA@beforewhite{ } \def\styleA@afterwhite{} \def\styleA@beforeblack{, } \def\styleA@afterblack{ } \def\styleA{% \let\opencommands=\styleA@opencommands \let\closecommands=\styleA@closecommands \let\whiteopen=\styleA@whiteopen \let\blackopen=\styleA@blackopen \let\beforenumber=\styleA@beforenumber \let\beforewhite=\styleA@beforewhite \let\afterwhite=\styleA@afterwhite \let\beforeblack=\styleA@beforeblack \let\afterblack=\styleA@afterblack \leavestylec } \def\styleB@opencommands{} \def\styleB@closecommands{} \def\styleB@whiteopen{ } \def\styleB@blackopen{\ldots} \def\styleB@beforenumber{} \def\styleB@beforewhite{} \def\styleB@afterwhite{ } \def\styleB@beforeblack{} \def\styleB@afterblack{ } \def\styleB{% \let\opencommands=\styleB@opencommands \let\closecommands=\styleB@closecommands \let\whiteopen=\styleB@whiteopen \let\blackopen=\styleB@blackopen \let\beforenumber=\styleB@beforenumber \let\beforewhite=\styleB@beforewhite \let\afterwhite=\styleB@afterwhite \let\beforeblack=\styleB@beforeblack \let\afterblack=\styleB@afterblack \leavestylec } % avoiding problems with switch from styleC to other styles % problem reported by Joao Nabais \newcommand{\leavestylec}{% \styleC@on{\normalstyles}{\relax}% \def\styleC@on{\False}% } \def\styleC@opencommands{% \begin{tabbing}% \hspace{.2\linewidth}\=\hspace{.2\linewidth}\=% \hspace{.2\linewidth}\= \kill} \def\styleC@closecommands{\end{tabbing}} \def\styleC@whiteopen{} \def\styleC@blackopen{\>\ldots} \def\styleC@beforenumber{\>} \def\styleC@beforewhite{\>} \def\styleC@afterwhite{} \def\styleC@beforeblack{\>} \def\styleC@afterblack{\\} \def\styleC{% \let\opencommands=\styleC@opencommands% \let\closecommands=\styleC@closecommands% \let\whiteopen=\styleC@whiteopen% \let\blackopen=\styleC@blackopen% \let\beforenumber=\styleC@beforenumber% \let\beforewhite=\styleC@beforewhite% \let\afterwhite=\styleC@afterwhite% \let\beforeblack=\styleC@beforeblack% \let\afterblack=\styleC@afterblack% \def\mainlinestyle{\styleC\bfseries}% \def\variationstyle{\styleB}% \def\styleC@on{\True}% } \def\mainlinestyle{\bfseries}% could also contain % definitions of the % various style options \def\variationstyle{}% as with mainlinestyle %\typeset@number is isomorf with \EatNumber \def\typeset@number#1{\TypeSetAfterBlack{\afterblack}{}% \gdef\TypeSetAfterBlack{\True}% \beforenumber\typeset@numberA(#1WXYZ)}% 22: -> 22\?open \def\typeset@numberA(#1.#2){% #1\typeset@numberHandlePeriods(.#2)} \def\typeset@numberHandlePeriods(#1#2#3#4){% \EqStr{.}{#2}% ... after the number {\blackopen\gdef\TypeSetColour{\False}\gdef\TypeSetAfterWhite{\False}% \typeset@numberHandleMove(#4)}% {\whiteopen\gdef\TypeSetColour{\True}\gdef\TypeSetAfterWhite{\True}% \typeset@numberHandleMove(#2#3#4)}} \def\typeset@numberHandleMove(#1XYZ){% \EqStr{W}{#1}% {\gdef\TypeSetNumberNext{\False}}% HERE {\typeset@numberStripMove(#1)}} \def\typeset@numberStripMove(#1W){% \typeset@A@move{#1}} \def\typeset@A@move#1{% \TypeSetColour% {\beforewhite\mbox{\typeset@A@moveA(#1Z)}% \gdef\TypeSetColour{\False}% \gdef\TypeSetNumberNext{\False}}% addition {\TypeSetAfterWhite{\afterwhite}{}% \beforeblack\mbox{\typeset@A@moveA(#1Z)}% \gdef\TypeSetColour{\True}\gdef\TypeSetNumberNext{\True}}} \def\typeset@A@moveA(#1#2){% \EqStr{Z}{#1}% {}% {\IsPieceName{#1}% {\xdef\temp@piece{\skak@pieceToEnglish{#1}}% \expandafter\cfss@textsymfigsymbol\temp@piece}% {\EqStr{=}{#1}% {}% {\EqStr{x}{#1}% {\capturesymbol}% %%changed UF {\EqStr{+}{#1}% {\checksymbol}% was "\ensuremath{\dagger}" before {\EqStr{-}{#1}% {\LastCharWasCastle {\castlinghyphen}% %%changed UF, dash from Textfont short dash for castlings {\hbox{--}}}% longer dash for moves {\EqStr{O}{#1}% {\gdef\LastCharWasCastle{\True}% \castlingchar}% %% UF added to be able to change from O to 0 {\gdef\LastCharWasCastle{\False}% \EqStr{##}{#1}%added 2004.04.14 for \mate {\mate} {#1}}}}}}}% \typeset@A@moveA(#2)}} \def\typeset@A#1{\gdef\TypeSetNumberNext{\True}% \gdef\TypeSetAfterBlack{\False}\opencommands\typeset@AA(#1 Z )% \closecommands} % \typeset@AA is isomorf with \Mainline \def\typeset@AA(#1 #2){% \EqStr{ }{#1}% {\typeset@AA(#2)}% {\EqStr{Z}{#1}% {}% {\TypeSetNumberNext% {\typeset@number{#1}% sets \TypeSetColour % \gdef\TypeSetNumberNext{\False}% \typeset@AA(#2)}% {\typeset@A@move{#1}% \typeset@AA(#2)}}}} % \typeset@cmoves and \typeset@comment added by db <2002-01-06> \def\movewhite{ } \def\typeset@cmoves(#1 #2){% \EqStr{ }{#1}% {\typeset@cmoves(#2)}% {\EqStr{Y}{#1}% {}% {\typeset@A@moveA(#1Z)\movewhite\typeset@cmoves(#2)}}} \def\typeset@comment#1{\opencommands\typeset@cmoves(#1 Y )% \closecommands} %\def\variation{\begingroup\catcode`\#=12 \@variation} \DeclareRobustCommand{\variation}{\begingroup\catcode`\#=12 \@variation} %\def\@variation#1{\endgroup{\variationstyle\typeset@A{#1}}} \DeclareRobustCommand{\variationcurrent}{\begingroup\catcode`\#=12 \@variationcurrent} \DeclareRobustCommand{\continuevariation}{\begingroup\catcode`\#=12 \@continuevariation} \DeclareRobustCommand{\continuevariationcurrent}{\begingroup\catcode`\#=12 \@continuevariationcurrent} % \def\@variation#1{\endgroup\gdef\NumberNext{\True}% % \gdef\AfterBlack{\False}% % \gdef\PrintMoves{\True}% % \gdef\ExecuteMoves{\False}% % \gdef\StoreLastMove{\False}% % {\variationstyle\opencommands% % \Mainline(#1 Z )% % \closecommands}} % new version of \@variation \def\@variation#1{\endgroup% \let\currentstyle=\variationstyle% \gdef\PrintMoves{\True}% \gdef\ExecuteMoves{\True}% \gdef\StoreLastMove{\False}% \@restoregame{skak.mainline.previous}% roll-back of last move. \runmoves{#1}% \storegame{skak.variation}\@restoremainline} % \def\@storevariationdata{% % \storegame{skak.variation}% % \restoregame{skak.temp.previous}% % \storegame{skak.variation.previous}} \def\@storemainline{% Only to be called after executing moves in \@mainline % or in \@hidemoves! \@storegame{skak.mainline}% \@restoregame{skak.temp.previous}% \@storegame{skak.mainline.previous}% \@restoregame{skak.mainline}} \def\@variationcurrent#1{\endgroup% \let\currentstyle=\variationstyle% \gdef\PrintMoves{\True}% \gdef\ExecuteMoves{\True}% \gdef\StoreLastMove{\False}% \@restoregame{skak.mainline}% \runmoves{#1}% \storegame{skak.variation}\@restoremainline} \def\@continuevariation#1{\endgroup% \let\currentstyle=\variationstyle% \gdef\PrintMoves{\True}% \gdef\ExecuteMoves{\True}% \gdef\StoreLastMove{\False}% \@restoregame{skak.variation.previous}% roll-back of last move. \runmoves{#1}% \storegame{skak.variation}\@restoremainline} \def\@continuevariationcurrent#1{\endgroup% \let\currentstyle=\variationstyle% \gdef\PrintMoves{\True}% \gdef\ExecuteMoves{\True}% \gdef\StoreLastMove{\False}% \@restoregame{skak.variation}% \runmoves{#1}% \storegame{skak.variation}\@restoremainline} % \runmoves is common to \variation, \mainline and \hidemoves \newcommand\runmoves[1]{% \gdef\NumberNext{\True}% \gdef\AfterBlack{\False}% {\currentstyle\opencommands% \Mainline(#1 Z )% \closecommands}} % typesetting moves without move number \def\wmove{\begingroup\catcode`\#=12 \@wmove} \def\@wmove#1{\endgroup{\variationstyle\typeset@A@moveA(#1Z)}} \def\bmove{\begingroup\catcode`\#=12 \@bmove} \def\@bmove#1{\endgroup{\variationstyle\ldots\typeset@A@moveA(#1Z)}} % \movecomment added by db <2002-01-06> \def\movecomment{\begingroup\catcode`\#=12 \@movecomment} \def\@movecomment#1{\endgroup{\variationstyle\typeset@comment{#1}}} %%% % printing of the board \newlength{\squarelength} %% Multiplier for the special PS markers, see set@special@psmarkers \newcount\square@multiplier \newlength{\ranklift} %%% 2004.04.09 UF: removed pt so bigger board are possible %%% 2004.04.05 UF: group around the font-changing-command %%% UF 2005.03.24 changes to use chessfss size changing commands \def\setup@showboard{% UF 2005.03.24 don't need argument. Sizes should be set before. \settowidth\squarelength{\BlackEmptySquare}% \square@multiplier=\squarelength% in sp \divide\square@multiplier by 65536% in pt % ps setup \ps@on{\psset{unit=\the\squarelength}}{} %% put a group around font-changing-command UF: {\sidefont\setlength{\@tempdima}{.5\squarelength-0.8ex} \xdef\aftergrouplength{\the\@tempdima}% \aftergroup\setlength\aftergroup\ranklift% \aftergroup{\aftergroup\aftergrouplength\aftergroup}}} \def\tinyboard{\cfss@setupboardsize{10pt}{6pt}\setup@showboard} \def\smallboard{\cfss@setupboardsize{15pt}{8pt}\setup@showboard} \def\normalboard{\cfss@setupboardsize{20pt}{10pt}\setup@showboard} \def\largeboard{\cfss@setupboardsize{30pt}{12pt}\setup@showboard} %new 2005.06.29 UF \newcommand\setupboard[2]{% \cfss@setupboardsize{#1}{#2}%#1 board, #2 notation \setup@showboard} % the default \normalboard \def\ToggleWhiteSquare{% \WhiteSquare{\def\WhiteSquare{\False}}{\def\WhiteSquare{\True}}} %\def\WhiteSquarePiece#1{% % \EqPiece{E}{#1}{0}{#1}} % getting around deficiencies in some fonts \def\WhiteSquarePiece#1{% \EqPiece{E}{#1}{\WhiteEmptySquare}{#1}} % for fonts without an empty square one can use %\renewcommand\WhiteEmptySquare}{{\rule{\squarelength}{0pt}}} \def\BlackSquarePiece#1{% \EqPiece{E}{#1}{Z}% {\EqPiece{P}{#1}{O}% {\EqPiece{p}{#1}{o}% {\EqPiece{R}{#1}{S}% {\EqPiece{r}{#1}{s}% {\EqPiece{N}{#1}{M}% {\EqPiece{n}{#1}{m}% {\EqPiece{B}{#1}{A}% {\EqPiece{b}{#1}{a}% {\EqPiece{Q}{#1}{L}% {\EqPiece{q}{#1}{l}% {\EqPiece{K}{#1}{J}{j}}}}}}}}}}}}} \def\FilterShowOnly#1{% piece -> piece, shows only the pieces in % ShowOnlyList \Member{\EqStr}{#1}{\ShowOnlyList}% {#1}{E}} \def\Showchar#1{% square -> drawn square \WhiteSquare% {\WhiteSquarePiece{\Compose\FilterShowOnly\Get{#1}}}% {\BlackSquarePiece{\Compose\FilterShowOnly\Get{#1}}}% \ToggleWhiteSquare} \def\Showrank#1{% rank -> drawn rank \boardfont\Apply{\Showchar}{\Rank{#1}}% \ifnum#1=1\ps@on{\pnode(-.5,.5){BM}}{}\fi} \def\ShowrankInverse#1{% rank -> drawn rank \boardfont\Apply{\Showchar}{\Reverse{\Rank{#1}}}% \ifnum#1=8\ps@on{\pnode(-.5,.5){BM}}{}\fi} \def\ShowMoverWhiteNormal{\pscustom{\skak@translate{h}{1}% \psline{->}(1,0.25)(1,0.8)% \psframe(0.84,-0.16)(1.16,0.16)}} \def\ShowMoverBlackNormal{% \pscustom[fillstyle=solid,fillcolor=gray]{\skak@translate{h}{8}% \psline{->}(1,-0.25)(1,-0.8)% \psframe(0.84,-0.16)(1.16,0.16)}} \def\ShowMoverWhiteInverse{\pscustom{\skak@translate{a}{1}% \psline{->}(1,-0.25)(1,-0.8)% \psframe(0.84,-0.16)(1.16,0.16)}} \def\ShowMoverBlackInverse{% \pscustom[fillstyle=solid,fillcolor=gray]{\skak@translate{a}{8}% \psline{->}(1,0.25)(1,0.8)% \psframe(0.84,-0.16)(1.16,0.16)}} \def\show@board{% \def\WhiteSquare{\True}% \leavevmode% \vbox{\offinterlineskip% \hrule height1pt% \hbox{\vrule width1pt% \vbox{\hbox{\Showrank{8}}\ToggleWhiteSquare% \hbox{\Showrank{7}}\ToggleWhiteSquare% \hbox{\Showrank{6}}\ToggleWhiteSquare% \hbox{\Showrank{5}}\ToggleWhiteSquare% \hbox{\Showrank{4}}\ToggleWhiteSquare% \hbox{\Showrank{3}}\ToggleWhiteSquare% \hbox{\Showrank{2}}\ToggleWhiteSquare% \hbox{\Showrank{1}}}% \vrule width1pt}% \hrule height1pt}% \setcounter{ps@inverse}{0}% \ShowMover% {\WhiteToMove% {\ShowMoverWhiteNormal}% {\ShowMoverBlackNormal}}% {}% } \def\show@board@inverse{% \leavevmode% \def\WhiteSquare{\True}% \vbox{\offinterlineskip% \hrule height1pt% \hbox{\vrule width1pt% \vbox{\hbox{\ShowrankInverse{1}}\ToggleWhiteSquare% \hbox{\ShowrankInverse{2}}\ToggleWhiteSquare% \hbox{\ShowrankInverse{3}}\ToggleWhiteSquare% \hbox{\ShowrankInverse{4}}\ToggleWhiteSquare% \hbox{\ShowrankInverse{5}}\ToggleWhiteSquare% \hbox{\ShowrankInverse{6}}\ToggleWhiteSquare% \hbox{\ShowrankInverse{7}}\ToggleWhiteSquare% \hbox{\ShowrankInverse{8}}}% \vrule width1pt}% \hrule height1pt}% \setcounter{ps@inverse}{180}% \ShowMover% {\WhiteToMove% {\ShowMoverWhiteInverse}% {\ShowMoverBlackInverse}}% {}% } \def\ShowrankNumber#1{% \makebox[0pt][r]{% \raisebox{\ranklift}[0cm][0cm]{% \makebox[\squarelength][r]{\sidefont#1\hspace*{.1\squarelength}}}}} \def\ShowrankWithNumber#1{\ShowrankNumber{#1}% \vrule width1pt \Showrank{#1}\vrule width1pt} \def\ShowrankInverseWithNumber#1{\ShowrankNumber{#1}% \vrule width1pt\ShowrankInverse{#1}\vrule width1pt} \def\Showfile#1{\hbox to \squarelength{\hfil\sidefont#1\hfil}} \def\Showfiles{\hfil\Showfile{a}\Showfile{b}\Showfile{c}\Showfile{d}% \Showfile{e}\Showfile{f}\Showfile{g}\Showfile{h}\hfil} \def\Showfiles@inverse{\hfil\Showfile{h}\Showfile{g}\Showfile{f}\Showfile{e}% \Showfile{d}\Showfile{c}\Showfile{b}\Showfile{a}\hfil} %%% changed \def\show@board@notation{% \def\WhiteSquare{\True}% \leavevmode% \vbox{\offinterlineskip% \hrule height1pt% \hbox{\ShowrankWithNumber{8}}\ToggleWhiteSquare% \hbox{\ShowrankWithNumber{7}}\ToggleWhiteSquare% \hbox{\ShowrankWithNumber{6}}\ToggleWhiteSquare% \hbox{\ShowrankWithNumber{5}}\ToggleWhiteSquare% \hbox{\ShowrankWithNumber{4}}\ToggleWhiteSquare% \hbox{\ShowrankWithNumber{3}}\ToggleWhiteSquare% \hbox{\ShowrankWithNumber{2}}\ToggleWhiteSquare% \hbox{\ShowrankWithNumber{1}}\ToggleWhiteSquare% \hrule height1pt% \vspace*{.1\squarelength}% \hbox{\Showfiles}}% \setcounter{ps@inverse}{0}% \ShowMover% {\WhiteToMove% {\ShowMoverWhiteNormal}% {\ShowMoverBlackNormal}}% {}% } \def\show@board@notation@inverse{% \def\WhiteSquare{\True}% \leavevmode%\rule{\squarelength}{0pt}%\hspace*{-\squarelength}% \vbox{\offinterlineskip% \hrule height1pt% \hbox{\ShowrankInverseWithNumber{1}}\ToggleWhiteSquare% \hbox{\ShowrankInverseWithNumber{2}}\ToggleWhiteSquare% \hbox{\ShowrankInverseWithNumber{3}}\ToggleWhiteSquare% \hbox{\ShowrankInverseWithNumber{4}}\ToggleWhiteSquare% \hbox{\ShowrankInverseWithNumber{5}}\ToggleWhiteSquare% \hbox{\ShowrankInverseWithNumber{6}}\ToggleWhiteSquare% \hbox{\ShowrankInverseWithNumber{7}}\ToggleWhiteSquare% \hbox{\ShowrankInverseWithNumber{8}}\ToggleWhiteSquare% \hrule height1pt% \vspace*{.1\squarelength}% \hbox{\Showfiles@inverse}}% \setcounter{ps@inverse}{180}% \ShowMover% {\WhiteToMove% {\ShowMoverWhiteInverse}% {\ShowMoverBlackInverse}}% {}% } % on the fly configuration \def\notationOn{\let\showboard=\show@board@notation% \let\showinverseboard=\show@board@notation@inverse} \def\notationOff{\let\showboard=\show@board% \let\showinverseboard=\show@board@inverse} \def\notationon{\notationOn} \def\notationoff{\notationOff} \def\showmoverOn{\def\ShowMover{\True}} \def\showmoverOff{\def\ShowMover{\False}} \def\showmoveron{\showmoverOn} \def\showmoveroff{\showmoverOff} \def\newgame{% \fenboard{rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1}} % Stores the initial boards for board manipulation. \def\@initstorage{% \@storegame{skak.mainline}% \@storegame{skak.mainline.previous}% no previous move for starters. \@storegame{skak.temp.previous}} %%%% storing and loading of games \newtoks\store@toks \def\savegame#1{% writes the board as fen to #1.fen \newwrite\skakstore% \immediate\openout\skakstore=#1.fen% \Fen@calculate% \immediate\write\skakstore{\temp@board}% \immediate\closeout\skakstore} \def\savegame#1{% writes the board as fen to #1.fen \immediate\openout0=#1.fen% \Fen@calculate% \immediate\write0{\temp@board}% \immediate\closeout0} % loading a board from a fen file is also possible % the file #1.fen should contain nothing but a fen of % a game \def\loadgame#1{% \def\load@read{}% \newread\load@in% \openin\load@in=#1.fen\relax% \read\load@in to \load@read% \closein\load@in% \expandafter\FenBoard\load@read)} %%% temporary storing of a game position, without resorting to files % \def\storegame#1{\Fen@calculate% % \def#1{\temp@board}} % \def\restoregame#1{\expandafter\FenBoard#1)} \def\@storegame#1{\Fen@calculate% \expandafter\xdef\csname chessgame.#1\endcsname{\temp@board}} \def\@restoregame#1{% \edef\restore@temp{\csname chessgame.#1\endcsname}% \expandafter\FenBoard\restore@temp)} \let\mystore=\@storegame \let\myrestore=\@restoregame \def\storegame#1{% \@storegame{#1}% \@restoregame{skak.temp.previous}% \@storegame{#1.previous}% \@restoregame{#1}} \def\restoregame#1{% \@restoregame{#1.previous}% \@storegame{skak.temp.previous}% \@storegame{skak.mainline.previous}% \@restoregame{#1}% \@storegame{skak.mainline}} % end skak.sty