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