]> git.lyx.org Git - lyx.git/blob - lib/tex/lyxskak.sty
two patches from John, and a moving math panel
[lyx.git] / lib / tex / lyxskak.sty
1 % based on skak.sty
2 % modified to work with older babel versions
3 \NeedsTeXFormat{LaTeX2e}
4 \ProvidesPackage{lyxskak}
5
6 \DeclareOption{tiny}{\AtEndOfClass{\tinyboard}}
7 \DeclareOption{small}{\AtEndOfClass{\smallboard}}
8 \DeclareOption{normal}{\AtEndOfClass{\normalboard}}
9 \DeclareOption{large}{\AtEndOfClass{\largeboard}}
10 \DeclareOption{notation}{\AtEndOfClass{\notationOn}}
11 \DeclareOption{mover}{\AtEndOfClass{\showmoverOn}}
12 \DeclareOption{moveroff}{\AtEndOfClass{\showmoverOff}}
13 \DeclareOption{notationoff}{\AtEndOfClass{\notationOff}}
14 \DeclareOption{ps}{\def\ps@on{\True}}
15 \DeclareOption{psoff}{\def\ps@on{\False}}
16 \DeclareOption{english}{\AtEndOfClass{\skaklanguage[english]}}
17 \DeclareOption{styleA}{\AtEndOfClass{\styleA}}
18 \DeclareOption{styleB}{\AtEndOfClass{\styleB}}
19 \ExecuteOptions{notation,normal,psoff,english,moveroff,styleB}
20 \ProcessOptions
21 %\AtBeginDocument{\skaklanguage{english}}
22
23 \RequirePackage{lambda,ifthen,calc}
24 % Now, we rename the ifthenelse here as skak@ifthenelse and then use that
25 % this is to co-exist with older babel.sty that redefine ifthenelse!
26 \let\skak@ifthenelse\ifthenelse
27 \ps@on{\RequirePackage{pstricks,pst-node}\SpecialCoor%
28   \newpsstyle{psskak}{arrowinset=0,nodesep=.25,armA=.75,arrowsize=.2 1,
29     linearc=.2,arrowlength=1.25,linewidth=0.04,
30     doubleline=true,doublesep=.06}}{}
31
32
33
34 % list related functions
35 \def\IsNil#1{#1{\False}{\True}}
36
37 \def\Member#1#2#3% ('a -> 'a -> bool) -> 'a -> 'a list -> bool
38   {#3{\MemberA{#1}{#2}}{\False}}
39 \def\MemberA#1#2#3#4%
40    {#1{#2}{#3}%
41      {\True}%
42      {\Member{#1}{#2}{#4}}} 
43
44 % Explode: string -> char list
45 \def\Explode#1{\EqStr{Z}{#1}{\Nil}{\ExplodeA#1Z}}
46 \def\ExplodeA#1#2Z{\EqStr{Z}{#2}%
47   {\Singleton{#1}}%
48   {\Cons{#1}{\ExplodeA#2Z}}}
49
50 \def\BoolToString#1{% bool -> string
51 #1{True}{False}}
52
53 % the basic manipulation of the board
54 \def\Set#1#2{% square -> piece -> unit 
55 \expandafter\xdef\csname#1\endcsname{#2}}
56 \def\Get#1{% square -> piece
57 \csname#1\endcsname}
58
59 \def\StoreBool#1#2{%
60   \expandafter\def\csname#1\endcsname{#2}}
61 \def\GetBool#1{%
62   \csname#1\endcsname}
63
64
65 \def\PieceNames{\Listize[K,Q,R,B,N]}
66 \def\FileNames{\Listize[a,b,c,d,e,f,g,h]}
67 \def\RankNames{\Listize[1,2,3,4,5,6,7,8]}
68
69 %% what pieces to show
70 %\def\ShowOnlyList{\Listize[K,Q,R,B,N,P,k,q,r,b,n,p]}
71
72 \def\showonly#1{\expandafter\def\csname ShowOnlyList\endcsname{\Listize[#1]}}
73 \def\showall{\showonly{K,Q,R,B,N,P,k,q,r,b,n,p}}
74 \showall
75
76 \def\showonlywhite{\showonly{K,Q,R,B,N,P}}
77 \def\showonlyblack{\showonly{k,q,r,b,n,p}}
78 \def\showonlypawns{\showonly{p,P}}
79
80 %%%
81 \def\TeXifx#1#2#3%
82    {#1\def\next{#2}\else\def\next{#3}\fi
83     \next}
84 \def\EqStr#1#2{% % has to be changed
85   \TeXif{\if#1#2}}
86 \def\EqPiece#1#2{\TeXif{\if#1#2}}
87
88
89 \def\RankOf(#1){\Second{#1}}
90 \def\FileOf(#1){\First{#1}}
91
92 \def\EqSquare#1#2{%
93   \skak@ifthenelse{\equal{#1}{#2}}{\True}{\False}}
94
95 %% is this really necessary????
96 \def\MySecond(#1#2){#2}
97 \def\MyFirst(#1#2){#1}
98
99 \def\MyEqual#1#2{% string -> string -> bool
100   \xdef\arga{#1}\xdef\argb{#2}%
101   \TeXif{\ifx\arga\argb }}
102 %  \skak@ifthenelse{\equal{#1}{#2}}{\True}{\False}}
103
104 \def\MyEqualB#1#2#3#4{%
105   \skak@ifthenelse{\equal{#1}{#2}}{#3}{#4}}
106
107 \def\myrightfile#1#2{% filediscriminator -> square -> bool
108   \Member{\MyEqual}{#2}{\File{#1}}}
109
110 \def\RightRank(#1){%square -> bool
111   \EqStr{\RankDiscriminator}{Z}%
112   {\True}%
113 %  {\EqStr{\RankDiscriminator}{\Second{#1}}}}
114 %  {\expandafter\EqStr{\RankDiscriminator}{\MySecond(#1)}}}
115   {\Member{\MyEqual}{#1}{\Rank{\RankDiscriminator}}}}
116 \def\RightFile(#1){%square -> bool
117   \EqStr{\FileDiscriminator}{Z}%
118   {\True}%
119   {\Member{\MyEqual}{#1}{\File{\FileDiscriminator}}}}
120
121 %  {\myrightfile{\FileDiscriminator}{#1}}}
122
123 %  {\expandafter\EqStr{\FileDiscriminator}{\FileOf(#1)}}}
124 %    {\edef\myhelper{\MyFirst(#1)}\Unlistize{\Explode{#1Z}}%
125 %     (rf-test\myhelper)\EqStr{\FileDiscriminator}{\myhelper}}}
126 %%  {(rf-test)\EqStr{\FileDiscriminator}{\MyFirst(#1)}}}
127
128
129 \def\Glue#1#2% 'a -> 'b -> 'ab , eg. a -> 1 -> a1
130 {#1#2}
131
132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133 %%%%% adding ornaments to a board %%%%%%%%%%%%%%%%%%%
134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135 % usefull when adding ps arrows:
136 % set@fileangle: from -> to -> angle -> unit
137 \def\set@fileangle#1#2#3{%
138   \expandafter\xdef\csname fileangle.#1.#2\endcsname{#3}}
139 \def\get@fileangle#1#2{\ifx\csname fileangle.#1.#2\endcsname\relax
140   \errmessage{Files #1 and #2 does not belong to a valid knight move}%
141   \else \csname fileangle.#1.#2\endcsname\fi}
142 \def\set@rankangle#1#2#3{%
143   \expandafter\xdef\csname rankangle.#1.#2\endcsname{#3}}
144 \def\get@rankangle#1#2{\ifx\csname rankangle.#1.#2\endcsname\relax%
145   \errmessage{Ranks #1 and #2 does not belong to a valid knight move}%
146   \else \csname rankangle.#1.#2\endcsname\fi}
147
148 \def\testfileangle{fileangles:\get@fileangle{a}{b},\get@fileangle{h}{f}}
149 \def\testrankangle{rankangles:\get@rankangle{1}{3},\get@rankangle{4}{5}}
150
151 % a file to ...
152 \set@fileangle{a}{b}{0}\set@fileangle{a}{c}{0}
153 % b file to ...
154 \set@fileangle{b}{a}{0}\set@fileangle{b}{c}{0}\set@fileangle{b}{d}{0}
155 % c file to ...
156 \set@fileangle{c}{a}{180}\set@fileangle{c}{b}{0}
157 \set@fileangle{c}{d}{0}\set@fileangle{c}{e}{0}
158 % d file to ...
159 \set@fileangle{d}{b}{180}\set@fileangle{d}{c}{0}
160 \set@fileangle{d}{e}{0}\set@fileangle{d}{f}{0}
161 % e file to ...
162 \set@fileangle{e}{c}{180}\set@fileangle{e}{d}{0}
163 \set@fileangle{e}{f}{0}\set@fileangle{e}{g}{0}
164 % f file to ...
165 \set@fileangle{f}{d}{180}\set@fileangle{f}{e}{0}
166 \set@fileangle{f}{g}{0}\set@fileangle{f}{h}{0}
167 % g file to ...
168 \set@fileangle{g}{e}{180}\set@fileangle{g}{f}{0}\set@fileangle{g}{h}{0}
169 % h file to ...
170 \set@fileangle{h}{f}{180}\set@fileangle{h}{g}{0}
171
172 % 1st rank to ...
173 \set@rankangle{1}{2}{0}\set@rankangle{1}{3}{90}
174 % 2nd rank to ...
175 \set@rankangle{2}{1}{0}\set@rankangle{2}{3}{0}\set@rankangle{2}{4}{90}
176 % 3rd rank to ...
177 \set@rankangle{3}{1}{270}\set@rankangle{3}{2}{0}
178 \set@rankangle{3}{4}{0}\set@rankangle{3}{5}{90}
179 % 4th rank to ...
180 \set@rankangle{4}{2}{270}\set@rankangle{4}{3}{0}
181 \set@rankangle{4}{5}{0}\set@rankangle{4}{6}{90}
182 % 5th rank to ...
183 \set@rankangle{5}{3}{270}\set@rankangle{5}{4}{0}
184 \set@rankangle{5}{6}{0}\set@rankangle{5}{7}{90}
185 % 6th rank to ...
186 \set@rankangle{6}{4}{270}\set@rankangle{6}{5}{0}
187 \set@rankangle{6}{7}{0}\set@rankangle{6}{8}{90}
188 % 7th rank to ...
189 \set@rankangle{7}{5}{270}\set@rankangle{7}{6}{0}\set@rankangle{7}{8}{0}
190 % 8th rank to ...
191 \set@rankangle{8}{6}{270}\set@rankangle{8}{7}{0}
192
193 % PSTricks addon that allows hollow arrowheads
194 \ps@on{%
195 \edef\pst@arrowtable{\pst@arrowtable,<|-|>}
196 \def\tx@ArrowTriangleA{ArrowTriangleA }
197 \def\tx@ArrowTriangleB{ArrowTriangleB }
198 \@namedef{psas@|>}{% 
199   /ArrowTriangleA { CLW dup 3.5 div SLW mul add dup 2 div /w ED mul dup 
200     /h ED mul /a ED 
201     0 h a sub moveto w h L 0 0 L w neg h L 0 h a sub L 
202     gsave 1 setgray fill grestore gsave
203     stroke grestore } def 
204   \psk@arrowinset \psk@arrowlength \psk@arrowsize
205   \tx@ArrowTriangleA}
206 \@namedef{psas@<|}{%
207   /ArrowTriangle { CLW dup 2 div SLW mul add dup 2 div 
208     /w ED mul dup /h ED mul /a ED 
209     { 0 h T 1 -1 scale } if w neg h moveto 0 0 L w h L w neg a neg
210     rlineto w neg a rlineto w 0 rmoveto gsave stroke grestore } def 
211   true \psk@arrowinset \psk@arrowlength \psk@arrowsize
212   \tx@ArrowTriangleB}
213 % end of PSTricks addon
214 }
215 {}
216
217 \newcounter{ps@knightangle} \newcounter{ps@inverse}
218 \def\printknightmove#1#2{% 
219   \setcounter{ps@knightangle}{\get@fileangle{\First#1}{\First#2}+%
220     \get@rankangle{\Second#1}{\Second#2} + \value{ps@inverse}}%
221   \ncdiagg[style=psskak,angleA=\arabic{ps@knightangle}]{-|>}{#1}{#2}}
222  
223 \def\printarrow#1#2{\ncline[style=psskak]{-|>}{#1}{#2}}
224
225 \def\ps@highlightsquare#1{%
226   \pscustom[linewidth=.06]{\translate(#1)\psframe(-.5,-.5)(.5,.5)}}
227
228 \def\highlight#1{% comma separated list eg, \highlight{a1,b4,d4}
229   \Apply{\ps@highlightsquare}{\Listize[#1]}}
230 %%%%% end of adding ornaments to a board %%%%%%%%%%%%%%%%%%%%%%%%
231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232
233
234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235 %%%%% support for other languages %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237 % \uc@king queen rook bishop knight pawn holds the letters
238 % representinng the pieces in the current language
239 % \skak@currentPieceNames : char list, holds the current piece names
240 % \def\skak@pieceToEnglish#1{% string -> string, (pgn(curr. lang) -> pgn(eng))
241 %   \skak@piece@toEnglish(#1Z)}
242 \def\skak@piece@toEnglish#1{%
243   \EqPiece{#1}{\uc@king}%
244   {K}%
245   {\EqPiece{#1}{\uc@queen}%
246     {Q}%
247     {\EqPiece{#1}{\uc@rook}%
248       {R}%
249       {\EqPiece{#1}{\uc@bishop}%
250         {B}%
251         {\EqPiece{#1}{\uc@knight}%
252           {N}%
253           {\errmessage{not a valid piece name in the current language:#1}}}}}}}
254 %   \EqPiece{Z}{#2}%
255 %   {}% done
256 %   {\skak@pgn@toEnglish(#2)}}
257
258 \def\skak@englishToEnglish#1{#1}
259
260 \def\skak@definepieces#1#2#3#4#5#6{%
261   \edef\uc@king{#1}
262   \edef\uc@queen{#2}
263   \edef\uc@rook{#3}
264   \edef\uc@bishop{#4}
265   \edef\uc@knight{#5}
266   \edef\uc@pawn{#6}}
267
268 \def\newskaklanguage#1#2{%
269   \expandafter\xdef\csname skaklanguage.#1\endcsname{#2}}
270
271 \newcommand{\skaklanguage}[1][english]{%
272 %\def\skaklanguage#1{%
273   \def\currentlanguage{#1}%
274   \skak@ifthenelse{\equal{#1}{english}}%
275     {\let\skak@pieceToEnglish=\skak@englishToEnglish%
276       \def\PieceNames{\Listize[K,Q,R,B,N]}}
277     {\edef\temp@lang{\csname skaklanguage.#1\endcsname}
278       \expandafter\skak@definepieces\temp@lang%
279       \let\skak@pieceToEnglish=\skak@piece@toEnglish%
280       \def\PieceNames{%
281         \Listize[\uc@king,\uc@queen,\uc@rook,\uc@bishop,\uc@knight]}}}
282
283   
284 \def\showskaklanguage{%
285   (\uc@king)(\uc@queen)(\uc@rook)(\uc@bishop)(\uc@knight)(\uc@pawn)}
286
287 %%%%% end of language support %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289
290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291 %%%%% parsing macros %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293 \def\IsPieceName#1{\Member{\EqPiece}{#1}\PieceNames}
294 \def\IsFile#1% char -> bool
295 {\Member{\EqStr}{#1}\FileNames}
296 \def\IsRank#1% char -> bool
297 {\Member{\EqStr}{#1}\RankNames}
298 \def\IsCapture#1% char -> bool
299 {\EqStr{#1}{x}}
300 \def\IsPromotion#1% char -> bool
301 {\EqStr{#1}{=}}
302 \def\IsDash#1% char -> bool
303 {\EqStr{#1}{-}}
304 \def\IsO#1% char -> bool
305 {\EqStr{#1}{O}}
306
307 \def\File#1% file -> square list, eg. a -> [a1,a2,...,a8]
308 {\Map{\Glue{#1}}{\RankNames}} 
309 \def\Rank#1% rank -> square list, eg. 1 -> [a1,b1,...,h1]
310 {\Map{\Twiddle\Glue{#1}}{\FileNames}}
311
312
313 % Compose: ('b -> 'c) -> ('a -> 'b) -> ('a -> c')
314 % Second:  'a -> 'b  -> 'b
315 % f: 'a -> unit
316 % Compose Second f: 'a -> ('a -> 'b -> unit)    
317 % \def\Apply#1#2% ('a -> unit) -> ('a list -> unit)
318 % {\Force{\Map{#1}{#2}}}
319 % \def\Force#1{#1\ForceA{}}
320 % \def\ForceA#1{#1\Foldr\DoIt{}}
321 % \def\DoIt#1#2{#1#2}
322
323 \def\Sideeffect#1#2#3{% ('a -> unit) -> ('a -> 'b -> unit)
324   #1{#2}#3}
325
326 \def\Apply#1#2{% ('a -> unit)  -> 'a list -> unit
327   \Foldr{\Sideeffect{#1}}{\relax}{#2}}
328
329
330 \def\EmptyBoard%
331 {\Apply{\Twiddle\Set{E}}{\Rank{1}}
332 \Apply{\Twiddle\Set{E}}{\Rank{2}}
333 \Apply{\Twiddle\Set{E}}{\Rank{3}}
334 \Apply{\Twiddle\Set{E}}{\Rank{4}}
335 \Apply{\Twiddle\Set{E}}{\Rank{5}}
336 \Apply{\Twiddle\Set{E}}{\Rank{6}}
337 \Apply{\Twiddle\Set{E}}{\Rank{7}}
338 \Apply{\Twiddle\Set{E}}{\Rank{8}}}
339
340
341 \def\FenConvert#1{%
342   \EqStr{8}{#1}%
343   {EEEEEEEE}%
344   {\EqStr{7}{#1}%
345     {EEEEEEE}%
346     {\EqStr{6}{#1}%
347       {EEEEEE}%
348       {\EqStr{5}{#1}%
349         {EEEEE}%
350         {\EqStr{4}{#1}%
351           {EEEE}%
352           {\EqStr{3}{#1}%
353             {EEE}%
354             {\EqStr{2}{#1}%
355               {EE}%
356               {\EqStr{1}{#1}%
357                 {E}%
358                 {#1}}}}}}}}}
359        
360
361 \def\ParseFenRank#1{\ParseFenRankA(#1Z)}
362 \def\ParseFenRankA(#1#2){%
363   \EqStr{Z}{#1}%
364   {}%
365   {\FenConvert{#1}\ParseFenRankA(#2)}}
366
367 \def\SetCheckKing#1#2{% square -> piece -> unit
368   \EqStr{K}{#2}%
369   {\edef\WhiteKingSquare{#1}}%
370   {\EqStr{k}{#2}%
371     {\edef\BlackKingSquare{#1}}%
372     {}}%
373   \Set{#1}{#2}}
374
375 \def\InitRank#1#2#3#4#5#6#7#8#9{%
376   \SetCheckKing{a#9}{#1}%
377   \SetCheckKing{b#9}{#2}%
378   \SetCheckKing{c#9}{#3}%
379   \SetCheckKing{d#9}{#4}%
380   \SetCheckKing{e#9}{#5}%
381   \SetCheckKing{f#9}{#6}%
382   \SetCheckKing{g#9}{#7}%
383   \SetCheckKing{h#9}{#8}}
384
385 \def\SetRank#1#2{% rank -> fenrank -> unit
386   \edef\pap{\ParseFenRank{#2}}%
387   \expandafter\InitRank\pap#1}
388  
389
390 \def\InitBoard(#1/#2/#3/#4/#5/#6/#7/#8){%
391   \SetRank{8}{#1}%
392   \SetRank{7}{#2}%
393   \SetRank{6}{#3}%
394   \SetRank{5}{#4}%
395   \SetRank{4}{#5}%
396   \SetRank{3}{#6}%
397   \SetRank{2}{#7}%
398   \SetRank{1}{#8}%
399   }
400
401 \def\WhiteCastling{-}
402 \def\BlackCastling{-}
403
404 \def\ExtractWhiteCastling#1{\def\tempCastling{-}%
405 \ExtractWhiteCastlingA(#1Z)%
406 \edef\WhiteCastling{\tempCastling}}
407 \def\ExtractWhiteCastlingA(#1#2){%
408   \EqStr{Z}{#1}%
409   {}%
410   {\Or{\EqPiece{K}{#1}}{\EqPiece{Q}{#1}}%
411     {\EqStr{-}{\tempCastling}%
412       {\edef\tempCastling{#1}\ExtractWhiteCastlingA(#2)}%
413       {\edef\tempCastling{\tempCastling#1}}}%
414     {\ExtractWhiteCastlingA(#2)}}}
415
416 \def\ExtractBlackCastling#1{\def\tmpCastling{-}%
417 \ExtractBlackCastlingA(#1Z)%
418 \edef\BlackCastling{\tmpCastling}}
419 \def\ExtractBlackCastlingA(#1#2){%
420   \EqStr{Z}{#1}%
421   {}%
422   {\Or{\EqPiece{k}{#1}}{\EqPiece{q}{#1}}%
423     {\EqStr{-}{\tmpCastling}%
424       {\edef\tmpCastling{#1}\ExtractBlackCastlingA(#2)}%
425       {\edef\tmpCastling{\tmpCastling#1}}}%
426     {\ExtractBlackCastlingA(#2)}}}
427
428 \newcounter{halfmove}
429 \newcounter{move}
430 \def\fenboard#1{\FenBoard#1)}
431 \def\FenBoard#1 #2 #3 #4 #5 #6){%
432   \InitBoard(#1)%
433   \def\WhiteToMove{\EqStr{w}{#2}}%
434     \ExtractWhiteCastling{#3}%}
435     \ExtractBlackCastling{#3}%}
436   \def\EnPassantSquare{#4}%
437   \setcounter{halfmove}{#5}%
438   \setcounter{move}{#6}}
439
440
441 \newcounter{helpgobble}
442 \def\PieceToFen#1{%
443   \EqPiece{E}{#1}%
444   {1}{#1}}
445
446 \def\Fen@RawRank#1{\PieceToFen{\Get{a#1}}\PieceToFen{\Get{b#1}}%
447     \PieceToFen{\Get{c#1}}\PieceToFen{\Get{d#1}}%
448     \PieceToFen{\Get{e#1}}\PieceToFen{\Get{f#1}}%
449     \PieceToFen{\Get{g#1}}\PieceToFen{\Get{h#1}}}
450
451 \def\PrintCastling{%
452   \EqStr{-}{\WhiteCastling}%
453   {\BlackCastling}%
454   {\WhiteCastling%
455     \EqStr{-}{\BlackCastling}%
456     {-}%
457     {\BlackCastling}}}
458
459
460 \def\Fen@handlenumbers#1#2#3#4#5#6#7#8{\setcounter{helpgobble}{0}%
461   \Fen@handleA(#1#2#3#4#5#6#7#8Z)}
462 \def\Fen@handleA(#1#2){%
463   \EqStr{Z}{#1}%
464   {\ifnum0=\thehelpgobble%
465     \else\edef\temp@rank{\temp@rank\arabic{helpgobble}}\fi}%
466   {\EqPiece{1}{#1}%
467     {\stepcounter{helpgobble}\Fen@handleA(#2)}%
468     {\ifnum0=\thehelpgobble\edef\temp@rank{\temp@rank#1}\Fen@handleA(#2)%
469       \else\edef\temp@rank{\temp@rank\arabic{helpgobble}#1}%
470       \setcounter{helpgobble}{0}\Fen@handleA(#2)\fi}}}
471
472
473 \def\Fen@Rank#1{\edef\temp@rank{}\edef\temp@rankA{\Fen@RawRank{#1}}%
474   \expandafter\Fen@handlenumbers\temp@rankA}
475
476 \def\Fen@calculate{%
477   \Fen@Rank{8}\edef\temp@board{\temp@rank/}%
478   \Fen@Rank{7}\edef\temp@board{\temp@board\temp@rank/}%
479   \Fen@Rank{6}\edef\temp@board{\temp@board\temp@rank/}%
480   \Fen@Rank{5}\edef\temp@board{\temp@board\temp@rank/}%
481   \Fen@Rank{4}\edef\temp@board{\temp@board\temp@rank/}%
482   \Fen@Rank{3}\edef\temp@board{\temp@board\temp@rank/}%
483   \Fen@Rank{2}\edef\temp@board{\temp@board\temp@rank/}%
484   \Fen@Rank{1}\edef\temp@board{\temp@board\temp@rank}%
485   \edef\temp@board{\temp@board\space\WhiteToMove{w}{b}}%
486   \edef\temp@board{\temp@board\space\PrintCastling\space\EnPassantSquare}%
487   \edef\temp@board{\temp@board\space\arabic{halfmove}\space\arabic{move}}}
488
489
490 \def\boardasfen{\Fen@calculate\temp@board} % if someone wants fen in
491                                            % their document
492
493
494 %%%%% manipulation of the board state
495 % the special out-of-bounds square
496 \Set{Offboard}{X} % note: no piece is named X
497
498 \def\EnPassantSquare{-}% updated by ExecuteMove
499
500
501 \def\WhiteToMove{\True}
502
503 \def\WhiteKingSquare% unit -> square
504 {e1}
505 \def\BlackKingSquare% unit -> square
506 {e8}
507 \def\KingSquare#1{% bool -> square
508 #1\WhiteKingSquare\BlackKingSquare}
509 \def\SetKingSquare#1#2{% bool -> square -> unit
510   #1{\xdef\WhiteKingSquare{#2}}{\xdef\BlackKingSquare{#2}}}
511
512
513 % neighbours of a square
514 \def\SetNeighbour#1#2#3% direction -> square -> square -> unit, #2's
515                        % neighbour in direction #1 is #3
516 {\expandafter\xdef\csname#1.#2\endcsname{#3}}
517 \def\GetNeighbour#1#2% direction -> square -> square
518 {\csname#1.#2\endcsname}
519 % all the hard work:
520 % first we deal with the board boarder ;-)
521 \def\FF#1#2{\SetNeighbour{#1}{#2}{Offboard}}
522
523 \def\ForwardDirection#1% bool -> direction; up for white, down for black
524 {#1{up}{down}}
525 \def\BackwardDirection#1% bool -> direction
526 {#1{down}{up}}
527 \def\LeftDirection#1% bool -> direction
528 {#1{left}{right}}
529 \def\RightDirection#1% bool -> direction
530 {#1{right}{left}}
531
532
533 \Apply{\FF{left}}{\File{a}}
534 \Apply{\FF{upleft}}{\File{a}}
535 \Apply{\FF{downleft}}{\File{a}}
536 \Apply{\FF{right}}{\File{h}}
537 \Apply{\FF{upright}}{\File{h}}
538 \Apply{\FF{downright}}{\File{h}}
539 \Apply{\FF{up}}{\Rank{8}}
540 \Apply{\FF{upleft}}{\Rank{8}}
541 \Apply{\FF{upright}}{\Rank{8}}
542 \Apply{\FF{down}}{\Rank{1}}
543 \Apply{\FF{downleft}}{\Rank{1}}
544 \Apply{\FF{downright}}{\Rank{1}}
545
546
547 \def\SetUpNeighbour#1#2#3% direction -> rank -> rank -> unit
548 {\SetNeighbour{#1}{a#2}{a#3}%
549   \SetNeighbour{#1}{b#2}{b#3}%
550   \SetNeighbour{#1}{c#2}{c#3}%
551   \SetNeighbour{#1}{d#2}{d#3}%
552   \SetNeighbour{#1}{e#2}{e#3}%
553   \SetNeighbour{#1}{f#2}{f#3}%
554   \SetNeighbour{#1}{g#2}{g#3}%
555   \SetNeighbour{#1}{h#2}{h#3}}
556 \let\SetDownNeighbour=\SetUpNeighbour%
557 \SetUpNeighbour{up}{1}{2}
558 \SetUpNeighbour{up}{2}{3}
559 \SetUpNeighbour{up}{3}{4}
560 \SetUpNeighbour{up}{4}{5}
561 \SetUpNeighbour{up}{5}{6}
562 \SetUpNeighbour{up}{6}{7}
563 \SetUpNeighbour{up}{7}{8}
564 \SetDownNeighbour{down}{2}{1}
565 \SetDownNeighbour{down}{3}{2}
566 \SetDownNeighbour{down}{4}{3}
567 \SetDownNeighbour{down}{5}{4}
568 \SetDownNeighbour{down}{6}{5}
569 \SetDownNeighbour{down}{7}{6}
570 \SetDownNeighbour{down}{8}{7}
571
572
573
574 \def\SetUpRightNeighbour#1#2#3% direction -> rank -> rank -> unit
575 {\SetNeighbour{#1}{a#2}{b#3}%
576   \SetNeighbour{#1}{b#2}{c#3}%
577   \SetNeighbour{#1}{c#2}{d#3}%
578   \SetNeighbour{#1}{d#2}{e#3}%
579   \SetNeighbour{#1}{e#2}{f#3}%
580   \SetNeighbour{#1}{f#2}{g#3}%
581   \SetNeighbour{#1}{g#2}{h#3}%
582   \SetNeighbour{#1}{h#2}{Offboard}}
583 \let\SetDownRightNeighbour=\SetUpRightNeighbour
584 \SetUpRightNeighbour{upright}{1}{2}
585 \SetUpRightNeighbour{upright}{2}{3}
586 \SetUpRightNeighbour{upright}{3}{4}
587 \SetUpRightNeighbour{upright}{4}{5}
588 \SetUpRightNeighbour{upright}{5}{6}
589 \SetUpRightNeighbour{upright}{6}{7}
590 \SetUpRightNeighbour{upright}{7}{8}
591 \SetDownRightNeighbour{downright}{2}{1}
592 \SetDownRightNeighbour{downright}{3}{2}
593 \SetDownRightNeighbour{downright}{4}{3}
594 \SetDownRightNeighbour{downright}{5}{4}
595 \SetDownRightNeighbour{downright}{6}{5}
596 \SetDownRightNeighbour{downright}{7}{6}
597 \SetDownRightNeighbour{downright}{8}{7}
598
599
600
601 \def\SetUpLeftNeighbour#1#2#3% direction -> rank -> rank -> unit
602 {\SetNeighbour{#1}{a#2}{Offboard}%
603   \SetNeighbour{#1}{b#2}{a#3}%
604   \SetNeighbour{#1}{c#2}{b#3}%
605   \SetNeighbour{#1}{d#2}{c#3}%
606   \SetNeighbour{#1}{e#2}{d#3}%
607   \SetNeighbour{#1}{f#2}{e#3}%
608   \SetNeighbour{#1}{g#2}{f#3}%
609   \SetNeighbour{#1}{h#2}{g#3}}
610 \let\SetDownLeftNeighbour=\SetUpLeftNeighbour
611 \SetUpLeftNeighbour{upleft}{1}{2}
612 \SetUpLeftNeighbour{upleft}{2}{3}
613 \SetUpLeftNeighbour{upleft}{3}{4}
614 \SetUpLeftNeighbour{upleft}{4}{5}
615 \SetUpLeftNeighbour{upleft}{5}{6}
616 \SetUpLeftNeighbour{upleft}{6}{7}
617 \SetUpLeftNeighbour{upleft}{7}{8}
618 \SetDownLeftNeighbour{downleft}{2}{1}
619 \SetDownLeftNeighbour{downleft}{3}{2}
620 \SetDownLeftNeighbour{downleft}{4}{3}
621 \SetDownLeftNeighbour{downleft}{5}{4}
622 \SetDownLeftNeighbour{downleft}{6}{5}
623 \SetDownLeftNeighbour{downleft}{7}{6}
624 \SetDownLeftNeighbour{downleft}{8}{7}
625
626
627 \def\SetLeftNeighbour#1#2#3% direction -> file -> file -> unit
628 {\SetNeighbour{#1}{#21}{#31}%
629   \SetNeighbour{#1}{#22}{#32}%
630   \SetNeighbour{#1}{#23}{#33}%
631   \SetNeighbour{#1}{#24}{#34}%
632   \SetNeighbour{#1}{#25}{#35}%
633   \SetNeighbour{#1}{#26}{#36}%
634   \SetNeighbour{#1}{#27}{#37}%
635   \SetNeighbour{#1}{#28}{#38}}
636 \let\SetRightNeighbour=\SetLeftNeighbour
637 \SetLeftNeighbour{left}{b}{a}
638 \SetLeftNeighbour{left}{c}{b}
639 \SetLeftNeighbour{left}{d}{c}
640 \SetLeftNeighbour{left}{e}{d}
641 \SetLeftNeighbour{left}{f}{e}
642 \SetLeftNeighbour{left}{g}{f}
643 \SetLeftNeighbour{left}{h}{g}
644 \SetRightNeighbour{right}{a}{b}
645 \SetRightNeighbour{right}{b}{c}
646 \SetRightNeighbour{right}{c}{d}
647 \SetRightNeighbour{right}{d}{e}
648 \SetRightNeighbour{right}{e}{f}
649 \SetRightNeighbour{right}{f}{g}
650 \SetRightNeighbour{right}{g}{h}
651
652
653
654 % the knight needs special attention
655 \def\KnightSquares#1% square -> square list
656 {\csname#1.knight\endcsname}
657
658 \def\SetKnightSquares#1#2% square -> square list -> unit
659 {\expandafter\def\csname#1.knight\endcsname{#2}}
660
661 % a file
662 \SetKnightSquares{a1}{\Listize[b3,c2]}
663 \SetKnightSquares{a2}{\Listize[b4,c3,c1]}
664 \SetKnightSquares{a3}{\Listize[b5,c4,c2,b1]}
665 \SetKnightSquares{a4}{\Listize[b6,c5,c3,b2]}
666 \SetKnightSquares{a5}{\Listize[b7,c6,c4,b3]}
667 \SetKnightSquares{a6}{\Listize[b8,c7,c5,b4]}
668 \SetKnightSquares{a7}{\Listize[c8,c6,b5]}
669 \SetKnightSquares{a8}{\Listize[c7,b6]}
670 % b file
671 \SetKnightSquares{b1}{\Listize[a3,c3,d2]}
672 \SetKnightSquares{b2}{\Listize[a4,c4,d3,d1]}
673 \SetKnightSquares{b3}{\Listize[a5,c5,d4,d2,a1,c1]}
674 \SetKnightSquares{b4}{\Listize[a6,c6,d5,d3,a2,c2]}
675 \SetKnightSquares{b5}{\Listize[a7,c7,d6,d4,a3,c3]}
676 \SetKnightSquares{b6}{\Listize[a8,c8,d7,d5,a5,c5]}
677 \SetKnightSquares{b7}{\Listize[d8,d6,a5,c5]}
678 \SetKnightSquares{b8}{\Listize[d7,a6,c6]}
679 % c file
680 \SetKnightSquares{c1}{\Listize[a2,b3,d3,e2]}
681 \SetKnightSquares{c2}{\Listize[a1,a3,b4,d4,e3,e1]}
682 \SetKnightSquares{c3}{\Listize[a2,a4,b1,b5,d1,d5,e2,e4]}
683 \SetKnightSquares{c4}{\Listize[a3,a5,b2,b6,d2,d6,e3,e5]}
684 \SetKnightSquares{c5}{\Listize[a4,a6,b3,b7,d3,d7,e4,e6]}
685 \SetKnightSquares{c6}{\Listize[a5,a7,b4,b8,d4,d8,e5,e7]}
686 \SetKnightSquares{c7}{\Listize[a6,a8,b5,d5,e6,e8]}
687 \SetKnightSquares{c8}{\Listize[a7,b6,d6,e7]}
688 % d file
689 \SetKnightSquares{d1}{\Listize[b2,c3,e3,f2]}
690 \SetKnightSquares{d2}{\Listize[b1,b3,c4,e4,f3,f1]}
691 \SetKnightSquares{d3}{\Listize[b2,b4,c1,c5,e1,e5,f2,f4]}
692 \SetKnightSquares{d4}{\Listize[b3,b5,c2,c6,e2,e6,f3,f5]}
693 \SetKnightSquares{d5}{\Listize[b4,b6,c3,c7,e3,e7,f4,f6]}
694 \SetKnightSquares{d6}{\Listize[b5,b7,c4,c8,e4,e8,f5,f7]}
695 \SetKnightSquares{d7}{\Listize[b6,b8,c5,e5,f6,f8]}
696 \SetKnightSquares{d8}{\Listize[b7,c6,e6,f7]}
697 % e file
698 \SetKnightSquares{e1}{\Listize[c2,d3,f3,g2]}
699 \SetKnightSquares{e2}{\Listize[c1,c3,d4,f4,g3,g1]}
700 \SetKnightSquares{e3}{\Listize[c2,c4,d1,d5,f1,f5,g2,g4]}
701 \SetKnightSquares{e4}{\Listize[c3,c5,d2,d6,f2,f6,g3,g5]}
702 \SetKnightSquares{e5}{\Listize[c4,c6,d3,d7,f3,f7,g4,g6]}
703 \SetKnightSquares{e6}{\Listize[c5,c7,d4,d8,f4,f8,g5,g7]}
704 \SetKnightSquares{e7}{\Listize[c6,c8,d5,f5,g6,g8]}
705 \SetKnightSquares{e8}{\Listize[c7,d6,f6,g7]}
706 % f file
707 \SetKnightSquares{f1}{\Listize[d2,e3,g3,h2]}
708 \SetKnightSquares{f2}{\Listize[d1,d3,e4,g4,h3,h1]}
709 \SetKnightSquares{f3}{\Listize[d2,d4,e1,e5,g1,g5,h2,h4]}
710 \SetKnightSquares{f4}{\Listize[d3,d5,e2,e6,g2,g6,h3,h5]}
711 \SetKnightSquares{f5}{\Listize[d4,d6,e3,e7,g3,g7,h4,h6]}
712 \SetKnightSquares{f6}{\Listize[d5,d7,e4,e8,g4,g8,h5,h7]}
713 \SetKnightSquares{f7}{\Listize[d6,d8,e5,g5,h6,h8]}
714 \SetKnightSquares{f8}{\Listize[d7,e6,g6,h7]}
715 % g file
716 \SetKnightSquares{g1}{\Listize[h3,f3,e2]}
717 \SetKnightSquares{g2}{\Listize[h4,f4,e3,e1]}
718 \SetKnightSquares{g3}{\Listize[h5,f5,e4,e2,h1,f1]}
719 \SetKnightSquares{g4}{\Listize[h6,f6,e5,e3,h2,f2]}
720 \SetKnightSquares{g5}{\Listize[h7,f7,e6,e4,h3,f3]}
721 \SetKnightSquares{g6}{\Listize[h8,f8,e7,e5,h4,f4]}
722 \SetKnightSquares{g7}{\Listize[e8,e6,h5,f5]}
723 \SetKnightSquares{g8}{\Listize[h6,f6,e7]}
724 % h file
725 \SetKnightSquares{h1}{\Listize[g3,f2]}
726 \SetKnightSquares{h2}{\Listize[g4,f3,f1]}
727 \SetKnightSquares{h3}{\Listize[g5,f4,f2,g1]}
728 \SetKnightSquares{h4}{\Listize[g6,f5,f3,g2]}
729 \SetKnightSquares{h5}{\Listize[g7,f6,f4,g3]}
730 \SetKnightSquares{h6}{\Listize[g8,f7,f5,g4]}
731 \SetKnightSquares{h7}{\Listize[f8,f6,g5]}
732 \SetKnightSquares{h8}{\Listize[f7,g6]}
733
734
735 % % finding the neighbours of a square, used when the king moves...
736 %  \def\Neighbours#1% square -> square list
737 %  {\Map{\Twiddle\GetNeighbour{#1}}%
738 %    {\Listize[left,upleft,up,upright,right,downright,down,downleft]}}
739
740 % StringToTokens: string -> string list, cut at spaces
741 \def\StringToTokens#1%
742 {\skak@ifthenelse{\equal{#1}{}}{\Nil}{\StrToTokens(#1 )}}
743 \def\StrToTokens (#1 #2){%
744   \EqStr{#1}{}% 
745     {\Nil}%
746     \Cons{#1}{\EqStr{#2}{} {\Nil} {\StrToTokens(#2)}}}
747
748 \def\BlackPiece#1% char -> piece
749 {\EqStr{#1}{K}%
750   {k}%
751   {\EqStr{#1}{Q}%
752     {q}%
753     {\EqStr{#1}{R}%
754       {r}%
755       {\EqStr{#1}{B}%
756         {b}%
757         {\EqStr{#1}{N}%
758           {n}%
759           {p}}}}}}
760
761 \def\PieceNameToPiece#1#2% piecename -> bool -> piece
762 {#2{#1}{\BlackPiece{#1}}}
763
764 % setting up variables for ParseMove
765 \def\ParseMoveInit{%
766  \gdef\MoveToRank{Z}\gdef\MoveToFile{Z}%
767  \gdef\RankDiscriminator{Z}\gdef\FileDiscriminator{Z}%
768  \gdef\PieceNameToMove{Z}%
769  \gdef\Capture{\False}%
770  \gdef\Promotion{\False}\gdef\PromotionPieceName{Z}%
771  \gdef\Castling{\False}\gdef\LongCastling{\False}}
772
773 \def\ParseMove#1{% string -> unit
774   \ParseMoveA(#1)}
775
776 \def\ParseMoveA(#1#2){% char -> string -> unit 
777   \IsPieceName{#1}%
778   {\gdef\PieceNameToMove{\skak@pieceToEnglish{#1}}%
779     \gdef\PieceToMove{\PieceNameToPiece{\PieceNameToMove}{\WhiteToMove}}%
780     \ParseCoordinates(#2Z)%
781     \gdef\MoveTo{\MoveToFile\MoveToRank}}%
782   {\IsO{#1}%
783     {\def\Castling{\True}%
784       \ParseCastling(#2Z)}%
785     {\ParseCoordinates(#1#2Z)%
786       \gdef\MoveTo{\MoveToFile\MoveToRank}}}}
787
788 \def\FirstChar(#1#2){#1}
789
790 \def\ParseCoordinates(#1#2){% char -> string -> unit
791   \EqStr{Z}{#1}%
792   {}% we are done!
793   {\IsFile{#1}%
794     {\EqStr{\MoveToFile}{Z}%
795       {}% first File name in move so nothing to do
796       {\xdef\FileDiscriminator{\MoveToFile}}%
797       \gdef\MoveToFile{#1}%
798       \ParseCoordinates(#2)}%
799   {\IsRank{#1}%
800     {\EqStr{\MoveToRank}{Z}%
801       {}%
802       {\gdef\RankDiscriminator{\MoveToRank}}%
803       \gdef\MoveToRank{#1}%
804       \ParseCoordinates(#2)}%
805     {\IsCapture{#1}%
806       {\gdef\Capture{\True}%
807         \ParseCoordinates(#2)}%
808       {\IsPromotion{#1}%
809         {\def\Promotion{\True}%
810           \gdef\PromotionPieceName{\skak@pieceToEnlish{\FirstChar(#2)}}}}%
811       {}% no more information is of interest   
812       }}}}
813
814 % help for \ParseCastling
815 \def\ParseCastlingA(#1#2#3){%
816   \MyEqualB{#1#2}{-O}%
817   {\gdef\LongCastling{\True}}%
818   {}}
819
820 \def\ParseCastling(-O#1){% strip the first -O, at least Z is left
821   \ParseCastlingA(#1VW)}
822
823 % \def\ParseCastling(-O#1#2){%
824 %   \EqStr{#1}{Z}%
825 %   {}%
826 %   {\def\LongCastling{\True}}}
827
828
829 % for testing purposes
830 \def\ShowParseInfo%
831 { %MoveTo: \MoveTo
832   MoveToRank: \MoveToRank, MoveToFile: \MoveToFile, \\
833   RankDiscriminator: \RankDiscriminator, FileDiscriminator:
834   \FileDiscriminator, \\ Promotion: \BoolToString{\Promotion},
835   PromotionPieceName: \PromotionPieceName
836   Capture: \BoolToString{\Capture}, \\
837   PieceNameToMove: \PieceNameToMove, \\
838   Castling: \BoolToString{\Castling},
839   LongCastling: \BoolToString{\LongCastling}}
840
841 % castling, with preparation for eg, FisheRandom
842 %\def\WhiteShortRook{h1}
843 %\def\WhiteLongRook{a1}
844 %\def\BlackShortRook{h8}
845 %\def\WhiteLong
846 \def\FirstRank#1{% bool -> rank
847   #1{1}{8}}
848 \def\CastleKingFile#1{% bool -> file, LongCastling is used as argument
849   #1{c}{g}}
850 \def\CastleRookToFile#1{%
851   #1{d}{f}}
852 \def\CastleRookFromFile#1{%
853   #1{a}{h}}
854
855 \def\CastleDone#1{% bool -> unit
856   #1{\gdef\WhiteCastling{-}}{\gdef\BlackCastling{-}}}
857
858 \def\ExecuteCastling{% relies on \ParseMove
859   \stepcounter{halfmove}%
860   \gdef\MoveTo{\CastleKingFile{\LongCastling}\FirstRank{\WhiteToMove}}%
861   \ExecuteKingMove%
862   \gdef\MoveTo{\CastleRookToFile{\LongCastling}\FirstRank{\WhiteToMove}}%
863   \DoTheMove{\CastleRookFromFile{\LongCastling}\FirstRank{\WhiteToMove}}%
864   \CastleDone{\WhiteToMove}}
865
866
867 %%% after ParseMove has gathered info we find the piece to move
868 % LookFor looks in one direction, stopping if a non-empty square is
869 % found
870 \def\LookFor#1#2#3{% (piece -> bool) -> square -> direction -> square list
871   \LookForA{#1}{\GetNeighbour{#3}{#2}}{#3}} % we have to skip the
872                                             % first square!!!
873 \def\LookForA#1#2#3{% (piece -> bool) -> square -> direction -> square list
874   #1{\Get{#2}}%
875   {\Singleton{#2}}%
876   {\EqPiece{E}{\Get{#2}}% empty square => continue in the given direction
877     {\LookForA{#1}{\GetNeighbour{#3}{#2}}{#3}}%
878     {\Nil}}}
879
880
881 % IsRightPiece is true if a piece matching #1 is on square#2
882 \def\IsRightPiece#1#2{% piece -> square -> bool
883  \EqPiece{#1}{\Get{#2}}}
884
885 \def\IsRookQueen#1#2{% bool -> piece -> bool
886   \Or{\EqPiece{#2}{\PieceNameToPiece{R}{#1}}}%
887   {\EqPiece{#2}{\PieceNameToPiece{Q}{#1}}}%
888   }
889 \def\IsBishopQueen#1#2{% bool -> piece -> bool
890   \Or{\EqPiece{#2}{\PieceNameToPiece{B}{#1}}}%
891   {\EqPiece{#2}{\PieceNameToPiece{Q}{#1}}}%
892   }
893
894 % (piece-> bool) -> square -> direction list -> square list
895 \def\ScanDirections#1#2#3{\Foldr{\Compose\Cat{\LookFor{#1}{#2}}}\Nil{#3}}
896
897
898 % relies on the info gathered by ParseMove
899 \def\FindPieceSquares#1#2{% bool -> square -> square list 
900   \EqPiece{\PieceNameToMove}{R}%
901   {\ScanDirections%
902     {\EqPiece{\PieceToMove}}{#2}{\Listize[up,down,left,right]}}%
903   {\EqPiece{\PieceNameToMove}{B}%
904     {\ScanDirections%
905       {\EqPiece{\PieceToMove}}{#2}%
906       {\Listize[upright,downright,downleft,upleft]}}%
907     {\EqPiece{\PieceNameToMove}{Q}%
908       {\ScanDirections%
909         {\EqPiece{\PieceToMove}}{#2}%
910         {\Listize[up,down,left,right,upleft,upright,downleft,downright]}}%
911       {\Filter{\IsRightPiece{\PieceToMove}}{\KnightSquares{#2}}}}}}
912
913 \def\UniqueMove% bool, if the descriminators <> Z
914 {\And%
915   {\Not{\EqStr{\RankDiscriminator}{Z}}}%
916   {\Not{\EqStr{\FileDiscriminator}}{Z}}}
917
918 \def\DoTheMove#1{% move the piece from #1 to \MoveToFile\MoveToRank
919   \edef\oldpiece{\Get{\MoveToFile\MoveToRank}}%
920   \Set{\MoveTo}{\Get{#1}}\Set{#1}{E}%
921   \gdef\MoveFrom{#1}}
922
923 \def\DoTheMoveList#1{\DoTheMove{\Head{#1}}}
924
925 % undoes the move to #1
926 \def\UndoMove#1{% square -> unit, relies on \oldpiece and \MoveToFile/Rank
927 \Set{#1}{\Get{\MoveToFile\MoveToRank}}\Set{\MoveToFile\MoveToRank}{\oldpiece}%
928 \Or{\EqPiece{\PieceToMove}{K}}{\EqPiece{\PieceToMove}{k}}%
929   {\SetKingSquare{\WhiteToMove}{#1}}%
930   {}}
931
932 \def\NoEnemiesFound{% bool
933 \IsNil{\Cat{\ScanDirections{\IsRookQueen{\Not\WhiteToMove}}%
934     {\KingSquare{\WhiteToMove}}{\Listize[up,down,left,right]}}%
935   {\ScanDirections{\IsBishopQueen{\Not\WhiteToMove}}%
936     {\KingSquare{\WhiteToMove}}%
937     {\Listize[upleft,downright,downleft,upright]}}}}
938
939 \newboolean{helplegal}
940
941 \def\LegalMove#1{% square -> bool, is the move possible to do?
942   \DoTheMove{#1}%
943   \NoEnemiesFound%
944   {\UndoMove{#1}\True}%
945   {\UndoMove{#1}\False}}%
946 %  \skak@ifthenelse{\boolean{helplegal}}{\True}{\False}}
947 % \def\LegalMove#1{% square -> bool, is the move possible to do?
948 % %  \edef\oldpiece{\Get{\MoveToFile\MoveToRank}}%
949 %   \DoTheMove{#1}%
950 % %  \setboolean{helplegal}{\NoEnemiesFound{true}{false}}%
951 %   \gdef\HelpLegal{\NoEnemiesFound}
952 %   \UndoMove{#1}%
953 %   \HelpLegal}
954 % %  \skak@ifthenelse{\boolean{helplegal}}{\True}{\False}}
955
956 % relies on \ParseMove
957 \def\TrimMoveList#1{% square -> bool
958 \gdef\trimhelp{#1}%(
959 \And{\RightRank(\trimhelp)}{\And{\RightFile(\trimhelp)}{\LegalMove{\trimhelp}}}}
960 %\And{\RightRank(#1)}{\And{\RightFile(#1)}{\LegalMove{#1}}}}
961
962 \def\ExecuteKingMove{% relies on ParseMove, WhiteToMove
963   \DoTheMove{\KingSquare{\WhiteToMove}}%
964   \SetKingSquare{\WhiteToMove}{\MoveTo}%
965   \WhiteToMove%
966   {\edef\WhiteCastling{-}}%
967   {\edef\BlackCastling{-}}}
968
969 % % used by UpdateCastling
970 % \def\RemoveLongCastling{% relies on \WhiteToMove
971 %   \WhiteToMove%
972 %   {\EqStr{KQ}{\WhiteCastling}%
973 %     {\edef\WhiteCastling{K}}%
974 %     {\EqStr{Q}{\WhiteCastling}%
975 %       {\edef\WhiteCastling{-}}
976 %       {}}}%
977 %   {\EqStr{kq}{\BlackCastling}%
978 %     {\edef\BlackCastling{k}}%
979 %     {\EqStr{q}{\BlackCastling}%
980 %       {\edef\BlackCastling{-}}%
981 %       {}}}}
982
983 % used by UpdateCastling
984 \def\RemoveLongCastling{% relies on \WhiteToMove
985   \WhiteToMove%
986   {\skak@ifthenelse{\equal{KQ}{\WhiteCastling}}%
987     {\gdef\WhiteCastling{K}}%
988     {\skak@ifthenelse{\equal{Q}{\WhiteCastling}}%
989       {\gdef\WhiteCastling{-}}%
990       {}}}%
991   {\skak@ifthenelse{\equal{kq}{\BlackCastling}}%
992       {\gdef\BlackCastling{k}}%
993       {\skak@ifthenelse{\equal{q}{\BlackCastling}}%
994         {\edef\BlackCastling{-}}%
995         {}}}}%
996
997 % % used by UpdateCastling
998 % \def\RemoveShortCastling{% relies on \WhiteToMove
999 %   \WhiteToMove%
1000 %   {\skak@ifthenelse{\equal{KQ}{\WhiteCastling}}%
1001 %     %\EqStr{KQ}{\WhiteCastling}%
1002 %     {\edef\WhiteCastling{Q}}%
1003 %     {\EqStr{K}{\WhiteCastling}%
1004 %       {\edef\WhiteCastling{-}}%
1005 %       {}}}%
1006 %   {\skak@ifthenelse{\equal{kq}{\BlackCastling}}%
1007 %     %\EqStr{kq}{\BlackCastling}%
1008 %     {\edef\BlackCastling{q}}%
1009 %     {\EqStr{k}{\BlackCastling}%
1010 %       {\edef\BlackCastling{-}}%
1011 %       {}}}}
1012
1013 % used by UpdateCastling
1014 \def\RemoveShortCastling{% relies on \WhiteToMove
1015   \WhiteToMove%
1016   {\skak@ifthenelse{\equal{KQ}{\WhiteCastling}}%
1017     %\EqStr{KQ}{\WhiteCastling}%
1018     {\gdef\WhiteCastling{Q}}%
1019     {\skak@ifthenelse{\equal{K}{\WhiteCastling}}
1020       {\gdef\WhiteCastling{-}}%
1021       {}}}%
1022   {\skak@ifthenelse{\equal{kq}{\BlackCastling}}%
1023     %\EqStr{kq}{\BlackCastling}%
1024     {\gdef\BlackCastling{q}}%
1025     {\EqStr{k}{\BlackCastling}%
1026       {\gdef\BlackCastling{-}}%
1027       {}}}}
1028
1029 \def\UpdateCastling{% relies on \ParseMove
1030   \EqPiece{R}{\PieceNameToMove}%
1031   { \EqSquare{\MoveFrom}{\CastleRookFromFile{\True}\FirstRank{\WhiteToMove}}%
1032     {\RemoveLongCastling}%
1033     {\EqSquare{\MoveFrom}{\CastleRookFromFile{\False}\FirstRank{\WhiteToMove}}%
1034       {\RemoveShortCastling}%
1035       {}}}%
1036   {}}% non rook moves will not change the castling possibilities
1037
1038 \def\ExecutePieceMove{% relies on the info gathered by ParseMove
1039   \Capture{\setcounter{halfmove}{0}}{\stepcounter{halfmove}}%
1040   \UniqueMove%
1041   {\DoTheMove{\FileDiscriminator\RankDiscriminator}}%
1042   {\EqPiece{K}{\PieceNameToMove}%
1043     {\ExecuteKingMove}%
1044     {%
1045 %       (\Unlistize{\FindPieceSquares{\WhiteToMove}{\MoveTo}},%
1046 %       \Unlistize{\Filter{\TrimMoveList}%
1047 %         {\FindPieceSquares{\WhiteToMove}{\MoveTo}}})%
1048       \Apply{\DoTheMove}{\Filter{\TrimMoveList}%
1049         {\FindPieceSquares{\WhiteToMove}{\MoveTo}}}}%
1050     }
1051   \UpdateCastling}
1052
1053 % % for pawn captures and moves
1054 % \newcounter{rankhelp}
1055 % % \def\FromRank{\setcounter{rankhelp}{\MoveToRank}%
1056 % %   \addtocounter{rankhelp}{\WhiteToMove{-1}{1}}
1057 % %   \arabic{rankhelp}}
1058 \def\FromRank{%
1059   \EqStr{1}{\MoveToRank}%
1060   {\WhiteToMove{0}{2}}%
1061   {\EqStr{2}{\MoveToRank}%
1062     {\WhiteToMove{1}{3}}%
1063     {\EqStr{3}{\MoveToRank}%
1064       {\WhiteToMove{2}{4}}%
1065       {\EqStr{4}{\MoveToRank}%
1066         {\WhiteToMove{3}{5}}%
1067         {\EqStr{5}{\MoveToRank}%
1068           {\WhiteToMove{4}{6}}%
1069           {\EqStr{6}{\MoveToRank}%
1070             {\WhiteToMove{5}{7}}%
1071             {\EqStr{7}{\MoveToRank}%
1072               {\WhiteToMove{6}{8}}%
1073               {\EqStr{8}{\MoveToRank}%
1074                 {\WhiteToMove{7}{9}}%
1075                 {}}}}}}}}}
1076 \def\InitialRank{\WhiteToMove{2}{7}}
1077
1078 \def\ExecutePawnMove{% relies on the info obtained by ParseMove
1079   \setcounter{halfmove}{0}%
1080   \Capture%
1081   {\EqPiece{E}{\Get{\MoveTo}}%
1082     {\Set{\MoveToFile\FromRank}{E}}%
1083     {}%
1084     \DoTheMove{\FileDiscriminator\FromRank}%
1085     \def\EnPassantSquare{-}}%
1086   {\EqPiece{E}{\Get{\MoveToFile\FromRank}}%
1087     {\edef\EnPassantSquare{\MoveToFile\FromRank}% two square move
1088       \DoTheMove{\MoveToFile\InitialRank}}%
1089     {\DoTheMove{\MoveToFile\FromRank}% one square move
1090       \def\EnPassantSquare{-}}}%
1091   \Promotion%
1092   {\Set{\MoveTo}{\PieceNameToPiece{\PromotionPieceName}{\WhiteToMove}}}%
1093   {}}
1094
1095
1096 \def\MakeMove#1{% string -> unit
1097 %  (In MakeMove: WhiteToMove \BoolToString\WhiteToMove)
1098   \ParseMoveInit%
1099   \ParseMove{#1}%
1100   \EqPiece{Z}{\PieceNameToMove}%
1101   {\Castling%
1102     {\gdef\EnPassantSquare{-}\ExecuteCastling}%
1103     {\ExecutePawnMove}}%
1104   {\gdef\EnPassantSquare{-}%
1105     \ExecutePieceMove}%
1106   \WhiteToMove%
1107   {\gdef\WhiteToMove{\False}}%
1108   {\gdef\WhiteToMove{\True}\addtocounter{move}{1}}%
1109 %(End MakeMove: WhiteToMove \BoolToString\WhiteToMove)
1110   }
1111
1112 % debugging aid
1113 %\def\MakeMove#1{#1}
1114
1115 \def\mainline{\begingroup\catcode`\#=12 \@mainline}
1116 \def\@mainline#1{\endgroup\gdef\NumberNext{\True}%
1117   \Mainline(#1 Z ){\mainlinestyle\typeset@A{#1}}}
1118
1119
1120 \def\hidemoves{\begingroup\catcode`\#=12 \@hidemoves}
1121 \def\@hidemoves#1{\endgroup\def\NumberNext{\True}%
1122   \Mainline(#1 Z )}
1123
1124
1125 \newcounter{helpnumber}
1126 \newcounter{helpnumberMove}
1127 % \def\EatNumber#1{\setcounter{helpnumber}{0}\EatNumberA(#1Z)%
1128 %   \skak@ifthenelse{\value{move}=\value{helpnumber}}%
1129 %     {\def\NumberOK{\True}}%
1130 %     {\def\NumberOK{\False}}}%
1131 \def\EatNumber#1{%
1132   \setcounter{helpnumberMove}{\arabic{move}}%
1133   \setcounter{helpnumber}{0}\EatNumberA(#1WXYZ)%
1134   \skak@ifthenelse{\value{helpnumberMove}=\value{helpnumber}}%
1135     {\gdef\NumberOK{\True}}%
1136     {\gdef\NumberOK{\False}}}%
1137 \def\EatNumberA(#1.#2){%
1138   \setcounter{helpnumber}{#1}%
1139   \LookForMove(.#2)% sets \ExpectedColur and \CurrentMove
1140   }
1141
1142 \def\LookForMove(#1#2#3#4){%
1143   \EqStr{.}{#2}% ... after the move number
1144   {\gdef\ExpectedColour{\False}%
1145     \HandleMove(#4)}%
1146   {\gdef\ExpectedColour{\True}%
1147     \HandleMove(#2#3#4)}}%
1148
1149 \def\HandleMove(#1XYZ){% executes a move if one is found
1150   \EqStr{W}{#1}%
1151   {}%
1152   {\StripMove(#1)}}
1153 \def\StripMove(#1W){% the execution of a move like 1.e4
1154   \MakeMoveMainline{#1}}
1155
1156 \def\MakeMoveMainline#1{%
1157     {\ExpectedColour%
1158       {\WhiteToMove%
1159         {\MakeMove{#1}%
1160           \gdef\ExpectedColour{\False}}%
1161         {\errmessage{mainline: black, not white, to move}}}%
1162       {\WhiteToMove%
1163         {\errmessage{mainline: white, not black, to move}}%
1164         {\MakeMove{#1}\gdef\NumberNext{\True}}}}}
1165   
1166
1167 \def\Mainline(#1 #2){%
1168   \EqStr{Z}{#1}%
1169   {}%
1170   {\NumberNext%
1171     {\EatNumber{#1}% sets \NumberOK, \ExpectedColour
1172                                 % executes a move not separated from the 
1173                                 % number with a space, eg, 1.e4
1174       \NumberOK%
1175       {\gdef\NumberNext{\False}%
1176         \Mainline(#2)}%
1177       {\errmessage{mainline: not the correct move number}}}%
1178     {\MakeMoveMainline{#1}%
1179       \Mainline(#2)}}}
1180
1181
1182 %%%%% typesetting
1183 %%% figurine notation
1184 %\input{fig1\@ptsize.clo}
1185 \newcommand{\skakfamily}{\usefont{U}{skak}{m}{n}}
1186 \DeclareTextFontCommand{\textskak}{\skakfamily}
1187
1188 \def\liftfig#1{\textskak{#1}}
1189
1190
1191 \def\styleA@opentypesetting{}
1192 \def\styleA@closetypesetting{}
1193 \def\styleA@whiteopen{.}
1194 \def\styleA@blackopen{. -}
1195 \def\styleA@beforenumber{}
1196 \def\styleA@beforewhite{ }
1197 \def\styleA@afterwhite{}
1198 \def\styleA@beforeblack{, }
1199 \def\styleA@afterblack{ }
1200
1201 \def\styleA{%
1202 \let\opentypesetting=\styleA@opentypesetting
1203 \let\closetypesetting=\styleA@closetypesetting
1204 \let\whiteopen=\styleA@whiteopen
1205 \let\blackopen=\styleA@blackopen
1206 \let\beforenumber=\styleA@beforenumber
1207 \let\beforewhite=\styleA@beforewhite
1208 \let\afterwhite=\styleA@afterwhite
1209 \let\beforeblack=\styleA@beforeblack
1210 \let\afterblack=\styleA@afterblack
1211 }
1212 %%%% the default style
1213 \styleA
1214
1215 \def\styleB@opentypesetting{}
1216 \def\styleB@closetypesetting{}
1217 \def\styleB@whiteopen{ }
1218 \def\styleB@blackopen{\ldots}
1219 \def\styleB@beforenumber{}
1220 \def\styleB@beforewhite{}
1221 \def\styleB@afterwhite{ }
1222 \def\styleB@beforeblack{}
1223 \def\styleB@afterblack{ }
1224
1225 \def\styleB{%
1226 \let\opentypesetting=\styleB@opentypesetting
1227 \let\closetypesetting=\styleB@closetypesetting
1228 \let\whiteopen=\styleB@whiteopen
1229 \let\blackopen=\styleB@blackopen
1230 \let\beforenumber=\styleB@beforenumber
1231 \let\beforewhite=\styleB@beforewhite
1232 \let\afterwhite=\styleB@afterwhite
1233 \let\beforeblack=\styleB@beforeblack
1234 \let\afterblack=\styleB@afterblack
1235 }
1236
1237 \def\styleC@opentypesetting{%
1238   \begin{tabbing}%
1239     \hspace{.2\linewidth}\=\hspace{.2\linewidth}\=%
1240     \hspace{.2\linewidth}\= \kill}
1241 \def\styleC@closetypesetting{\end{tabbing}}
1242 \def\styleC@whiteopen{}
1243 \def\styleC@blackopen{\>\ldots}
1244 \def\styleC@beforenumber{\>}
1245 \def\styleC@beforewhite{\>}
1246 \def\styleC@afterwhite{}
1247 \def\styleC@beforeblack{\>}
1248 \def\styleC@afterblack{\\}
1249
1250 \def\styleC{%
1251 \let\opentypesetting=\styleC@opentypesetting
1252 \let\closetypesetting=\styleC@closetypesetting
1253 \let\whiteopen=\styleC@whiteopen
1254 \let\blackopen=\styleC@blackopen
1255 \let\beforenumber=\styleC@beforenumber
1256 \let\beforewhite=\styleC@beforewhite
1257 \let\afterwhite=\styleC@afterwhite
1258 \let\beforeblack=\styleC@beforeblack
1259 \let\afterblack=\styleC@afterblack
1260 }
1261
1262
1263
1264 \def\mainlinestyle{\bfseries}%\let\Fig=\Figb}% could also contain
1265                                            % definitions of the 
1266                                 % various style options
1267 \def\variationstyle{}%\let\Fig=\Fign}   % as with mainlinestyle
1268
1269
1270 \def\typeset@number#1{\TypeSetAfterBlack{\afterblack}{}%
1271   \gdef\TypeSetAfterBlack{\True}%
1272   \beforenumber\typeset@numberA(#1WXYZ)}% 22: -> 22\?open
1273 \def\typeset@numberA(#1.#2){%
1274   #1\typeset@numberHandlePeriods(.#2)}
1275 \def\typeset@numberHandlePeriods(#1#2#3#4){%
1276   \EqStr{.}{#2}% ... after the number
1277   {\blackopen\gdef\TypeSetColour{\False}\gdef\TypeSetAfterWhite{\False}%
1278     \typeset@numberHandleMove(#4)}%
1279   {\whiteopen\gdef\TypeSetColour{\True}\gdef\TypeSetAfterWhite{\True}%
1280     \typeset@numberHandleMove(#2#3#4)}}
1281 \def\typeset@numberHandleMove(#1XYZ){%
1282   \EqStr{W}{#1}%
1283   {}%
1284   {\typeset@numberStripMove(#1)}}
1285 \def\typeset@numberStripMove(#1W){%
1286   \typeset@A@move{#1}}
1287   
1288 \def\typeset@A@move#1{%
1289   \TypeSetColour%
1290   {\beforewhite\mbox{\typeset@A@moveA(#1Z)}\gdef\TypeSetColour{\False}}%
1291   {\TypeSetAfterWhite{\afterwhite}{}%
1292     \beforeblack\mbox{\typeset@A@moveA(#1Z)}%
1293     \gdef\TypeSetColour{\True}\gdef\TypeSetNumberNext{\True}}}
1294 \def\typeset@A@moveA(#1#2){%
1295   \EqStr{Z}{#1}%
1296   {}%
1297   {\IsPieceName{#1}%
1298     {\xdef\temp@piece{\skak@pieceToEnglish{#1}}%
1299       \expandafter\liftfig\temp@piece}%
1300     {\EqStr{=}{#1}%
1301       {}%
1302       {\EqStr{x}{#1}%
1303         {\ensuremath{\!\!\:\times\!\!\;}}%
1304         {\EqStr{+}{#1}%
1305           {\ensuremath{\dagger}}%
1306           {#1}}}}%
1307     \typeset@A@moveA(#2)}}
1308
1309
1310 \def\typeset@A#1{\gdef\TypeSetNumberNext{\True}%
1311   \gdef\TypeSetAfterBlack{\False}\opentypesetting\typeset@AA(#1 Z )%
1312   \closetypesetting}
1313 \def\typeset@AA(#1 #2){%
1314   \EqStr{Z}{#1}%
1315   {}%
1316   {\TypeSetNumberNext%
1317     {\typeset@number{#1}% sets \TypeSetColour
1318       \gdef\TypeSetNumberNext{\False}%
1319       \typeset@AA(#2)}%
1320     {\typeset@A@move{#1}%
1321       \typeset@AA(#2)}}}
1322       
1323
1324 \def\variation{\begingroup\catcode`\#=12 \@variation}
1325 \def\@variation#1{\endgroup{\variationstyle\typeset@A{#1}}}
1326
1327 % typesetting moves with out move number
1328 \def\wmove{\begingroup\catcode`\#=12 \@wmove}
1329 \def\@wmove#1{\endgroup{\variationstyle\typeset@A@moveA(#1Z)}}
1330 \def\bmove{\begingroup\catcode`\#=12 \@bmove}
1331 \def\@bmove#1{\endgroup{\variationstyle\ldots\typeset@A@moveA(#1Z)}}
1332
1333 %%%
1334 % printing of the board
1335 \newlength{\squarelength}
1336 \newlength{\showlength}
1337 \newlength{\ranklift}
1338
1339 \def\setup@showboard#1{\font\Skak=skak#1%
1340   \setlength{\squarelength}{#1pt}%
1341   % ps setup
1342   \ps@on{\psset{unit=\the\squarelength}
1343     \edef\ps@squarecenter{(-.5,.5)}}
1344   {}
1345   \notationfont\setlength{\ranklift}{.5\squarelength-.8ex}\normalsize}
1346
1347
1348
1349 \def\tinyboard{\font\notationfont=cmss6\setup@showboard{10}}
1350 \def\smallboard{\font\notationfont=cmss8\setup@showboard{15}}
1351 \def\normalboard{\font\notationfont=cmss10\setup@showboard{20}}
1352 \def\largeboard{\font\notationfont=cmss12\setup@showboard{30}}
1353
1354 % the default
1355 \normalboard
1356
1357 \def\ToggleWhiteSquare{%
1358   \WhiteSquare{\def\WhiteSquare{\False}}{\def\WhiteSquare{\True}}}
1359
1360 \def\WhiteSquarePiece#1{%
1361   \EqPiece{E}{#1}{0}{#1}}
1362
1363 \def\BlackSquarePiece#1{%
1364   \EqPiece{E}{#1}{Z}%
1365   {\EqPiece{P}{#1}{O}%
1366     {\EqPiece{p}{#1}{o}%
1367       {\EqPiece{R}{#1}{S}%
1368         {\EqPiece{r}{#1}{s}%
1369           {\EqPiece{N}{#1}{M}%
1370             {\EqPiece{n}{#1}{m}%
1371               {\EqPiece{B}{#1}{A}%
1372                 {\EqPiece{b}{#1}{a}%
1373                   {\EqPiece{Q}{#1}{L}%
1374                     {\EqPiece{q}{#1}{l}%
1375                       {\EqPiece{K}{#1}{J}{j}}}}}}}}}}}}}
1376                           
1377 \def\FilterShowOnly#1{% piece -> piece, shows only the pieces in
1378                       % ShowOnlyList
1379   \Member{\EqStr}{#1}{\ShowOnlyList}%
1380   {#1}{E}}
1381
1382
1383 \def\Showchar#1{% square -> drawn square
1384   \WhiteSquare%
1385   {\WhiteSquarePiece{\Compose\FilterShowOnly\Get{#1}}}%
1386   {\BlackSquarePiece{\Compose\FilterShowOnly\Get{#1}}}%
1387   \ToggleWhiteSquare%
1388   % ps stuff
1389   \ps@on{\expandafter\pnode\ps@squarecenter{#1}}{}}
1390   
1391 \def\Showrank#1{% rank -> drawn rank
1392 \Skak\Apply{\Showchar}{\Rank{#1}}}
1393
1394 \def\ShowrankInverse#1{% rank -> drawn rank
1395   \Skak\Apply{\Showchar}{\Reverse{\Rank{#1}}}}
1396 %  \Skak\Apply{\Showchar}{\Rank{#1}}}
1397
1398 \def\ShowMoverWhiteNormal{\pscustom{\translate(h1)
1399 \psline{->}(1,0.25)(1,0.8)%
1400 \psframe(0.84,-0.16)(1.16,0.16)}}
1401
1402 \def\ShowMoverBlackNormal{%
1403   \pscustom[fillstyle=solid,fillcolor=gray]{\translate(h8)%
1404   \psline{->}(1,-0.25)(1,-0.8)%
1405   \psframe(0.84,-0.16)(1.16,0.16)}}
1406
1407 \def\ShowMoverWhiteInverse{\pscustom{\translate(a1)
1408 \psline{->}(1,-0.25)(1,-0.8)%
1409 \psframe(0.84,-0.16)(1.16,0.16)}}
1410
1411 \def\ShowMoverBlackInverse{%
1412   \pscustom[fillstyle=solid,fillcolor=gray]{\translate(a8)%
1413   \psline{->}(1,0.25)(1,0.8)%
1414   \psframe(0.84,-0.16)(1.16,0.16)}}
1415
1416
1417
1418 \def\show@board{%
1419   \def\WhiteSquare{\True}
1420   \vbox{\offinterlineskip
1421    \hrule height1pt 
1422    \hbox{\vrule width1pt
1423          \vbox{\hbox{\Showrank{8}}\ToggleWhiteSquare
1424                \hbox{\Showrank{7}}\ToggleWhiteSquare
1425                \hbox{\Showrank{6}}\ToggleWhiteSquare
1426                \hbox{\Showrank{5}}\ToggleWhiteSquare
1427                \hbox{\Showrank{4}}\ToggleWhiteSquare
1428                \hbox{\Showrank{3}}\ToggleWhiteSquare
1429                \hbox{\Showrank{2}}\ToggleWhiteSquare
1430                \hbox{\Showrank{1}}}%
1431          \vrule width1pt}
1432    \hrule height1pt}
1433  \setcounter{ps@inverse}{0}
1434  \ShowMover
1435  {\WhiteToMove
1436    {\ShowMoverWhiteNormal}
1437    {\ShowMoverBlackNormal}}
1438  {}
1439 }
1440
1441 \def\show@board@inverse{%
1442   \def\WhiteSquare{\True}
1443   \vbox{\offinterlineskip
1444    \hrule height1pt
1445    \hbox{\vrule width1pt
1446          \vbox{\hbox{\ShowrankInverse{1}}\ToggleWhiteSquare
1447                \hbox{\ShowrankInverse{2}}\ToggleWhiteSquare
1448                \hbox{\ShowrankInverse{3}}\ToggleWhiteSquare
1449                \hbox{\ShowrankInverse{4}}\ToggleWhiteSquare
1450                \hbox{\ShowrankInverse{5}}\ToggleWhiteSquare
1451                \hbox{\ShowrankInverse{6}}\ToggleWhiteSquare
1452                \hbox{\ShowrankInverse{7}}\ToggleWhiteSquare
1453                \hbox{\ShowrankInverse{8}}}%
1454          \vrule width1pt}
1455    \hrule height1pt}
1456  \setcounter{ps@inverse}{180}
1457  \ShowMover
1458  {\WhiteToMove
1459    {\ShowMoverWhiteInverse}
1460    {\ShowMoverBlackInverse}}
1461  {}
1462 }
1463
1464 \def\ShowrankNumber#1{%
1465 \makebox[0pt][r]{%
1466   \raisebox{\ranklift}[0cm][0cm]{%
1467     \makebox[\squarelength][r]{\notationfont#1\hspace*{.1\squarelength}}}}}
1468
1469 \def\ShowrankWithNumber#1{\ShowrankNumber{#1}%
1470 \vrule width1pt \Showrank{#1}\vrule width1pt}
1471
1472 \def\ShowrankInverseWithNumber#1{\ShowrankNumber{#1}%
1473   \vrule width1pt\ShowrankInverse{#1}\vrule width1pt}
1474
1475
1476 \def\Showfile#1{\hbox to \squarelength{\hfil\notationfont#1\hfil}}
1477 \def\Showfiles{\hfil\Showfile{a}\Showfile{b}\Showfile{c}\Showfile{d}%
1478   \Showfile{e}\Showfile{f}\Showfile{g}\Showfile{h}\hfil}
1479 \def\Showfiles@inverse{\hfil\Showfile{h}\Showfile{g}\Showfile{f}\Showfile{e}%
1480   \Showfile{d}\Showfile{c}\Showfile{b}\Showfile{a}\hfil}
1481
1482 \def\show@board@notation{%
1483   \def\WhiteSquare{\True}%
1484   \vbox{\offinterlineskip%
1485     \hrule height1pt 
1486     \hbox{\ShowrankWithNumber{8}}\ToggleWhiteSquare
1487     \hbox{\ShowrankWithNumber{7}}\ToggleWhiteSquare
1488     \hbox{\ShowrankWithNumber{6}}\ToggleWhiteSquare
1489     \hbox{\ShowrankWithNumber{5}}\ToggleWhiteSquare
1490     \hbox{\ShowrankWithNumber{4}}\ToggleWhiteSquare
1491     \hbox{\ShowrankWithNumber{3}}\ToggleWhiteSquare
1492     \hbox{\ShowrankWithNumber{2}}\ToggleWhiteSquare
1493     \hbox{\ShowrankWithNumber{1}}\ToggleWhiteSquare
1494     \hrule height1pt
1495     \vspace*{.1\squarelength}
1496     \hbox{\Showfiles}}
1497    \setcounter{ps@inverse}{0}
1498  \ShowMover
1499  {\WhiteToMove
1500    {\ShowMoverWhiteNormal}
1501    {\ShowMoverBlackNormal}}
1502  {}
1503 }
1504
1505 \def\show@board@notation@inverse{%
1506   \def\WhiteSquare{\True}%
1507   \vbox{\offinterlineskip%
1508     \hrule height1pt 
1509     \hbox{\ShowrankInverseWithNumber{1}}\ToggleWhiteSquare
1510     \hbox{\ShowrankInverseWithNumber{2}}\ToggleWhiteSquare
1511     \hbox{\ShowrankInverseWithNumber{3}}\ToggleWhiteSquare
1512     \hbox{\ShowrankInverseWithNumber{4}}\ToggleWhiteSquare
1513     \hbox{\ShowrankInverseWithNumber{5}}\ToggleWhiteSquare
1514     \hbox{\ShowrankInverseWithNumber{6}}\ToggleWhiteSquare
1515     \hbox{\ShowrankInverseWithNumber{7}}\ToggleWhiteSquare
1516     \hbox{\ShowrankInverseWithNumber{8}}\ToggleWhiteSquare
1517     \hrule height1pt
1518     \vspace*{.1\squarelength}
1519     \hbox{\Showfiles@inverse}}
1520    \setcounter{ps@inverse}{180}
1521  \ShowMover
1522  {\WhiteToMove
1523    {\ShowMoverWhiteInverse}
1524    {\ShowMoverBlackInverse}}
1525  {}
1526 }
1527
1528 % on the fly configuration
1529 \def\notationOn{\let\showboard=\show@board@notation%
1530   \let\showinverseboard=\show@board@notation@inverse}
1531 \def\notationOff{\let\showboard=\show@board%
1532   \let\showinverseboard=\show@board@inverse}
1533
1534 \def\showmoverOn{\def\ShowMover{\True}}
1535 \def\showmoverOff{\def\ShowMover{\False}}
1536
1537
1538 \def\newgame{%
1539 \fenboard{rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1}}
1540
1541
1542 %%%% storing and loading of games
1543 \newtoks\store@toks
1544 \def\savegame#1{% writes the board as fen to #1.fen
1545   \newwrite\skakstore%
1546   \immediate\openout\skakstore=#1.fen%
1547   \Fen@calculate%
1548   \immediate\write\skakstore{\temp@board}%
1549   \immediate\closeout\skakstore}
1550
1551 % loading a board from a fen file is also possible
1552 % the file #1.fen should contain nothing but a fen of
1553 % a game
1554 \def\loadgame#1{%
1555   \def\load@read{}%
1556   \newread\load@in%
1557   \openin\load@in=#1.fen\relax%
1558   \read\load@in to \load@read%
1559   \closein\load@in%
1560   \expandafter\FenBoard\load@read)}
1561
1562 %%% temporary storing of a game position, without resorting to files
1563 % \def\storegame#1{\Fen@calculate%
1564 %   \def#1{\temp@board}}
1565 % \def\restoregame#1{\expandafter\FenBoard#1)}
1566 \def\storegame#1{\Fen@calculate%
1567   \expandafter\xdef\csname chessgame.#1\endcsname{\temp@board}}
1568 \def\restoregame#1{%
1569   \edef\restore@temp{\csname chessgame.#1\endcsname}
1570   \expandafter\FenBoard\restore@temp)}
1571
1572 % end skak.sty
1573
1574
1575