diff options
author | Karl Berry <karl@freefriends.org> | 2021-08-24 23:54:38 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-08-24 23:54:38 +0000 |
commit | 0052fcfc5c7b6a85b5f9cb128c299effd52c6ebb (patch) | |
tree | a999657da9d9b9026f7a75a0a681e8d1fa5562f6 | |
parent | 1e0cf33a2c4ee1f510b36e7fc5eb408c349ba1bb (diff) |
gamebooklib (25aug21)
git-svn-id: svn://tug.org/texlive/trunk@60318 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdf | bin | 265430 -> 263005 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdf | bin | 117057 -> 117057 bytes | |||
-rw-r--r-- | Master/texmf-dist/source/latex/gamebooklib/Makefile | 2 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/gamebooklib/gamebooklib.dtx | 156 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/gamebooklib/gamebooklib.sty | 74 |
5 files changed, 148 insertions, 84 deletions
diff --git a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdf b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdf Binary files differindex 991b237de3b..43657233fe4 100644 --- a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdf +++ b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdf diff --git a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdf b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdf Binary files differindex ceac9a9eb7f..ae56f8e9534 100644 --- a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdf +++ b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdf diff --git a/Master/texmf-dist/source/latex/gamebooklib/Makefile b/Master/texmf-dist/source/latex/gamebooklib/Makefile index eae89220722..6925b402bdd 100644 --- a/Master/texmf-dist/source/latex/gamebooklib/Makefile +++ b/Master/texmf-dist/source/latex/gamebooklib/Makefile @@ -15,6 +15,6 @@ gamebooklib.pdf : gamebooklib.sty gamebooklib.dtx tidy: rm -f *.log *.ind *.idx *.glo *.gls *.aux *.ilg - +# TODO: should we really be deleting the .sty? Check CTAN rules. clean: tidy rm -f *~ *.sty diff --git a/Master/texmf-dist/source/latex/gamebooklib/gamebooklib.dtx b/Master/texmf-dist/source/latex/gamebooklib/gamebooklib.dtx index eed4fc64c6a..0251127fb04 100644 --- a/Master/texmf-dist/source/latex/gamebooklib/gamebooklib.dtx +++ b/Master/texmf-dist/source/latex/gamebooklib/gamebooklib.dtx @@ -17,7 +17,7 @@ % \iffalse % <package>\NeedsTeXFormat{LaTeX2e}[2005/12/01] % <package>\ProvidesPackage{gamebooklib} -% <package> [2021/08/10 v1.0 gamebooklib typesetting] +% <package> [2021/08/24 v1.1 gamebooklib typesetting] % %<*driver> \documentclass{ltxdoc} @@ -51,9 +51,10 @@ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % -% \CheckSum{507} +% \CheckSum{539} % % \changes{v1.0}{2021/08/10}{Initial Release} +% \changes{v1.1}{2021/08/24}{Bugfix: edge case with clashing fixed-index entries} % % \GetFileInfo{gamebooklib.sty} % @@ -77,7 +78,7 @@ % \DoNotIndex{\vbox, \unvbox, \vfill, \vspace, \vsize} % \DoNotIndex{\WarningFilter, \whiledo, \Collect@Body, \CurrentOption} % \DoNotIndex{\DeclareOption, \g@addto@macro, \the, \noindent} -% \DoNotIndex{\interfootnotelinepenalty, \marginpar, \myidx} +% \DoNotIndex{\interfootnotelinepenalty, \marginpar} % \DoNotIndex{\addtocounter, \refstepcounter, \label} % \DoNotIndex{\iffalse, \iftrue, \outputpenalty, \renewcommand} % \DoNotIndex{\noshuffle, \verbose, \endpage, \footnote} @@ -332,7 +333,7 @@ %\StopEventually{\PrintChanges \pagebreak[4] \PrintIndex} % % \begin{macrocode} -\ProvidesPackage{gamebooklib}[2021/08/10 Gamebook by R Lee latex@rjlee.homelinux.org] +\ProvidesPackage{gamebooklib}[2021/08/24 Gamebook by R Lee latex@rjlee.homelinux.org] % \end{macrocode} % We need \LaTeXe, for the extra token registers. % \begin{macrocode} @@ -396,7 +397,6 @@ % |\usepackage[seed=123]{lcg}| % \begin{macrocode} \DeclareOption*{% - \typeout{Current option: \CurrentOption}% \PassOptionsToClass{\CurrentOption}{lcg}% }% \ProcessOptions\relax% @@ -446,20 +446,33 @@ % \end{macrocode} % \cs{gentry} just makes the first argument mandatory. % -% \cs{@gentry} defines \cs{gentryidx} and \cs{gentrycode}, which can be used in -% the body of the \cs{gentry} environment to supply the unsorted index -% number and the current entry's unique code. -% % NB: If you define two entries with the same code, \LaTeX\ will print % out a "multiply defined" label warning. % \begin{macrocode} \newenvironment{@gentry}[2]{% - \def\gentryidx{#1}% - \def\gentrycode{#2}% + \xdef\gentryidx{#1}% + \xdef\gentrycode{#2}% \@@gentry% }{\ignorespacesandallpars% + \global\let\gentryidx\@undefined% + \global\let\gentrycode\@undefined% + \global\let\gentryidxu\@undefined% + \global\let\gentryidxs\@undefined% }% % \end{macrocode} +% \begin{macro}{gentryidx} +% This can be used inside a |gentry|; it expands to the first optional +% argument of the |gentry| environment, which is either blank or the +% requested fixed index of the entry. +% To get the actual shuffled index, use \cs{gentryidxu}. +% \end{macro} +% +% \begin{macro}{gentrycode} +% This can be used inside a |gentry|; it expands to the first mandatory +% argument of the |gentry| environment, which is the code for this +% entry (without the |gentry:| prefix). +% \end{macro} +% % \cs{@@gentry} then reads in the optional title argument, storing it in the \cs{gentrytitle} % macro to supply the unsorted index number and the current entry's code respectively. % \begin{macrocode} @@ -590,13 +603,30 @@ }\fi% % \end{macrocode} % -% \subsection*{The shuffling algorithm} +% \subsection*{The Shuffling Algorithm} +% +% The basic shuffling algorithm is to first shuffle all entries, +% except for those marked with a fixed index, then to ge through the +% fixed-index entries in order and swap them into their final place. +% +% The original version of this package had a bug relating to multiple +% fixed-index entries. +% In short, let $A$, $B$, and $C$ be indices; if $A<B$ and +% (unshuffled) entry number $A$ was fixed at (shuffled) +% location $B$, while (unshuffled) entry number $B$ was fixed at +% (shuffled) location $C$, so during the ``shuffle,'' $A$ would be +% swapped with $B$, then $B$ would be swapped with $C$, resulting in +% $A$ appearing at $C$ in the text, not $B$ as requested. Because the +% unshuffled index doesn't appear in either the source or output +% document, this could be difficult to diagnose; the author simply saw +% one of their entries ending up in the wrong place. % % \TeX\ has well beyond 255 token registers these days, so don't % bother to check that limit. % % The LCG package provides a suitable pseudo-random number generator. -% What we want is a repeatable series of numbers. +% What we want is a repeatable series of dispirate numbers, not an +% especially random one. % %\begin{enumerate} % \item Work out how many entries there are~($N$). Provided \cs{thegentries} is @@ -604,7 +634,7 @@ % \item Declare a set of token registers named \cs{paratoks}$n$, where $n$ is % each integer 1\dots$N$ inclusive. These will hold the contents of the entry. % \item Declare a set of macros named \cs{paraidx}$n$, where $n$ is -% each integer 1\dots$N$ inclusive, initialised to $n$. These will hold the number of the entry. +% each integer 1\dots$N$ inclusive, each initialised to $n$. These will hold the number of the entry. % \item Shuffle elements $\{2:N-1\}$, in that array. For $i=2$ through $N-2$ % \begin{enumerate} % \item Let $R$ be a random number between $i$ and $N-1$ inclusive @@ -614,8 +644,8 @@ % \item For $i=1:n$, output token reg $i$ %\end{enumerate} % -% Define macros \cs{csname}~|paraIdx|$N'$\cs{endcsname} containing the arabic -% original page number to be put out on the $N'$th output ``page'' +% Define macros \cs{csname}~|paraIdx|$n$\cs{endcsname} containing the arabic +% original page number to be put out on the $n$th output ``page'' % \begin{macrocode} \xdef\gentrycount{\arabic{gentryctr}}% % \end{macrocode} @@ -628,64 +658,90 @@ % \begin{macrocode} \ifthenelse{\gentrycount<3}{}{%SHUFFLE START \whiledo{\not{\value{gentryctr}>\gentrycount}}{% - \edef\myidx{\arabic{gentryctr}}% - \expandafter\xdef\csname paraIdx\myidx\endcsname{\myidx}% + \edef\gentryidxu{\arabic{gentryctr}}% + \expandafter\xdef\csname paraIdx\gentryidxu\endcsname{\gentryidxu}% \stepcounter{gentryctr}% }% % \end{macrocode} -% Don't renumber para~1 or \cs{gentrycount}; Knuth-shuffle the rest -% NB: we stop at \cs{gentrycount}$-2$, because \cs{gentrycount}$-1$ would only shuffle -% with itself. +% \begin{macro}{gentryidxu} +% \changes{v1.1}{2021/08/24}{Access shuffled index} +% The \cs{gentryidxu} macro can be used inside a |gentry| to obtain the +% current arabic shuffled index of the entry. +% \end{macro} +% \begin{macro}{gentryidxs} +% \changes{v1.1}{2021/08/24}{Access original index} +% The \cs{gentryidxs} macro can be used inside a |gentry| to obtain the +% arabic original unshuffled index of the entry (the first |gentry| is +% 1, and this counter resets after each expansion of \cs{thegentries}). +% \end{macro} % \begin{macrocode} \if@gamebook@shuffle - \setcounter{gentryctr}{2}% \setcounter{rand}{\gentrycount}% \addtocounter{rand}{-1}\edef% \stoppoint{\arabic{rand}}% +% \end{macrocode} +% First, shuffle everything that isn't fixed down. +% Don't renumber para~1 or \cs{gentrycount}; Knuth-shuffle the rest +% NB: we stop at \cs{gentrycount}$-2$, because \cs{gentrycount}$-1$ would only shuffle +% with itself. +% \begin{macrocode} + \setcounter{gentryctr}{2}% \chgrand[last=\stoppoint]% \whiledo{\value{gentryctr}<\stoppoint}{% % \end{macrocode} % If this is to be swapped with a fixed position, skip it % \begin{macrocode} - \edef\myidx{\arabic{gentryctr}}% - \expandafter\ifcsname fixedat\myidx\endcsname% - \gamebook@info{Not shuffling \myidx; fixed pos}% + \edef\gentryidxu{\arabic{gentryctr}}% + \expandafter\ifcsname fixedat\gentryidxu\endcsname% + \gamebook@info{Not shuffling \gentryidxu; fixed pos}% \stepcounter{gentryctr}% \else% - \gamebook@info{Shuffling \myidx}% + \gamebook@info{Shuffling \gentryidxu}% \stepcounter{gentryctr}% \edef\nextidx{\arabic{gentryctr}}% % \end{macrocode} -% If we've hit an entry with fixed position, we may as well skip it +% Roll the dice. If we've hit an entry with fixed position, we must +% skip it, or it would end up being swapped out into +% |fixedat\arabic{rand}| instead. % \begin{macrocode} - \expandafter\ifcsname fixedto\arabic{rand}\endcsname\else% \chgrand[first=\nextidx]% \rand% - \gamebook@info{Shuffling \myidx to \arabic{rand}}% - \macroswap{paraIdx\myidx}{paraIdx\arabic{rand}}% + \expandafter\ifcsname fixedat\arabic{rand}\endcsname\else% + \gamebook@info{Shuffling \gentryidxu to \arabic{rand}}% + \macroswap{paraIdx\gentryidxu}{paraIdx\arabic{rand}}% \fi% \fi% }% % \end{macrocode} -% Now move fixed entries into their final place: +% Now move fixed entries into their final place: % \begin{macrocode} \setcounter{gentryctr}{2}% - \whiledo{\value{gentryctr}<\stoppoint}{% - \edef\myidx{\arabic{gentryctr}}% - \expandafter\ifcsname fixedat\myidx\endcsname% - \expandafter\edef\expandafter\mydest\expandafter% - {\expandafter\csname fixedat\myidx\endcsname}% - \gamebook@info{MOVING FIXED GAMEBOOK ENTRY INTO PLACE: \myidx -> \mydest}% - \macroswap{paraIdx\myidx}% - {paraIdx\expandafter\csname fixedat\myidx\endcsname}% + \whiledo{\not{\value{gentryctr}>\stoppoint}}{% + \edef\gentryidxu{\arabic{gentryctr}}% + \expandafter\ifcsname fixedat\gentryidxu\endcsname% + \expandafter\edef\expandafter\mydest\expandafter% + {\expandafter\csname fixedat\gentryidxu\endcsname}% + \gamebook@info{MOVING FIXED GAMEBOOK ENTRY INTO PLACE: \gentryidxu -> \mydest}% + \macroswap{paraIdx\gentryidxu}% + {paraIdx\expandafter\csname fixedat\gentryidxu\endcsname}% +% \end{macrocode} +% Edge case: It's possible that we also have |fixedat\mydest|; in which case that +% would be messed up with the reshuffling. So we need to rename that +% to |fixedat\gentryidxu| as well, then reprocess this index +% \begin{macrocode} + \expandafter\ifcsname fixedat\mydest\endcsname% + \macroswap{fixedat\gentryidxu}{fixedat\mydest}% + \expandafter\global\expandafter\let\csname fixedat\mydest\endcsname\@undefined% + \addtocounter{gentryctr}{-1}% + \fi% \fi% \stepcounter{gentryctr}% }}\fi%SHUFFLE END \gamebook@info{Shuffled! Gentry order:}% \setcounter{gentryctr}{1}% \whiledo{\not{\value{gentryctr}>\gentrycount}}{% - \edef\myidx{\arabic{gentryctr}}% - \gamebook@info{\myidx -> \csname paraIdx\myidx\endcsname}% + \edef\gentryidxu{\arabic{gentryctr}}% + \gamebook@info{\gentryidxu -> \csname paraIdx\gentryidxu\endcsname}% \stepcounter{gentryctr}% }% % \end{macrocode} @@ -705,14 +761,14 @@ \ifthenelse{\value{gentryctr}=\gentrycount}{% \gamebook@beforelast% }{}% - \edef\myidx{\arabic{gentryctr}}% - \xdef\youridx{\csname paraIdx\myidx\endcsname}% - \gamebook@info{Output gentry \myidx\ of \gentrycount,% - original idx \youridx}% + \edef\gentryidxu{\arabic{gentryctr}}% + \xdef\gentryidxs{\csname paraIdx\gentryidxu\endcsname}% + \gamebook@info{Output gentry \gentryidxu\ of \gentrycount,% + original idx \gentryidxs}% % \end{macrocode} % Output the stored entry body, stripping any extraneous space: % \begin{macrocode} - \the\csname paratok\youridx\endcsname% + \the\csname paratok\gentryidxs\endcsname% }% % \end{macrocode} % Finally, we clear the registers and reset the counter in case we want to start again @@ -720,12 +776,12 @@ \gamebook@info{All gamebook entries added to main vertical list}% \setcounter{gentryctr}{1}% \whiledo{\not{\value{gentryctr}>\gentrycount}}{% - \edef\myidx{\arabic{gentryctr}}% + \edef\gentryidxu{\arabic{gentryctr}}% \expandafter\global\expandafter\let% - \csname paratok\myidx\endcsname\@undefined% - \expandafter\ifcsname fixedat\myidx\endcsname% + \csname paratok\gentryidxu\endcsname\@undefined% + \expandafter\ifcsname fixedat\gentryidxu\endcsname% \expandafter\global\expandafter\let% - \csname fixedat\myidx\endcsname\@undefined% + \csname fixedat\gentryidxu\endcsname\@undefined% \fi% \stepcounter{gentryctr}% }% diff --git a/Master/texmf-dist/tex/latex/gamebooklib/gamebooklib.sty b/Master/texmf-dist/tex/latex/gamebooklib/gamebooklib.sty index 7822d932cdc..b85504a71a0 100644 --- a/Master/texmf-dist/tex/latex/gamebooklib/gamebooklib.sty +++ b/Master/texmf-dist/tex/latex/gamebooklib/gamebooklib.sty @@ -20,7 +20,7 @@ %% and version 1.3 or later is part of all distributions of %% LaTeX version 2005/12/01 or later. %% -\ProvidesPackage{gamebooklib}[2021/08/10 Gamebook by R Lee latex@rjlee.homelinux.org] +\ProvidesPackage{gamebooklib}[2021/08/24 Gamebook by R Lee latex@rjlee.homelinux.org] \NeedsTeXFormat{LaTeX2e}[1994/06/01] \newcommand{\gamebook@info}[1]{}% \DeclareOption{verbose}{% @@ -41,7 +41,6 @@ \gamebook@info{Gamebook Library entries output in order}% }% \DeclareOption*{% - \typeout{Current option: \CurrentOption}% \PassOptionsToClass{\CurrentOption}{lcg}% }% \ProcessOptions\relax% @@ -54,10 +53,14 @@ \setcounter{gentryctr}{0}% \newcommand{\gentry}[1][]{\@gentry{#1}}% \newenvironment{@gentry}[2]{% - \def\gentryidx{#1}% - \def\gentrycode{#2}% + \xdef\gentryidx{#1}% + \xdef\gentrycode{#2}% \@@gentry% }{\ignorespacesandallpars% + \global\let\gentryidx\@undefined% + \global\let\gentrycode\@undefined% + \global\let\gentryidxu\@undefined% + \global\let\gentryidxs\@undefined% }% \newcommand{\@@gentry}[1][]{% \def\gentrytitle{#1}% @@ -102,50 +105,55 @@ \setcounter{gentryctr}{0}% \ifthenelse{\gentrycount<3}{}{%SHUFFLE START \whiledo{\not{\value{gentryctr}>\gentrycount}}{% - \edef\myidx{\arabic{gentryctr}}% - \expandafter\xdef\csname paraIdx\myidx\endcsname{\myidx}% + \edef\gentryidxu{\arabic{gentryctr}}% + \expandafter\xdef\csname paraIdx\gentryidxu\endcsname{\gentryidxu}% \stepcounter{gentryctr}% }% \if@gamebook@shuffle - \setcounter{gentryctr}{2}% \setcounter{rand}{\gentrycount}% \addtocounter{rand}{-1}\edef% \stoppoint{\arabic{rand}}% + \setcounter{gentryctr}{2}% \chgrand[last=\stoppoint]% \whiledo{\value{gentryctr}<\stoppoint}{% - \edef\myidx{\arabic{gentryctr}}% - \expandafter\ifcsname fixedat\myidx\endcsname% - \gamebook@info{Not shuffling \myidx; fixed pos}% + \edef\gentryidxu{\arabic{gentryctr}}% + \expandafter\ifcsname fixedat\gentryidxu\endcsname% + \gamebook@info{Not shuffling \gentryidxu; fixed pos}% \stepcounter{gentryctr}% \else% - \gamebook@info{Shuffling \myidx}% + \gamebook@info{Shuffling \gentryidxu}% \stepcounter{gentryctr}% \edef\nextidx{\arabic{gentryctr}}% - \expandafter\ifcsname fixedto\arabic{rand}\endcsname\else% \chgrand[first=\nextidx]% \rand% - \gamebook@info{Shuffling \myidx to \arabic{rand}}% - \macroswap{paraIdx\myidx}{paraIdx\arabic{rand}}% + \expandafter\ifcsname fixedat\arabic{rand}\endcsname\else% + \gamebook@info{Shuffling \gentryidxu to \arabic{rand}}% + \macroswap{paraIdx\gentryidxu}{paraIdx\arabic{rand}}% \fi% \fi% }% \setcounter{gentryctr}{2}% - \whiledo{\value{gentryctr}<\stoppoint}{% - \edef\myidx{\arabic{gentryctr}}% - \expandafter\ifcsname fixedat\myidx\endcsname% - \expandafter\edef\expandafter\mydest\expandafter% - {\expandafter\csname fixedat\myidx\endcsname}% - \gamebook@info{MOVING FIXED GAMEBOOK ENTRY INTO PLACE: \myidx -> \mydest}% - \macroswap{paraIdx\myidx}% - {paraIdx\expandafter\csname fixedat\myidx\endcsname}% + \whiledo{\not{\value{gentryctr}>\stoppoint}}{% + \edef\gentryidxu{\arabic{gentryctr}}% + \expandafter\ifcsname fixedat\gentryidxu\endcsname% + \expandafter\edef\expandafter\mydest\expandafter% + {\expandafter\csname fixedat\gentryidxu\endcsname}% + \gamebook@info{MOVING FIXED GAMEBOOK ENTRY INTO PLACE: \gentryidxu -> \mydest}% + \macroswap{paraIdx\gentryidxu}% + {paraIdx\expandafter\csname fixedat\gentryidxu\endcsname}% + \expandafter\ifcsname fixedat\mydest\endcsname% + \macroswap{fixedat\gentryidxu}{fixedat\mydest}% + \expandafter\global\expandafter\let\csname fixedat\mydest\endcsname\@undefined% + \addtocounter{gentryctr}{-1}% + \fi% \fi% \stepcounter{gentryctr}% }}\fi%SHUFFLE END \gamebook@info{Shuffled! Gentry order:}% \setcounter{gentryctr}{1}% \whiledo{\not{\value{gentryctr}>\gentrycount}}{% - \edef\myidx{\arabic{gentryctr}}% - \gamebook@info{\myidx -> \csname paraIdx\myidx\endcsname}% + \edef\gentryidxu{\arabic{gentryctr}}% + \gamebook@info{\gentryidxu -> \csname paraIdx\gentryidxu\endcsname}% \stepcounter{gentryctr}% }% \setcounter{gentryctr}{0}% @@ -155,21 +163,21 @@ \ifthenelse{\value{gentryctr}=\gentrycount}{% \gamebook@beforelast% }{}% - \edef\myidx{\arabic{gentryctr}}% - \xdef\youridx{\csname paraIdx\myidx\endcsname}% - \gamebook@info{Output gentry \myidx\ of \gentrycount,% - original idx \youridx}% - \the\csname paratok\youridx\endcsname% + \edef\gentryidxu{\arabic{gentryctr}}% + \xdef\gentryidxs{\csname paraIdx\gentryidxu\endcsname}% + \gamebook@info{Output gentry \gentryidxu\ of \gentrycount,% + original idx \gentryidxs}% + \the\csname paratok\gentryidxs\endcsname% }% \gamebook@info{All gamebook entries added to main vertical list}% \setcounter{gentryctr}{1}% \whiledo{\not{\value{gentryctr}>\gentrycount}}{% - \edef\myidx{\arabic{gentryctr}}% + \edef\gentryidxu{\arabic{gentryctr}}% \expandafter\global\expandafter\let% - \csname paratok\myidx\endcsname\@undefined% - \expandafter\ifcsname fixedat\myidx\endcsname% + \csname paratok\gentryidxu\endcsname\@undefined% + \expandafter\ifcsname fixedat\gentryidxu\endcsname% \expandafter\global\expandafter\let% - \csname fixedat\myidx\endcsname\@undefined% + \csname fixedat\gentryidxu\endcsname\@undefined% \fi% \stepcounter{gentryctr}% }% |