Some Macros to Draw Crosswords^{∗}

B Hamilton Kelly^{†}

December 9, 1996

Abstract The crossword environment is intended to be used to typeset crossword

puzzles for use in newsletters, etc.

Contents

1 Introduction 1

1.1 How to Specify Clue Numbers . . . . . . . . . . 2

2 Definition of the Macros 3 2.1 Counters and Lengths . . 3 2.2 Reading and Writing the

Clues . . . . . . . . . . . . 5 2.3 Tabulating the Clues … 6 3 Creating the Grid 7 3.1 Macros used when Popu-

lating the Grid . . . . . . 8 3.2 The \clue Command . . 11 3.2.1 Finding the clue

number to be set

in the light …. 12

3.3 Populating the Cross-

word Grid . . . . . . . . . 13 3.4 Setting the Grid . . . . . 15

List of Figures

1 A Sample Crossword . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1 Introduction

As a small diversion from the statistics of computer availability, lists of new software, and the like, Computer Centre Newsletters often include a crossword for the amusement of their readers.^{1}

The macros presented in this document provide a L^{A}TEX method of typesetting these, and also assist the composer to ensure that the “grid” all goes together correctly. The grid generated is the more usual form, with black squares separating the “lights” which receive the answers to the clues. Work is in hand to be able to handle the Mephisto/Azed type of grid, in which only thicker grid lines separate the lights.

∗This file is v2.8b, dated 1996/12/06

†Especial thanks to my colleague Niel Kempson for many helpful suggestions, and to Frank Mittelbach of the Johannes Gutenberg University of Mainz, who saved me two pages of code!

1That at RMCS has a bottle of wine as a prize!

A sample crossword appears as Figure 1; I’ve left the grid blank for those who want some intellectual exercise: those who don’t can cheat by reading the source listing at the end of this article!

The whole crossword, including the \clue commands (q.v.), is bracketed within the crossword environment. This requires that the user specifies two parameters: ⟨gridsize⟩ This is a number which spe-

cifies the columns (and rows) in the square grid.

⟨visible⟩ This controls whether the answers are to be “filled in”; obviously of no use for publication, but useful whilst composing the crossword. If the parameter provided is the letter ‘Y’, then the answers will be typeset; if ‘N’ then the lights will be left blank. Any other value^{2} provided for this parameter will cause L^{A}TEX to input a yes/no answer by interaction with the user.

An analogous environment is provided especially for typesetting a smaller version of a grid showing, for example, “Last Month’s Solution”. In this of course, the answers always appear, and the clues are not printed. Again it takes two parameters:

⟨gridsize⟩ As before, this specifies the number of squares in each axis.

⟨header text⟩ Some text which will be set (in bold) above the completed grid.

Here is an example of the crossword* environment:

Last month’s solution

M O O R G N I D N A T S  T U L N D I I  N O R T O S I H T A B B A S  E T B L A R E S  C I S S A I L M U T A R R E  S O I A E A N  E C N U D D E S I R P R U S  D E C S  N O I T E L P M I E U S N E  A M G N R R L  C I A M A R A O L O P E I T  N G E R M T P S  I N I M R E T E S S A P M I  R C L N E E L  R O T A L U B M A R E P

Within the body of these environments appear a succession of \clue commands; each of these takes a total of seven (!) parameters:

⟨clue number⟩ The number of the light on the grid, for example {17}. See 1.1 below for details of how more complex specifications may be given for multiple lights.

⟨Across/Down⟩ This parameter must be either the letter ‘A’ or ‘D’, in upper-case.

⟨col number⟩ The x-coordinate of the first square of the light. The leftmost column of the grid is numbered 1.

⟨row number⟩ The y-coordinate of the first square of the light. The top-most row is numbered 1.

⟨answer⟩ The answer to the clue (or that part of it which appears in the light numbered ⟨clue number⟩). This must be a string of upper-case letters only; no spaces, punctuation, hyphens, etc.

2The lower-case letters ‘y’ and ‘n’ are also recognized

⟨text⟩ The text of the clue itself. If you want to use any L^{A}TEX macros in this text, such as \dots, each such macro must be preceded by \noexpand. This includes such macros as \&, to produce an explicit ampersand.

⟨help⟩ Anything to appear after the text, in parentheses; this will most usually be used for giving the length of the answer, such as “7” or “2,6,3-3”. Also used when the text of the clue is associated with another light when this parameter may say something like “see 14d”.

1.1 How to Specify Clue Numbers

Sometimes the solution to one clue is split amongst a number of “lights”. To cover this eventuality, provide a \clue for each of the lights involved, with the solution to that light alone given as ⟨answer⟩. All except the \clue corresponding to the first light of the solution should have a null ⟨text⟩, and the ⟨help⟩ parameter should be something like “see 7d”.

If this final parameter is totally empty, no corresponding clue number is printed: this facility would be used when the current clue is the next consecutive light, when it is usual to omit any further reference to the clue number.

The \clue for the first light of the solution should provide the entire clue as its ⟨text⟩, and the ⟨help⟩ should say something like “7,3-3”. The ⟨clue number⟩ field should consist of the number of that light, followed immediately by the text required to describe the other lights, separated from it by some non-digit character, for example, a space.

For example, suppose the clue “Bill’s desired outcome?”, has the solution ‘ACT OF PARLIAMENT’ which is to go into lights 9d and 13a. Then^{3}

