Gamma and other image manipulation commands
[TeXnicard.git] / system / tmiplain.cards
blobfb23cd3c0cab51bace426419bf4a3ced373a57f0
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}}
16 \advance\hfuzz by 4pt
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.
27 @. --- Utilities ---
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.
39 []sZ
41 @S Finally
42 @. ( subroutine -- )
43 B[x]+lZr+sZ
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
49 work.
51 @S Compose
52 @. ( code code -- code )
53 rB[x]+rB[x]++
56 Here is a simple code to determine whether a value on the stack is a
57 number or a string.
59 @S Data_Type
60 @. ( value -- type )
61 BArD91-0 1di
64 Compute power of ten. (It is used in the next code after this one.)
66 @S Pow10
67 @. ( exponent -- result )
68 1r[d1d0iQ1-r10*rY]xD
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.
79 @S Decimals
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}
94 @S Mark_Table
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.
101 @S Copy_Table
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.
109 @S Fill_Table
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.
117 @S Identity_Table
118 @. ( table-number -- )
119 <[:]ra+s2256[1-ddl2xd1d0iQY]xD>
121 @. --- String operations ---
124 Here are subroutines for a few common string operations.
126 @S Split_String
127 @. ( string char -- left right )
128 <[]s1s2[Adl2-0 1 0iQal1r+s1Y]xDl1r>
130 @S Reverse_String
131 @. ( string -- string )
132 <[]s1[Aal1+s1Y]xDl1>
134 @S Cut_Beginning
135 @. ( string amount -- string )
136 [1-d0 1 0iQrADrY]xD
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.
143 @S Translate
144 @. ( string table-number -- string )
145 <[]s1[;]ra+s2[Al2xal1r+s1Y]xDl1>
147 @S Sentence_Case
148 @. ( string -- string )
149 A;Uar+
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.
158 0`e(Fill_Table)x
159 [&$%#]1`e(Mark_Table)x
161 @S To_Plain_TeX
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.
172 @S Sort_Letters
173 @. ( string-of-characters -- )
174 <128s1[Al1r:Sl11+s1Y]xD>
176 @S Sort_Priority
177 @. ( string-of-characters -- )
178 <[Ad;S64+r:SY]xD>
180 @S Sort_Digits
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.
192 2`S(Fill_Table)x
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
197 [IX](Sort_Priority)x
198 3`,:S 4`.:S
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.
206 @E Title
207 [](Title)S
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.
219 @F cards.tex
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.
230 @F set_symbol.mf
231 mode_setup;
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
246 is in sharp units.
248 @F set_symbol.mf
249 boolean modes[]fil;
250 transform modes[]trans;
251 numeric modes[]thick,modes[]size;
253 def border_mode(expr n,s,t) =
254   modes[n]fil:=false;
255   modes[n]thick:=t;
256   modes[n]size:=s;
257   modes[n]trans:=identity
258 enddef;
260 def fill_mode(expr n,s) =
261   modes[n]fil:=true;
262   modes[n]size:=s;
263   modes[n]trans:=identity
264 enddef;
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.
271 @F set_symbol.mf
272 def make_symbol(expr n)(text t) =
273   for i=0 upto 15:
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);
277       mode_num:=i;
278       if not _mode.fil: pickup pencircle scaled _mode.thick; fi
279       t;
280       endchar;
281     fi
282   endfor
283 enddef;
285 def _mode = modes[mode_num] enddef;
288 Various prefixes are used to control how the drawing commands are used.
290 @F set_symbol.mf
291 let fill_=fill;
293 def asborder text t =
294   if not _mode.fil:
295     _mode.fil:=true;
296     t;
297     _mode.fil:=false;
298   fi
299 enddef;
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.
307 @F set_symbol.mf
308 def Shape(expr p) =
309   if _mode.fil: cullit; fill else: draw fi p;
310 enddef;
311 def Circle(expr p,r) =
312   Shape((fullcircle scaled r) shifted p);
313 enddef;
314 def Rectangle(expr a,b) =
315   Shape(a--(xpart a,ypart b)--b--(ypart a,xpart b)--cycle);
316 enddef;
319 Finally, the set symbol file must be correctly terminated.
322 [(set_symbol.mf)dL[ bye;]+rS](Finally)x
324 @. --- Plurals ---
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.
337 @E English
338 (English)L
342 But first, the specification of characters in a word form rule.
345 1`W(Fill_Table)x
346 [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]
347 0`W(Mark_Table)x
348 2`[:W 3`]:W
353 @. Normal plural rules "-s" "-es" (level 5 and 10)
354 5:]:s
355 10:s]:ses
356 10:ch]:ches
357 10:sh]:shes
359 @. Rules for "-ys" "-ies" (level 10 and 15)
360 15:ay]:ays
361 15:ey]:eys
362 15:iy]:iys
363 15:oy]:oys
364 15:uy]:uys
365 10:y]:ies
367 @. Rules for "-ves" (level 10 and 15)
368 10:alf]:alves
369 10:arf]:arves
370 15:deaf]:deafs
371 10:eaf]:eaves
372 10:elf]:elves
373 10:life]:lives
374 10:nife]:nives
375 10:olf]:olves
376 10:thief]:thieves
377 10:wife]:wives
379 @. Uninflected nouns (level 500)
380 >Bd500 0
381 =bison
382 =carp
383 =corps
384 =debris
385 =djinn
386 =elk
387 =flounder
388 =gallows
389 =innings
390 =mackerel
391 =pants
392 =pliers
393 =salmon
394 =scissors
395 =sea-bass
396 =series
397 =species
398 =swine
399 =trout
400 =tuna
401 =whiting
402 =wildebeest
404 @. Uninflected suffix (level 500)
405 >BADd500 0
406 =deer
407 =fish
408 =ois
409 =pox
410 =sheep
412 @. Irregular suffix (level 500)
413 >`:(Split_String)xrBADr500 0
414 =foot:feet
415 =goose:geese
416 =human:humans
417 =louse:lice
418 =man:men
419 =mouse:mice
420 =tooth:teeth
421 =xis:xes
422 =zoon:zoa
424 @. Irregular plurals (level 1000)
425 >`:(Split_String)xBrBr1000 0
426 =ephemeris:ephemerides
427 =soliloquy:soliloquies
428 =ox:oxen
429 =mythos:mythoi
431 @. "-um" to "-a" (level 750)
432 >d[um]+Br[a]+750 0
433 =agend
434 =bacteri
435 =candelabr
436 =dat
437 =extrem
438 =strat
441 @. "-" to "-im" (level 750)
442 >d[im]+BrBr750 0
443 =cherub
444 =goy
445 =seraph
447 @. "-a" to "-ae" (level 750)
448 >dBr[e]+750 0
449 =alga
450 =alumna
451 =vertebra
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''
464 to ``1st''.
466 @E English
467 (English)L
471 The last case, ``1'' to ``1st'', is simplest, so it comes first.
473 @S 1_1st
474 @. ( number -- text )
475 <[th]s0[st]s1[nd]s2[rd]s3
477 100%d10%r10/1-1 0 1i*
478 d3-1d0i*
479 `0+L+>
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
484 into words.
489 2:0]:]
490 2:1]:one
491 2:2]:two
492 2:3]:three
493 2:4]:four
494 2:5]:five
495 2:6]:six
496 2:7]:seven
497 2:8]:eight
498 2:9]:nine
499 3:10]:ten
500 3:11]:eleven
501 3:12]:twelve
502 3:13]:thirteen
503 3:14]:fourteen
504 3:15]:fifteen
505 3:16]:sixteen
506 3:17]:seventeen
507 3:18]:eighteen
508 3:19]:nineteen
509 4:2t]:twenty
510 4:3t]:thirty
511 4:4t]:forty
512 4:5t]:fifty
513 4:6t]:sixty
514 4:7t]:seventy
515 4:8t]:eighty
516 4:9t]:ninety
517 5:-th]:th
518 5:ty-th]:tieth
519 5:one-th]:first
520 5:two-th]:second
521 5:three-th]:third
522 5:five-th]:fifth
523 5:eight-th]:eighth
524 5:nine-th]:ninth
525 5:twelve-th]:twelvth
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.
533 @S 1_one
534 @. ( number -- text )
535 d[D[zero]]d[<s1
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
542 >]ix
544 @S 1_one_20to99
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
550 @S 1_one_1000
551 l20[D][
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
555 +@. Join the result
558 @S 1_first
559 @. ( number -- text )
560 (1_one)x[-th]+1WD
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
570 entered.
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.)
579 @E Card_Field_Number
580 0(Card_Field_Number)S
582 @E Field_Command
583 @. >( ?? field-number -- ?? )
584 [D](Field_Command)S
586 @S Add_Field
587 @. ( name -- )
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.
595 @S Begin_Sort
596 @. ( -- )
597 0`G(Fill_Table)x
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.
608 @S _Sort_Order
609 Lrl9r:G
611 @S Primary_Ascending
612 @. >( -- )
613 `As9(_Sort_Order)(Field_Command)S
615 @S Primary_Descending
616 @. >( -- )
617 `Zs9(_Sort_Order)(Field_Command)S
619 @S Secondary_Ascending
620 @. >( -- )
621 `as9(_Sort_Order)(Field_Command)S
623 @S Secondary_Descending
624 @. >( -- )
625 `zs9(_Sort_Order)(Field_Command)S
627 @S Record_Sorted_Position
628 @. >( -- )
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.
636 @S Write_Fields
637 @. >( value -- )
638 [Lf](Field_Command)S
641 We also need reading fields! It can also be used multiple times, like the
642 one above can be.
644 @S Read_Fields
645 @. >( -- value )
646 [Lv](Field_Command)S
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.
662 `n(Identity_Table)x
663 `(1:n`)2:n1`(:n2`):n
665 @S Name_To_Text
666 @. ( name -- text )
667 NAD`n(Translate)x
669 @S Text_To_Name
670 @. ( text -- name )
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.
681 @S Group_By
682 @. >( -- )
683 [s9](Field_Command)S
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
696 multiplier in \.8.
698 You need to set the number of decimal places in statistics, first.
700 @E Stat_Decimals
701 2(Stat_Decimals)S
703 @S _Statistics_Set
704 (Stat_Decimals)L(Pow10)xs8
705 s4l8*2/s5s3s2s1s0
706 l8l1*l0/s6
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
718 we are looking for):
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.)
724 @S _Statistics_Set
725 l2l0*l1d*-l8*l0d*/s7
727 @S Do_Statistics
728 @. >( code -- )
729 (Begin_Sort)x`Al9:G
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
736 template code.
738 The first thing is to set up the date and time for the statistics report.
740 @F statistics.tex
741 \newcount\hours
742 \newcount\minutes
743 \hours=\time
744 \divide\hours by 60
745 \minutes=\hours
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}
756 input file.
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.
769 @F statistics.tex
770 \parindent=0pt
771 \pretolerance=10000
772 \frenchspacing
773 \parskip=1pt
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.
782 @F statistics.tex
783 \def\statpage#1#2{
784   \tabskip=4pt plus 1fil
785   \halign to\hsize{##\hss&&\hss$##$\cr
786     \omit\hss\bf#1\hss\span\relax\cr
787     #2%
788   }\filbreak
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.
803 @S Line_Thickness
804 [2.5pt]
806 @S Pie_Radius
807 [3in]
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
815 mode_setup;
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) =
826   slice_val:=0;
827   slice_total:=t;
828   clearit;
829   pickup pencircle scaled line_thickness;
830   draw fullcircle scaled pie_radius;
831   pie_outline:=currentpicture;
832 enddef;
834 def send_picture(expr p) =
835   charcode:=character_number;
836   charwd:=chardx:=0; chardp:=charht:=pie_radius#;
837   character_number:=character_number+1;
838   shipout p;
839 enddef;
841 def end_pie =
842   send_picture(pie_outline);
843 enddef;
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)
853 enddef;
855 def add_slice(expr v) =
856   clearit;
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;
865 enddef;
868 Next we do the beginning of the {\TeX} file for statistics, and doing the
869 bar graphs.
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 ---
880 That's all folks!