1 @. Plain TeXnicard (T/M/I edition) -- version 0.1
2 @. This file is licensed under the same terms as TeXnicard itself.
4 @. As a special exception, if you create a document which uses this file,
5 @. and link it with this file, this file does not by itself cause the
6 @. resulting document to be covered by the GNU General Public License.
7 @. This exception does not however invalidate any other reasons why the
8 @. document might be covered by the GNU General Public License. If you
9 @. modify this file, you may extend this exception to your version of the
10 @. file, but you are not obligated to do so. If you do not wish to do so,
11 @. delete this exception statement from your version.
14 \font\logo=logo10 \def\MF{{\logo META}\-{\logo FONT}}
15 \font\biglogo=logo10 scaled\magstep2 \def\bigMF{{\biglogo METAFONT}}
18 This is Plain \TeX nicard, a standard set of macros and definitions which
19 can be used with \TeX nicard. In most cases you will use this file with
20 another template for the game which you are making cards of. (Which means,
21 this file is called a ``meta-template''.)
23 Subroutines defined here are described using a stack effect notation,
24 similar to the stack notation commonly used in Forth.
30 Here are some utility codes which are useful to use with \TeX nicard, just
31 some miscellaneous stuff that doesn't belong elsewhere and should be
32 defined before the other things are defined.
34 The first thing is the \.{Finally} command, which is just a convenient way
35 to add things which should be done at the end of the processing, after the
36 metatemplate, template, and set, have all been loaded and processed.
46 This subroutine is used to compose functions. Just using \.+ to do this
47 will not always work, because they might be numbers and the premature
48 exiting and required spaces between numbers can easily cause that not to
52 @. ( code code -- code )
56 Here is a simple code to determine whether a value on the stack is a
64 Compute power of ten. (It is used in the next code after this one.)
67 @. ( exponent -- result )
71 This is used to make a number displayed with decimal places. The input
72 will be integer, but it is displayed as a fractional number with decimal
73 places, such as ``\.{325.04}'' when the number is in units of $1/100$ you
74 can make real display units.
76 This is used when doing statistics calculations, such as average, standard
77 deviation, variance, etc.
80 @. ( number places -- string )
81 <(Pow10)xs2dl2%l2+BAD[.]r+rl2/Br+>
83 @. --- Table operations ---
86 Here we are defining some subroutines to deal with tables. Please note
87 that the \.{table-number} parameter can be written like \.{`S} to refer
88 to the \.S table, for example.
90 The \.{Mark\_Table} command is used for marking a value in many positions
91 of a table all at once. The list of indices is given as a string. Example:
92 \.{[aeiou]1`v(Mark\_Table)x}
95 @. ( string-of-indices value table-number -- )
96 <[:]ra+s2s1[Al1rl2xY]xD>
99 The \.{Copy\_Table} command copies a table; it is sometimes very useful.
102 @. ( src-table-number dst-table-number -- )
103 <[:]ra+s2[;]ra+s10[ddl1xrl2x1+d256-0 1diQY]xD>
106 The \.{Fill\_Table} command fills the entire table with one value. This
107 might be used to reset a table to zero, for instance.
110 @. ( value table-number -- )
111 <[:]ra+s2s10[dl1rl2x1+d256-0 1diQY]xD>
114 Here is a command to create a table that maps every number to itself. The
115 resulting table might then be modified.
118 @. ( table-number -- )
119 <[:]ra+s2256[1-ddl2xd1d0iQY]xD>
121 @. --- String operations ---
124 Here are subroutines for a few common string operations.
127 @. ( string char -- left right )
128 <[]s1s2[Adl2-0 1 0iQal1r+s1Y]xDl1r>
131 @. ( string -- string )
135 @. ( string amount -- string )
139 The \.{Translate} command is used to change characters in a string
140 according to a table. It can also be used to convert a string into
141 uppercase, or into lowercase.
144 @. ( string table-number -- string )
145 <[]s1[;]ra+s2[Al2xal1r+s1Y]xDl1>
148 @. ( string -- string )
152 The other string operation is to convert into the format expected by Plain
153 \TeX, for making reports and so on. Some characters such as \.\{ and \.\}
154 will not be used, but \.\&, \.\$, \.\#, and \.\% are a bit common. A new
155 table \.e is used to select which ones.
159 [&$%#]1`e(Mark_Table)x
162 @. ( string -- string )
163 <[]s1[Ad;e[]d[\]il1r+s1al1r+s1Y]xDl1>
165 @. --- Natural sorting ---
168 You can read the description of the natural sorting algorithm in the
169 \TeX nicard program book. It requires the \.S table to be filled in, in
170 order to work. That is what this chapter of this file is for.
173 @. ( string-of-characters -- )
174 <128s1[Al1r:Sl11+s1Y]xD>
177 @. ( string-of-characters -- )
181 @. ( string-of-characters -- )
182 <64s1[Al1r:Sl11+s1Y]xD>
185 Most characters are treated like spaces/punctuation (category 2). Field
186 terminators and so on are treated as the end of the text to match. This
187 file configures it to use the English alphabet; in your own templates, you
188 might add accented letters to allow different languages to be used, if you
189 want to make a card game with French writing or some other language.
193 0 4:S 0 9:S 0 30:S 0 31:S
194 [0123456789](Sort_Digits)x
195 [ABCDEFGHIJKLMNOPQRSTUVWXYZ](Sort_Letters)x
196 [abcdefghijklmnopqrstuvwxyz](Sort_Letters)x
200 @. --- Set information ---
203 The title is stored here at first. It is blank, so that you can just use
204 \.{@@S Title} to type the new one.
209 @S Title_To_Plain_TeX
210 (Title)L(To_Plain_TeX)x
212 @. --- \TeX\ definitions ---
215 Here we check the that the Plain \TeX nicard format is loaded. If it is
216 not loaded, it will just stop, so that the user can try again, this time
217 with loading the correct format.
220 {\def\0{texnicard}\ifx\0\fmtname\else\message{** Wrong format! **}\end\fi}
222 @. --- \bigMF\ definitions ---
225 Now, {\MF} definitions for the set symbol.
227 The first thing to do is to set up the font-making mode, which is what all
228 font programs in {\MF} usually start with. Next is the font identifier.
232 font_identifier "SET_SYMBOL";
235 We will allow up to sixteen symbols per card set, and up to sixteen modes
236 for each symbol. The border and fill of the symbol each need separate mode
237 numbers (if you have both of these things), as well as mode numbers for
238 the different sizes and aspect ratios it is rendered at, and any other
239 effects which are dealt with in \MF.
241 The symbol number is the high nybble and the mode number is the low nybble
242 of the character code number.
244 Some variables and macros are defined for keeping track of the modes.
245 After one of these macros, you can enter the transformation. Note the size
250 transform modes[]trans;
251 numeric modes[]thick,modes[]size;
253 def border_mode(expr n,s,t) =
257 modes[n]trans:=identity
260 def fill_mode(expr n,s) =
263 modes[n]trans:=identity
267 Here is how a symbol is being made. It will ship characters for all of
268 the modes which have been set up for this symbol. There are various
269 commands which will then be used inside of the symbol.
272 def make_symbol(expr n)(text t) =
274 if known modes[i]size:
275 currenttransform:=(modes[i]trans) yscaled aspect_ratio;
276 beginchar(16*n+i,modes[i]size,modes[i]size,0);
278 if not _mode.fil: pickup pencircle scaled _mode.thick; fi
285 def _mode = modes[mode_num] enddef;
288 Various prefixes are used to control how the drawing commands are used.
293 def asborder text t =
300 def hole text t = let fill=unfill; t; let fill=fill_; enddef;
301 def noborder text t = if _mode.fil: t; fi enddef;
302 def nofill text t = if not _mode.fil: t; fi enddef;
305 Here comes the commands which draw shapes.
309 if _mode.fil: cullit; fill else: draw fi p;
311 def Circle(expr p,r) =
312 Shape((fullcircle scaled r) shifted p);
314 def Rectangle(expr a,b) =
315 Shape(a--(xpart a,ypart b)--b--(ypart a,xpart b)--cycle);
319 Finally, the set symbol file must be correctly terminated.
322 [(set_symbol.mf)dL[ bye;]+rS](Finally)x
327 Here is patterns for making plurals of English. You can add exceptions in
328 your template in case the game uses special words. (The rules and word
329 list is based on Damian Conway's list.)
331 These plurals are conditionally selected based on whether the name
332 \.{(English)} is given a nonzero value in the template which includes this
333 one; this way you can disable them if you do not need English.
335 Mostly Anglicized plurals are used here due to simpler rules.
342 But first, the specification of characters in a word form rule.
346 [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]
353 @. Normal plural rules "-s" "-es" (level 5 and 10)
359 @. Rules for "-ys" "-ies" (level 10 and 15)
367 @. Rules for "-ves" (level 10 and 15)
379 @. Uninflected nouns (level 500)
404 @. Uninflected suffix (level 500)
412 @. Irregular suffix (level 500)
413 >`:(Split_String)xrBADr500 0
424 @. Irregular plurals (level 1000)
425 >`:(Split_String)xBrBr1000 0
426 =ephemeris:ephemerides
427 =soliloquy:soliloquies
431 @. "-um" to "-a" (level 750)
441 @. "-" to "-im" (level 750)
447 @. "-a" to "-ae" (level 750)
453 @. For a complete set of category tables, please see:
454 @. http://www.csse.monash.edu.au/~damian/papers/HTML/Plurals_AppendixA.html
458 @. --- English numbers ---
461 There is another thing controlled by the \.{(English)} parameter.
462 Converting numbers to words is also conditionally enabled. These can be
463 grouped into three kinds: ``1'' to ``one'', ``1'' to ``first'', and ``1''
471 The last case, ``1'' to ``1st'', is simplest, so it comes first.
474 @. ( number -- text )
475 <[th]s0[st]s1[nd]s2[rd]s3
477 100%d10%r10/1-1 0 1i*
482 The other two are also simple, if they are done using a word form table.
483 So, that is what we will do. Word form table 1 will be used for numbers
528 Now we have the definition for \.{(1\_one)} and \.{(1\_first)}. The second
529 one is mostly like the first one, so it will call the first one. You
530 should not input negative numbers to these subroutines, because it will
531 just assume it is zero.
534 @. ( number -- text )
536 l1100%B1WD@. Get words for number 1-19
537 l1100%20-[](1_one_20to99)dix@. Deal with prefix for 20-90
538 l1100/10%s2[hundred](1_one_1000)x@. Deal with hundreds
539 l11000/1000%s2[thousand](1_one_1000)x@. Deal with thousands
540 l11000000/1000%s2[million](1_one_1000)x@. Deal with millions
541 l11000000000/s2[billion](1_one_1000)x@. Deal with billions
545 AD@. Remove the tens digit left from before
546 l110/10%B[t]+1WD@. Make word for 20-90
547 rdZ0[][-]ir+@. Figure out whether a hyphen should be added
548 +@. Join the tens word with the ones word
552 l2(1_one)x@. A recursive call, get word for this number
553 [ ]+r+@. Add the suffix
554 rdZ0[][ ]ir+@. Figure out if a space is needed
559 @. ( number -- text )
564 @. --- Card lists ---
567 We have a list storing pointers to the cards and data used for sorting and
568 for statistics. One use of this sorting is to automatically number the
569 cards in the correct order regardless of the order in which they are
572 Please note there is maximum 32 fields!
574 Register \.{(Card\_Field\_Number)} selects which is the number for the
575 next field. Register \.{(Field\_Command)} stores a subroutine number (or a
576 subroutine code) so that it will decide what to do with the fields. (This
577 is similar to the current ``mood'' in BBL/Abundance.)
580 0(Card_Field_Number)S
583 @. >( ?? field-number -- ?? )
588 (Card_Field_Number)LB[(Field_Command)Lx]+rS
589 (Card_Field_Number)dL1+rS
592 Just before listing the fields to sort (and group) by, it should clear the
593 current list so that it can be filled in by fresh.
600 Now here are some of the moods of card fields. Also the register \.9 is
601 used as a parameter sometimes.
603 At first, we have the list of sort orders. There is also a special value
604 to record the sorted position so that they can be numbered even after
605 changing sorting to something else. They can also be sorted based on the
606 previous results in this way.
613 `As9(_Sort_Order)(Field_Command)S
615 @S Primary_Descending
617 `Zs9(_Sort_Order)(Field_Command)S
619 @S Secondary_Ascending
621 `as9(_Sort_Order)(Field_Command)S
623 @S Secondary_Descending
625 `zs9(_Sort_Order)(Field_Command)S
627 @S Record_Sorted_Position
629 `Rs9(_Sort_Order)(Field_Command)S
632 Next is the command to write fields. It will be the one usually used while
633 in a card area, and then you can just use multiple fields to write to
634 without specifying writing every time.
641 We also need reading fields! It can also be used multiple times, like the
649 Some words might be placed in names so that their numbers can be placed in
650 card lists and compared. A conversion table \.n is used to change any
651 parentheses that might be inside the text into control characters and back
652 again, since parentheses are not allowed in any register names.
654 Each such name will begin with an asterisk (which is automatically added
655 and removed as necessary). This is so that it will not interfere with
656 existing names for commands and so on.
658 These registers also have a value, although the present program does not
659 use it. You might find a use for it in your own templates, though.
671 `n(Translate)x[)]+[(*]r+x
673 @. --- Statistics ---
676 There are two field moods for doing statistics with fields. One for
677 setting grouping, and one for selecting the statistics field.
679 The current group by field is saved in register \.9.
686 Now it might be useful to compute the statistics. Statistics includes:
687 mean, median, minimum, maximum, and variance.
689 Variance is the mean of the square minus the square of the mean. In
690 mathematical notation: $$\sigma^2=\left({s_2\over s_0}\right)-\left(
691 {s_1\over s_0}\right)^2$$
693 In each group, the code will be executed, storing statistics as follows:
694 count in \.0, sum in \.1, sum of squares in \.2, minimum in \.3, maximum
695 in \.4, median in \.5, mean in \.6, variance in \.7, and stat decimals
698 You need to set the number of decimal places in statistics, first.
704 (Stat_Decimals)L(Pow10)xs8
709 Now, in order to calculate the variance, we will rearrange the equation
710 above in order to increase accuracy and allow any number of decimal places
711 in the result. The rearranged equation is as follows:
712 $$\sigma^2={s_2s_0-s_1^2\over s_0^2}$$
714 Now all multiplications are done first before division, in order to
715 minimize rounding errors. However, this equation still does not deal with
716 decimal places. Here is the final equation including decimal places (where
717 $d$ is the number of decimal places, and $r$ is the integer result which
719 $$r=\left\lfloor{10^d(s_2s_0-s_1^2)\over s_0^2}\right\rfloor$$
721 Sorting is done here, for single-dimensional statistics. (Two-dimensional
722 statistics comes later.)
730 [<d`al9:Gr(_Statistics_Set)r(Compose)xrl9g>](Field_Command)S
733 Text statistics are printed out using Plain \TeX. The resulting \.{DVI}
734 file should be processed normally, rather than with \TeX nicard. If any
735 special fonts or parameters are needed, they should be specified in the
738 The first thing is to set up the date and time for the statistics report.
746 \multiply\minutes by -60
747 \advance\minutes by \time
748 \def\lznum#1{\ifnum#1<10 0\fi\number#1}@. Print leading zero
749 \def\date{\hbox{%@. Do not break the line within the date/time
750 \the\year/\lznum\month/\lznum/day
751 \quad \lznum\hours:\lznum\minutes
755 At end end of the file, \z{bye} will be added. This finishes a {\TeX}
759 [(statistics.tex)dL10a[\bye]++rS](Finally)x
762 Some of the parameters will be changed, such as having no paragraph
763 indentation and so on. French spacing is selected to ensure the names are
764 typed as names rather than as sentences.
766 Also, the footer line will now show the date, time, and set title, in
767 addition to the page number.
775 \def\title{@^C(Title_To_Plain_TeX)}
776 \def\clap#1{\hbox to 0pt{\hss#1\hss}}
777 \footline={\tenrm\rlap\title\hss\clap\folio\hss\llap\date}
780 There are {\TeX} macros for making the tables with the data.
784 \tabskip=4pt plus 1fil
785 \halign to\hsize{##\hss&&\hss$##$\cr
786 \omit\hss\bf#1\hss\span\relax\cr
791 @. --- Graphical statistics ---
794 When doing statistics, you will want to create: pie graphs, bar graphs,
795 minimum, maximum, and so on.
797 Pie graphs can be created with \MF, while bar graphs can just use rules in
798 a {\TeX} document. Both of these things will be defined here.
800 First thing shall be the line thickness parameter and the pie radius
801 parameter, both of which can be customized.
810 This output file generates the fonts for the pie slices. Please note the
811 total number of slices in all pages plus the total number of pages of pie
812 graphs must not exceed 256.
814 @F statistics_graph.mf
817 line_thickness=@^C(Line_Thickness);
818 pie_radius=@^C(Pie_Radius);
819 pie_radius#=@^C(Pie_Radius)#;
820 picture pie_outline;@.Circle and lines separating slices
821 slice_val:=0;@.Current total value of slices so far
822 slice_total:=0;@.Current total of all slices in this group
823 character_number:=0;@.Next character number
825 def new_pie(expr t) =
829 pickup pencircle scaled line_thickness;
830 draw fullcircle scaled pie_radius;
831 pie_outline:=currentpicture;
834 def send_picture(expr p) =
835 charcode:=character_number;
836 charwd:=chardx:=0; chardp:=charht:=pie_radius#;
837 character_number:=character_number+1;
842 send_picture(pie_outline);
846 Some explanation should seem appropriate here. You make a filled shape
847 with the center of the circle, the two end points, and two points in
848 between. Now you cut it off so that the slice of the circle remained.
850 @F statistics_graph.mf
851 vardef ro_slice(expr a,b) =
852 (a*pie_radius,0) rotated (360(slice_val+b)/slice_total)
855 def add_slice(expr v) =
857 fill (0,0)--ro_slice(3,v)--ro_slice(3,2v/3)
858 --ro_slice(3,v/3)--ro_slice(3,0)--cycle;
859 fill fullcircle scaled pie_radius;
860 cull currentpicture keeping (2,2);
861 slice_val:=slice_val+v;
862 currentpicture:=pie_outline;
863 draw (0,0)--ro_slice(1,0);
864 pie_outline:=currentpicture;
868 Next we do the beginning of the {\TeX} file for statistics, and doing the
871 @F statistics_graph.tex
872 {\def\0{texnicard}\ifx\0\fmtname\else\message{** Wrong format! **}\end\fi}
874 \def\line_thickness{@^C(Line_Thickness)}
875 \font\piefont=statistics_graph
877 @. --- End of file ---