\clue{13}{A}{5}{1}{PARLIAMENT}{}{see 9d}
\clue{9 {\noexpand\rm\&} 13a}{D}{1}{10}{ACTOF}%
{Bill's desired outcome?}{3,2,10}

will produce

13 (see 9d)

amongst the ACROSS clues, and

9 & 13a Bill’s desired outcome? (3,2,10)

amongst the DOWN clues

2 Definition of the Macros

\ninept \@listi We define a new font size to ensure clues are set at 9pt, no matter what style size option is in effect. This command also defines suitable parameters for list environments set in this size of type.

1 ⟨∗package⟩

2 \def\ninept{\@setsize\ninept{11pt}\ixpt\@ixpt
3 \abovedisplayskip 8.5pt plus 3pt minus 4pt

3note the \noexpand before the \rm for the \&

28 27 26  25 24 23  22 21 20  19  18 17 16 15  14 13  12 11  10 9 8  7 6 5 4 3 2 1

ACROSS

8 Points a thousand tested for witchcraft. (4) 9 Gourmet’s triumphant cry on finding

middle-cut Pacific salmon! (3) 10 One hundred stride backwards across a

Pole. (3-3) 11 Fifties’ jazz record about Eastern childs’

play. (2-4) 12 Timetable created by editor in synagogue

of Spain. (8) 13 The dialect a girl mixed up tangle around

symbolic diagram used by maritime student! (15)

15 Wire fastening bent road narrowly. (7) 17 Hammerhead consumes German company

and casts a shade. (7) 20 Strange cel alien chops to make a figure with

odd sides. (7,8) 23 Sounds like a hoarse editor came to in total!

(8) 25 Assert without proof everyone, for example,

English. (6) 26 Flourished examination of flowers. (6) 27 Floor covering discards fuming sulphuric

acid and returns to nothing. (3) 28 “Latin for a candle” to be silent note about

aircraftman? (4)

DOWN

1 Water rush noise disturbs show so! (6) 2 Mischievous child with cloth measure hesi-

tates to assemble rotor. (8) 3 Mercifully inclined to pass round ten? Nay,

about short blower! (15) 4 Sort ion? An isotron gives it a new twist!

(7) 5 Wildly and boisterously rearrange Billy

May Third, roughly. (15) 6 Satirical book or film—give odds about re-

vision of “Dune”? (4-2) 7 & 24 Premier took in a Lord Lieutenant and all played an old game in London street. (4-4)

14 Work expended in power games? (3) 16 A church circle (or part of one). (3) 18 Encircle hindrances under hair in long curls.

(8) 19 Boss over otorhinolaryngology department

undergraduate. (7) 21 Old dovecote in Parisian museum. (6) 22 Like ornamental fabric, for example, that’s

in bequest. (6) 24 (See 7)

Figure 1: A Sample Crossword

 4 \belowdisplayskip \abovedisplayskip
 5 \abovedisplayshortskip \z@ plus2pt
 6 \belowdisplayshortskip 4pt plus2pt minus 2pt
 7 \def\@listi{\itemsep 0pt
 8  \parsep \z@ plus 1pt
 9  \topsep 4pt plus 2pt minus 2pt
10 }}

2.1 Counters and Lengths

\ifnumberit \numberittrue \numberitfalse The crossword environment draws a grid (with black and white squares); each “light” into which a clue’s answer is to be written has to be numbered, and this number will be typeset (using \tiny) in the top-left corner of the first square of the light.

This style option also provides the crossword* environment, which is intended to be used to produce “last month’s solution” in a smaller grid. There is insufficient room for clue numbers to appear on the grid in this mode, so \ifnumberit is used to indicate whether the numbers should be set.

11 \newif\ifnumberit

\gr@dsize \p@csize The counter \gr@dsize is used to hold the width of the grid, as the number of

squares in each direction.

To prevent too much run-time arithmetic, the counter \p@csize is set to be one count higher than \gr@dsize.

12 \newcount{\gr@dsize}
13 \newcount{\p@csize}

\Down \Across As we move around the grid, determining whether squares are black or white, we utilize the counters \Across and \Down to keep track of our location.

14 \newcount{\Down}
15 \newcount{\Across}

2.2 Reading and Writing the Clues

\tf@acr \tf@dwn \OpenClueFiles Whilst we are determining the appearance of the grid, we copy the text of each of the clues to an auxiliary file, so that the latter may later be read back to generate the clues themselves after the grid has been printed.

This macro opens a new file, with file extension .acr, and puts into it the commands necessary to typeset the Across clues. It also opens a .dwn file, which is similarly filled with the Down clues.

Next paragraph is no longer true. I changed the coding to allow more than 6 crosswords to be used in one document. Using the approach outlined below the system would run out of write channels pretty soon. (FMi)

[ These files are created in the same manner as table-of-contents (.toc) files, etc; thus L^{A}TEX will create file “handles” with names \tf@acr and \tf@dwn. However, that would ordinarily attempt to read the given file first, and also might defer the actual opening; therefore, we start a new group in which we redefine L^{A}TEX’s @input command and TEX’s \openout primitive. ]

16 \newwrite\tf@acr
17 \newwrite\tf@dwn

18 \def\OpenClueFiles{%
19 \immediate\openout \tf@acr \jobname.acr\relax
20 \immediate\openout \tf@dwn \jobname.dwn\relax

Here’s the preliminary material that gets inserted into the .acr file.

21 \@writefile{acr}{\begin{minipage}[t]{70mm}}%
22 \@writefile{acr}{ \centerline{\textbf{\ACROSStext}}}%
23 \@writefile{acr}{ \sloppy}%
24 \@writefile{acr}{ \ninept}%
25 \@writefile{acr}{ \begin{ClueList}}%

Whilst something similar goes into the .dwn file.

26 \@writefile{dwn}{\begin{minipage}[t]{70mm}}%
27 \@writefile{dwn}{ \centerline{\textbf{\DOWNtext}}}%
28 \@writefile{dwn}{ \sloppy}%
29 \@writefile{dwn}{ \ninept}%
30 \@writefile{dwn}{ \begin{ClueList}}}
\ACROSStext \DOWNtext
31 \newcommand\ACROSStext{ACROSS}
32 \newcommand\DOWNtext{DOWN}

\CloseClueFiles After the grid has been printed, we can close the “clues” files; these will later be read back in (by the \endcrossword command) to set the text of the clues below the grid.

Before closing, we insert the material that completes the two ClueList environments; firstly across…

33 \def\CloseClueFiles{%
34 \@writefile{acr}{ \end{ClueList}}%
35 \@writefile{acr}{\end{minipage}}%

Then for the down clues.

36 \@writefile{dwn}{ \end{ClueList}}%
37 \@writefile{dwn}{\end{minipage}}%

Now we can close those files, and make them “invisible” if someone tries to write to them.

38 \immediate\closeout\tf@acr \let\tf@acr\relax
39 \immediate\closeout\tf@dwn \let\tf@dwn\relax
40 \endgraf

41 }

2.3 Tabulating the Clues

The auxiliary files contain the texts of the clues, each given as an \item for the ClueList environment. This is similar to a description list, except that overlong labels run on into the text rather than sticking out to the left.

\ClueList \ClueListLabel This sets up the ClueList environment, and defines the appearance of the label.

42 \def\ClueListlabel#1{\hspace\labelsep {\bf #1}\hss}
43 \def\ClueList{\list{}{\labelwidth\leftmargin
44 \advance \labelwidth by -\labelsep
45 \let\makelabel\ClueListlabel}}
46 \let\endClueList\endlist

\PrintClues The following macro reads in the two files (of Across and Down clues), and sets them alongside each other, separated by a vertical rule. Clues are set in the style of the ClueList environment.

47 \def\PrintClues{%
48 \centerline{%
49  \begin{tabular}{ c | c }
50  \@input{\jobname.acr}

51 &

52  \@input{\jobname.dwn}
53  \end{tabular}
54 }\endgraf

55 }

3 Creating the Grid

The remaining commands are concerned with creating (and, optionally, populating) the crossword grid

\crossword The crossword environment takes two parameters: viz. the size of the matrix, and the indication of whether the grid is to include the answers. (If the latter is omitted, L^{A}TEX will request it interactively.)

56 \def\crossword#1#2{%

We start off with a \vtop box and a group to hold everything within the environment, so as to ensure that user-entered text remains with the crossword.

57 \endgraf\leavevmode
58 \vtop\bgroup

The crossword environment uses the full-size grid, and has the lights numbered. Furthermore it doesn’t have any heading to output (see the crossword* environment).

59  \unitlength 6mm\numberittrue
60  \def\Header{}%

We now open the auxiliary files into which the clues are written, and determine (interactively if necessary) whether the answers are to be written into the grid.

61  \OpenClueFiles
62  \TestAnswers{#2}%

Finally, we generate the necessary macros to describe the grid as being entirely filled with black squares; for each square, a macro whose name is of the form \RiCi, \RxiiCviii, etc. is created. As the \clue commands are read in, these will be redefined to produce the correct appearance when the macros are later expanded.

63  \SetUpGrid{#1}}

\endcrossword When all the clues have been processed, we can invoke \FinishGrid to draw the grid. The \FinishGrid and \PrintClues commands draw the grid and tabulate the clues, respectively. By enclosing them in a vertical mode list, we ensure that they remain stuck together on one page!

The crossword environment defines \Header to be empty, but the user may give it an explicit definition within the environment; if so, we’ll print it just above the grid itself.

64 \def\endcrossword{\endgraf
65  \centerline{\Header}%
66  \hbox{\FinishGrid}%

We can now finish off the auxiliary files and then read them back in to set the text of the clues below the grid.

Finally, we complete the group and the \vtop box.

67  \CloseClueFiles
68  \hbox{\PrintClues}%
69 \egroup

70 }

\crossword* \endcrossword* The crossword* environment doesn’t need a second parameter to control printing of answers, because it always populates the grid with the answers. Instead, its second parameter provides the text to appear above the printed grid. Its actions are as for the crossword environment except that

• It prints the descriptive text above the grid.

• It always outputs the answers, without numbers.

• It draws them in a smaller box.

• It doesn’t output the clues (it doesn’t even open any auxiliary files!)

71 \expandafter\def\csname crossword*\endcsname#1#2{%
72 \unitlength 4mm\numberitfalse
73 \endgraf\leavevmode
74 \vtop\bgroup
75  \def\Header{{\bf\strut #2}}%
76  \def\answer{Y}%
77  \let\tf@dwn=\relax \let\tf@acr=\relax
78  \SetUpGrid{#1}}

79

80 \expandafter\def\csname endcrossword*\endcsname{\endgraf
81  \centerline{\Header}%
82  \hbox{\FinishGrid}%
83 \egroup

84 }

3.1 Macros used when Populating the Grid

\laterletter The following macro calls this to “place” the letters of a solution by defining a macro unique to this square.

85 \def\laterletter#1{\setsquare{\lettersquare{#1}}}

\nextletter \nextlet To determine how much space is required for the light corresponding to an answer, we need to cycle through each of the characters of the answer individually; this macro is called with two parameters — the first indicates the current setting direction (and thus accesses one of the counters \Across or \Down), whilst the second consists of the characters forming the answer followed by the string \@nil. When it is called, this “second” parameter is not enclosed in braces, so only the first token in it is accessed. The macro calls itself recursively to process the remaining characters until the \@nil has been met.

86 \def\nextletter#1#2{%

If the next token is \@nil, we’ve finished; the \let ensures that its parameter will be discarded (through the L^{A}TEX internal command \@gobble) and the recursion will then unravel.

87 \ifx#2\@nil \let\nextlet=\@gobble

Otherwise, we have another letter of the ⟨answer⟩ in #2, so we call \letterput to define the macro corresponding to this square, and count one more position occupied in the current direction.

88 \else\letterput{#2}\advance#1 by \@ne

After we’ve processed this letter, we want to call this routine recursively to process the remaining letters (if any)…

89  \let\nextlet=\nextletter

These letters cannot possibly require a starting square number, so we use a simpler macro for these later letters.

90  \let\letterput=\laterletter
91 \fi

This is where we either exit from the recursion (and \@gobble the #1 parameter) or call the macro recursively to process the next character; the direction has to be passed on as the first parameter for \nextletter or \@gobble.

92 \nextlet{#1}}

\blacktest Later we shall want to check that the square into which we are “putting” a letter is either black (and hence should be changed to contain the character) or has already had the same letter put into it by an intersecting light.

We don’t want to expand each squares’ macros, so these tests have to use the \ifx primitive; therefore, we need a macro which has the same substitution text at the highest level.

93 \def\blacktest{\blacksquare}

\ifneed@d \need@dtrue \need@dfalse As we create the macros corresponding to each occupied square, we have to decide whether it is necessary to actually perform a (re)definition of the macro; the following permits the code to determine whether such definition takes place (within

the \putsquare macro).
94 \newif\ifneed@d

\ifNoerr \Noerrtrue \Noerrfalse If an error is detected during the placement of the occupied squares, there will probably be other errors; to save pouring out yards of error messages, we arrange to suppress all but the first such; the following \newif provides this facility.

And of course we start without any errors!

95 \newif\ifNoerr
96 \Noerrtrue

\Number \Plain To determine whether a square has already been occupied, and if so, by what, we require a couple of new tokens which can be tested for as the result of a macro expansion

97 \newtoks\Number \newtoks\Plain

\blank \numbered The next two definitions can be temporarily \let to be the replacements for \lettersquare and \numbersquare respectively, for use in conjunction with the aforementioned test.

98 \def\blank#1{\Plain}
99 \def\numbered#1#2{\Number}

\letterinsquare \letterinnumbersquare When we first read the clues, we create macros which are unique to each square; later we shall redefine the macros to which the squares’ macros expand to actually perform the setting, but during the first phase we require expansions which correspond to the parameters alone. The following definitions are therefore used during the “filling” phase.

100 \def\letterinsquare#1{#1}

101

102 \def\letterinnumbersquare#1#2{#2}

\setsquare As we scan the answers for each clue, this macro is called with a parameter which specifies a call of either the \lettersquare or \numbersquare macros (with appropriate parameters).

It starts by assuming that no redefinition of the square’s macro will be required.

103 \def\setsquare#1{%
104 \need@dfalse

This macro is also called during the initialization of the grid, when we populate it with black squares; therefore, we definitely want to perform a definition of the square’s macro at this stage.

105 \ifx#1\blacksquare
106  \need@dtrue

Otherwise, let’s have a look and see what is already in the square’s macro. This test will succeed only if the square contains its initial definition (as \blacksquare).

107 \else
108  \expandafter\ifx\csname\ther@w\thec@l\endcsname\blacktest

in which case we will want to redefine the macro for this square

109  \need@dtrue

If the square has already been redefined, it means we’ve already “put” a letter (or number+letter) into its definition, so we will have to check that this definition doesn’t conflict with the new one (which is in #1). We have to expand the macros to perform this test, but don’t want that expansion to return anything except the letter which is being (and has been) placed in the square, so we make a temporary replacement for the two macros which might form our #1.

110  \else
111  \let\lettersquare=\letterinsquare
112  \let\numbersquare=\letterinnumbersquare

Now we expand the original definition and the new one; these should be the same!

113  \expandafter\if\csname\ther@w\thec@l\endcsname#1
114  \else

If they aren’t, it means the compiler of the crossword has made a mistake and has solutions which don’t correctly intersect: tell him so (well, the first time anyway). We even provide the user with some help!

115  \ifNoerr
116  \errhelp{Two intersecting lights tried to
117  put different letters^^Jin the same square!
118  You've probably confused their coordinates.^^J
119  Carry on, and examine the printout.}
120  \errmessage{Illegal redefinition of square \ther@w\thec@l.
121  Was: \expandafter\meaning\csname\ther@w
122  \thec@l\endcsname.
123  Now: \noexpand #1}
124  \Noerrfalse
125  \fi
126  \fi

So far, we don’t seem to need to change anything, but if the new #1 which has been passed to \putsquare specifies that it be numbered, we must subsume any existing definition which doesn’t have a number.

Again, we make temporary reassignments for the two potential macros, which is where we make use of the two new tokens that we invented.

127  \let\lettersquare=\blank
128  \let\numbersquare=\numbered

If the following test succeeds, we know that the new parameter specifies a number as well as a letter. This code could be expanded to check whether the original definition also specified a number, and if so ensure that they are the same, but would anybody really be silly enough to give different numbers for clues starting from the same square?!

129  \expandafter\ifx#1\Number
130  \need@dtrue
131  \fi
132  \fi
133 \fi

Now we know whether we must (re)define the macro which is unique to this square. If we must, we expand our #1, so as to get the actual number and letter passed in through that parameter, but keep the name of the placement macro itself^{4} unexpanded.

134 \ifneed@d
135  \expandafter\edef\csname\ther@w\thec@l\endcsname{\noexpand #1}
136 \fi

137 }

4This will be the first token of the parameter itself.

3.2 The \clue Command

\clue Well, here it is at last. We start off by extracting the parts (if any) which form the ⟨clue number⟩ parameter. We will therefore have the purely numeric first portion of the ⟨clue number⟩ in \cluenumber.

138 \def\clue#1#2#3#4#5#6#7{%
139 \findnumber{#1}

We now examine the second (⟨Across/Down⟩) parameter of the \clue command to determine whether this is an Across or Down clue. The clue’s ⟨text⟩ and ⟨help⟩ information is then written^{5} to the appropriate auxiliary file, and note taken of the direction in which the ⟨answer⟩ should be set into the light of the grid.

Firstly we deal with writes to the .acr file, if the ⟨Across/Down⟩ parameter is the letter ‘A’. In this case, the counter to be incremented is \Across.

140 \ifx#2A
141  \if\@empty#7\relax\else
142  \ifx\tf@acr\relax\else
143  \@writefile{acr}{  \item[#1] #6 (#7)}%
144  \fi
145  \fi
146  \let\Direction=\Across
147 \else

If this parameter is the letter ‘D’, writes go to the .dwn file, and the \Down counter is incremented.

148  \ifx#2D
149  \if\@empty#7\relax\else
150  \ifx\tf@dwn\relax\else
151  \@writefile{dwn}{  \item[#1] #6 (#7)}%
152  \fi
153  \fi
154  \let\Direction=\Down
155  \else

If this ⟨Across/Down⟩ parameter is not one of the two permitted characters, an error message is issued.

156  \errhelp{The second parameter of the \string\clue\space
157  command must be `A' or `D'}
158  \errmessage{Illegal direction (#1) specification
159  for \string\clue.}
160  \fi
161 \fi

The x and y coordinate counters are set from the ⟨column⟩ and ⟨row⟩ parameters.

162 \Across=#3 \Down=#4

\letterput The \letterput macro is defined anew at the start of each clue to create the correct definition for the first square of each light. The \setsquare macro redefines this macro internally for the remaining squares.

163 \edef\letterput##1{\noexpand\setsquare

5The writes only take place if the output files exist, and the ⟨help⟩ parameter is non-empty.

164  {\noexpand\numbersquare
165  {\noexpand\cluenumber}{##1}}}%

Now we can call \nextletter which will cycle through all the letters of the ⟨answer⟩ until meeting the token \@nil. As each letter is processed, it creates a definition for the current square, initially using the above definition, and then \laterletter for subsequent letters of the ⟨answer⟩.

Finally, we ensure that the newlines after \clue commands don’t lead to unwanted spaces being typeset.

166 \nextletter{\Direction}#5\@nil
167 \ignorespaces

168 }

3.2.1 Finding the clue number to be set in the light

\findnumber We mentioned earlier that clues with solutions which occupy more than one light require a special format for specifying their ⟨clue number⟩. If this form is required, the number of the current light is given first, with the remaining text (as it is required to be set) following, separated from the first number by some non-digit character.

The macro \findnumber is called with the entire ⟨clue number⟩ parameter passed to \clue and sets \cluenumber to expand to the first or only number found in that parameter (which should then appear in the first square of the light).

\clueNumber Of course, we require a counter in which to attempt to assemble that number:

169 \newcount\clueNumber

\special@gobble This macro is used by \findnumber to discard the unwanted portion (if any) of a ⟨clue number⟩, including the special termination token.

170 \def\special@gobble #1\@nil{}

The following mechanism to separate the first (or only) number from the remainder was suggested by Frank Mittelbach of the University of Mainz, and replaced about two pages worth of code.

171 \def\findnumber#1{%

We attempt to assign the ⟨clue number⟩ parameter to the \clueNumber counter: only that portion consisting purely of digits will actually be assigned. The remainder, if any, including the special terminator sequence \@nil is then discarded by

the \special@gobble command:
172 \afterassignment \special@gobble \clueNumber=0#1 \@nil

If the user did not provide a valid ⟨clue number⟩ (i.e. something starting with a digit), then clueNumber will have zero assigned to it — seems the user ought to be told about this!

This completes \findnumber.

173 \ifnum\clueNumber=0
174  \errhelp{The first parameter of the \string\clue\space command
175  must commence with a digit}
176  \errmessage{Illegal clue number (#1) specified
177  for \string\clue.}

178 \fi

179 }

\cluenumber This macro merely produces the number as saved in \clueNumber.

180 \def\cluenumber{\the\clueNumber}

3.3 Populating the Crossword Grid

\blackenrow For each column in a row we create a black square; effectively \setsquare will execute the definition

181 % \def\csname\ther@w\thec@l\endcsname{\blacksquare}

so that for row 3 column 6 of a 15 × 15 grid, for example, we would end up by

defining \def\RiiiCvi{\blacksquare}.

Before starting the inner loop, we need to save the definition of \body which was created for the outer loop. We cannot do this by creating a new block, since that would require that each square be defined globally, which might give rise to save stack overflow problems.

Actually with L^{A}TEX 2ε we have to save \iterate as the internals of \loop have been streamlined. With the old code only the first row was updated—this is the rpcie for using an unpublished implementation feature.

182 \def\blackenrow{\let\savediterate\iterate
183 \loop\relax\ifnum\Across>\z@
184  \setsquare{\blacksquare}%

We then shift ourselves back to the next column to the left and iterate. If we’ve reached the end of this inner loop, we re-establish the definition of \body.

Again with 2e this has to be \iterate.

185  \advance\Across by \m@ne
186 \repeat
187 \let\iterate\savediterate

188 }

\SetUpGrid This macro creates an empty grid of the appropriate size.

189 \def\SetUpGrid#1{%

We firstly make a note of the ⟨gridsize⟩ parameter in the \gr@dsize counter, from which the width and height of the grid may be computed. We also set the \p@csize counter to be one greater than \gr@dsize to save our recomputing this quantity many times over.

190 \gr@dsize=#1
191 \p@csize=#1 \advance\p@csize by \@ne

Right, this is where we start to generate the grid itself. We start at the bottom edge, because TEX loops are easiest if counting down to zero. Therefore, the \Down counter is set equal to the highest row number attainable.

192 \Down=\gr@dsize

We now start a loop, so the following code will be repeated for each row of the grid in turn. As with the rows, we process the columns from highest address to lowest, so the \Across counter is also set to the highest column attainable.

193 \loop
194  \Across=\gr@dsize

Provided we haven’t decremented down to the 0th row, we start off the inner loop to process each column: this is done by invoking a separate macro — the alternative to which would be to enclose the inner loop in a group, which would require the use of global definitions for each square.

195  \ifnum\Down>\z@
196  \blackenrow

Afterwards we move ourselves up one row, and iterate for the next row.

197  \advance\Down by \m@ne
198 \repeat

199 }

And that’s the end of \SetUpGrid!

\thec@l \ther@w \thec@l and \ther@w macros generate a string of letters, starting with ‘C’ (for column) and ‘R’ (for row) respectively. The remainder of the string consists of the lower-case Roman numeral equivalent to the current value of the appropriate counter. Such all-letter strings are used to create the names for macros which can be unique for each square of the grid.

200 \def\thec@l{C\romannumeral\Across}
201 \def\ther@w{R\romannumeral\Down}

\TestAnswers This macro interacts with the user, if necessary, to get a yes or no indication of whether the answers shall be written into the grid. No check is made that the user has entered a valid response, but the use of \answer is such that any answer apart from a ‘y’ (in upper- or lower-case) is treated as if it were ‘n’.

\f@rst To determine what parameter has been provided, or the response elicited, we will require a little macro to pass on the first token of a list terminated by a full stop.

202 \def\f@rst#1#2.{#1}

We commence by lower-casing the given parameter, setting the lower-cased version into the macro \answer.

203 \def\TestAnswers#1{\edef\next{\def\noexpand\answer{#1}}%
204 \lowercase\expandafter{\next}%

We can then extract just the first character

205 \edef\answer{\expandafter \f@rst \answer .}%

The we determine whether it’s the letter ‘y’ or ‘n’…

206 \if\answer y \else \if\answer n \else

If the ⟨visible⟩ parameter isn’t either of these, we ask the user to give us an answer!

207  \typein[\answer]{Make answers visible? [Y/N]: }\fi
208 \fi

OK, \answer now contains some response; let’s upper-case it and extract just its first character

209 \edef\next{\def\noexpand\answer{\answer}}%
210 \uppercase\expandafter{\next}%
211 \edef\answer{\expandafter \f@rst \answer .}%

212 }

3.4 Setting the Grid

\letter This is the expansion which is used (for \letterinsquare, and within the expansion of \numberedsquare) when the grid is actually being typeset from the stored squares’ macros.

213 \def\letter#1{{\put(\Across,-\Down){\makebox(1,1){\sffamily #1}}}}

\numberedsquare This macro is used (for \numbersquare) when the lights are being drawn with light numbering enabled. It puts the number (and the letter of the answer too, depending upon the definition of \letter which is current) at the current coordinate position specified by (\Across,\Down).

214 \def\numberedsquare#1#2{%
215 \put(\Across,-\Down){%

To insert the clue number, we generate it within a sub-picture, of size equal to one square.

216  \begin{picture}(1,1)(0,0)

We stick the number in the top-left corner of an (invisible) box which fills the central 81% of the area.

217  \put(0.05,0.05){\makebox(0.9,0.9)[tl]{\tiny #1}}
218  \end{picture}%

219 }

We also set the letter in the square (depending upon the definition of \letter which applies.

220 \letter{#2}}

\unnumberedsquare Despite its name, this macro is invoked (through \numbersquare) for those squares which would ordinarily carry a light’s number, were it not for the fact that the numbers have been suppressed by the crossword* environment.

It just discards the ⟨clue number⟩ given in the first parameter and sets the current letter by invoking \letter, which uses the second parameter…

221 \def\unnumberedsquare#1{\letter}

\FinishGrid Now we can process all the stored macros which define the appearance of each square in the grid, and thus generate the printed version thereof, using L^{A}TEX’s picture environment.

This command makes appropriate redefinitions of some macros which produced different effects during the filling of the grid.

222 \def\FinishGrid{%

If the customer doesn’t want the letters put into the grid, then we need only throw away any parameter to letter.

223 \if\answer Y \else \let \letter=\@gobble \fi

As stated in the introduction, when typesetting the grid in a smaller version, there is insufficient space to include the numbers for the lights; by testing \ifnumberit we can determine whether a macro which expands to \numbersquare shall result in a number being printed or not.

224 \ifnumberit
225  \let\numbersquare=\numberedsquare

226 \else
227  \let\numbersquare=\unnumberedsquare
228 \fi

Anything that’s been stored as a \lettersquare is “set” using the \letter macro (which we might have just \let equal to \@gobble).

229 \let\lettersquare=\letter

\blacksquare Any black squares that are still left in the grid are set by means of this command:

230 \def\blacksquare{%

The black square itself is merely a rule of the appropriate dimensions.

231  \put(\Across,-\Down){\rule{\unitlength}{\unitlength}}}

Now we come to the actual body of \FinishGrid. We start off at the bottom-most row of the grid…

232 \Down=\gr@dsize

The whole grid is created in a centered \hbox in a picture environment. By offsetting the origin negatively, we can address each row by simply negating the y coordinate; thus column x in the highest row is (x, −1).

233 \centerline{%
234  \begin{picture}(\p@csize,\p@csize)(1,-\p@csize)

We now cycle through each of the rows. The first thing we output is a horizontal rule of the full width of the grid, one such rule being generated for each row of the grid, providing the horizontal lines across vertical lights.

235  \loop\ifnum\Down>\z@
236  \put(1,-\Down){\line(1,0){\the\gr@dsize}}

Now we are about to cycle across all the columns of the current row; again, it’s convenient for us to work backwards to the left…

237  \Across=\gr@dsize

To do this we need an inner loop; this has to be inside a group so as to isolate the effects of its \repeat command.

238  {\loop \ifnum\Across>\z@

To set the appropriate object in this square, we merely invoke the macro which has been associated with the square. Thus we’ll end up with a black square, or a numbered or plain square, the latter two of which may also contain a letter.

239  \csname\ther@w\thec@l\endcsname

Now we advance to the next column and iterate. That’s the end of the inner loop for each of the columns of the current row.

240  \advance\Across by \m@ne
241  \repeat

242 }%

Now we can decrement down to the next row and iterate through the rows.

243  \advance\Down by \m@ne
244  \repeat

We’ve so far drawn a horizontal line under each of the rows; the next \put draws a final line above the top-most row.

245  \put(1,0){\line(1,0){\the\gr@dsize}}

Similarly, a short loop can draw vertical rules at the left-hand edge of each of the columns, starting with a line on the left of an imaginary column to the right of the whole grid, which will therefore form a line to the right of the final column.

246  \Across=\p@csize
247  \loop\ifnum\Across>\z@
248  \put(\Across,0){\line(0,-1){\the\gr@dsize}}
249  \advance\Across by \m@ne
250  \repeat

And that completes the picture.

251  \end{picture}%

252 }% 253 } 254 ⟨/package⟩

Finally, here’s the input which produced the crossword in figure 1

       \begin{crossword}{15}{N}
          \input{grid-1}
       \end{crossword}

255 ⟨∗grid0⟩

256 \clue{1}{A}{3}{1}{PERAMBULATOR}{Stroller carrying the baby}{12}
257 \clue{8}{A}{1}{3}{IMPASSE}{Eastern note returned about predicament resulting
258  in deadlock}{7}
259 \clue{9}{A}{9}{3}{TERMINI}{Many ends brought back in one minute soak}{7}
260 \clue{11}{A}{1}{5}{TIEPOLO}{Venetian painter to draw Spanish gipsy dance?}{7}
261 \clue{12}{A}{9}{5}{ARAMAIC}{Semitic language of one in charge of following a
262  sheep}{7}
263 \clue{13}{A}{1}{7}{ENSUE}{Follow three directions and bend eastward}{5}
264 \clue{14}{A}{7}{7}{IMPLETION}{Filling feeble-minded person who lost his head
265  about one}{9}
266 \clue{16}{A}{1}{9}{SURPRISED}{Rip apart with duress taken unawares}{9}
267 \clue{19}{A}{11}{9}{DUNCE}{Stupid person from hill church}{5}
268 \clue{21}{A}{1}{11}{ERRATUM}{Published correction --- return walled-up
269  sailor}{7}
270 \clue{23}{A}{9}{11}{LIASSIC}{Lower Jurassic sea trip backwards [thus]}{7}
271 \clue{24}{A}{1}{13}{SABBATH}{Midnight meeting of witches at hospital on rest
272  day?}{7}
273 \clue{25}{A}{9}{13}{ISOTRON}{Sort ion with an accelerator?}{7}
274 \clue{26}{A}{2}{15}{STANDINGROOM}{Substitute husband relegated here at
275  crowded wedding}{8-4}
276 \clue{1}{D}{3}{1}{PEPPERS}{Showers band with lonely hearts?}{7}
277 \clue{2}{D}{5}{1}{RESTORE}{Concerning money saved --- reinstate to former
278  owner}{7}
279 \clue{3}{D}{7}{1}{MNEMONICS}{No-one in higher degree produces memory
280  joggers}{9}
281 \clue{4}{D}{9}{1}{ULTRA}{Enigmatic secret of WW\,I\kern-.1em I?}{5}
282 \clue{5}{D}{11}{1}{ACREAGE}{Current about time flows over measured area}{7}

283 \clue{6}{D}{13}{1}{ORIGAMI}{Maybe magic endlessly raised before one with
284  Japanese artistic skill}{7}
285 \clue{7}{D}{1}{2}{LISTLESSNESS}{Enroll fewer once before head suffering a
286  languid malaise}{12}
287 \clue{10}{D}{15}{3}{INCANDESCENT}{White-hot Peruvian reorganized objects
288  covering small coin}{12}
289 \clue{15}{D}{9}{7}{PEDALLING}{Penny led a rearranged fish engaging in cyclic
290  activity!}{9}
291 \clue{17}{D}{3}{9}{RAREBIT}{Welsh toast? An unusual drill!}{7}
292 \clue{18}{D}{5}{9}{RETRAIN}{Keep in mind, take in, and acquire new
293  skills}{7}
294 \clue{19}{D}{11}{9}{DIABOLO}{Twice a high ball thrown up round a two-headed
295  top}{7}
296 \clue{20}{D}{13}{9}{NOSTRUM}{No good man with spirit offers quack remedy}{7}
297 \clue{22}{D}{7}{11}{MAHDI}{I would shortly overact, sent up, and the
298  downfall of Gordon}{5}

299 ⟨/grid0⟩

300 ⟨∗grid1⟩

301 \clue{8}{A}{1}{2}{SWAM}{Points a thousand tested for witchcraft.}{4}
302 \clue{9}{A}{6}{2}{OHO}{Gourmet's triumphant cry on finding middle-cut
303  Pacific salmon!}{3}
304 \clue{10}{A}{10}{2}{ICECAP}{One hundred stride backwards across a
305  Pole.}{3-3}
306 \clue{11}{A}{1}{4}{BOPEEP}{Fifties' jazz record about Eastern childs'
307  play.}{2-4}
308 \clue{12}{A}{8}{4}{SCHEDULE}{Timetable created by editor in synagogue
309  of Spain.}{8}
310 \clue{13}{A}{1}{6}{THALASSOGRAPHER}{The dialect a girl mixed up tangle
311  around symbolic diagram used by
312  maritime student!}{15}
313 \clue{15}{A}{1}{8}{HAIRPIN}{Wire fastening bent road narrowly.}{7}
314 \clue{17}{A}{9}{8}{UMBRAGE}{Hammerhead consumes German company
315  and casts a shade.}{7}
316 \clue{20}{A}{1}{10}{SCALENETRIANGLE}{Strange cel alien chops to make a
317  figure with odd sides.}{7,8}
318 \clue{23}{A}{1}{12}{AMOUNTED}{Sounds like a hoarse editor came to in
319  total!}{8}
320 \clue{25}{A}{10}{12}{ALLEGE}{Assert without proof everyone, for
321  example, English.}{6}
322 \clue{26}{A}{1}{14}{FLORAL}{Flourished examination of flowers.}{6}
323 \clue{27}{A}{8}{14}{NIL}{Floor covering discards fuming sulphuric acid
324  and returns to nothing.}{3}
325 \clue{28}{A}{12}{14}{TACE}{``Latin for a candle'' to be silent note
326  about aircraftman?}{4}
327 \clue{1}{D}{2}{1}{SWOOSH}{Water rush noise disturbs show so!}{6}
328 \clue{2}{D}{4}{1}{IMPELLER}{Mischievous child with cloth measure
329  hesitates to assemble rotor.}{8}
330 \clue{3}{D}{6}{1}{COMPASSIONATELY}{Mercifully inclined to pass round
331  ten? Nay, about short blower!}{15}
332 \clue{4}{D}{8}{1}{TORSION}{Sort ion? An isotron gives it a new
333  twist!}{7}
334 \clue{5}{D}{10}{1}{DITHYRAMBICALLY}{Wildly and boisterously rearrange
335  Billy May Third, roughly.}{15}
336 \clue{6}{D}{12}{1}{SENDUP}{Satirical book or film---give odds about

337  revision of ``Dune''?}{4-2}
338 \clue{7 {\noexpand\rm\&} 24}{D}{14}{1}{PALL}{Premier took in a Lord
339  Lieutenant and all played an
340  old game in London street.}{4-4}
341 \clue{14}{D}{14}{6}{ERG}{Work expended in power games?}{3}
342 \clue{16}{D}{2}{8}{ARC}{A church circle (or part of one).}{3}
343 \clue{18}{D}{12}{8}{RINGLETS}{Encircle hindrances under hair in long
344  curls.}{8}
345 \clue{19}{D}{8}{9}{STUDENT}{Boss over oto\-rhino\-laryng\-o\-logy
346  department undergraduate.}{7}
347 \clue{21}{D}{4}{10}{LOUVRE}{Old dovecote in Parisian museum.}{6}
348 \clue{22}{D}{14}{10}{LEGACY}{Like ornamental fabric, for example,
349  that's in bequest.}{6}
350 \clue{24}{D}{2}{12}{MALL}{}{See {\bf 7}}

351 ⟨/grid1⟩

352 ⟨∗exa0⟩

353 \documentclass{article}
354 \usepackage{crosswrd}
355 \pagestyle{empty}
356 \setlength\topmargin{-1in}
357 \setlength\textheight{10.7in}

358

359 \begin{document}
360  \begin{crossword}{15}{?}
361  \input{grid0}
362  \end{crossword}
363 \end{document}

364 ⟨/exa0⟩

365 ⟨∗exa1⟩

366 \documentclass{article}
367 \usepackage{crosswrd}
368 \pagestyle{empty}
369 \setlength\topmargin{-1in}
370 \setlength\textheight{10.7in}
371 \begin{document}
372  \section*{A Sample Crossword}
373  \textit{(Chamber's Twentieth Century dictionary)}
374  \begin{crossword}{15}{?}
375  \input{grid1}
376  \end{crossword}
377  \begin{crossword*}{15}{Solution to grid 0}
378  \input{grid0}
379  \end{crossword*}
380 \end{document}

381 ⟨/exa1⟩