From 7d948ae1e94a78e333748f27292be16da078074b Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sat, 28 May 2022 20:18:12 +0000 Subject: gamebooklib (28may22) git-svn-id: svn://tug.org/texlive/trunk@63424 c570f23f-e606-0410-a88d-b1316a301751 --- .../doc/latex/gamebooklib/gamebooklib.pdf | Bin 263005 -> 273926 bytes .../doc/latex/gamebooklib/gamebooklib_test.pdf | Bin 117057 -> 117057 bytes .../doc/latex/gamebooklib/gamebooklib_test.tex | 2 +- .../texmf-dist/source/latex/gamebooklib/Makefile | 10 +- .../source/latex/gamebooklib/gamebooklib.dtx | 228 +++++++++++++++++---- .../tex/latex/gamebooklib/gamebooklib.sty | 85 ++++++-- 6 files changed, 264 insertions(+), 61 deletions(-) diff --git a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdf b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdf index 43657233fe4..363ab333908 100644 Binary files a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdf and b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdf differ diff --git a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdf b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdf index ae56f8e9534..fb06cdb58f1 100644 Binary files a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdf and b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdf differ diff --git a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.tex b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.tex index 4d661dce633..3b5a116ba2b 100644 --- a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.tex +++ b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.tex @@ -27,7 +27,7 @@ This document was used for testing during development of gamebooklib. Please see the \texttt{gamebooklib\_test.tex} file alongside the PDF to see how the package behaves. - +\tracingmacros=1 \begin{gentry}{codea} This is the first gentry! diff --git a/Master/texmf-dist/source/latex/gamebooklib/Makefile b/Master/texmf-dist/source/latex/gamebooklib/Makefile index 6925b402bdd..00dd31cbb6b 100644 --- a/Master/texmf-dist/source/latex/gamebooklib/Makefile +++ b/Master/texmf-dist/source/latex/gamebooklib/Makefile @@ -1,4 +1,4 @@ -default: gamebooklib_test.pdf gamebooklib.pdf tidy +default: gamebooklib_test.pdf gamebooklib.pdf gamebooklib.zip tidy gamebooklib_test.pdf : gamebooklib_test.tex gamebooklib.sty pdflatex \\nonstopmode\\input gamebooklib_test.tex && \ @@ -13,6 +13,14 @@ gamebooklib.pdf : gamebooklib.sty gamebooklib.dtx makeindex -s gind.ist -o gamebooklib.ind gamebooklib.idx && \ pdflatex \\nonstopmode\\input gamebooklib.dtx +gamebooklib.zip : gamebooklib_countpagesperseed.sh gamebooklib.dtx gamebooklib.ins gamebooklib.pdf gamebooklib_test.pdf gamebooklib_test.tex Makefile README + cd ..; zip gamebooklib/gamebooklib.zip \ + gamebooklib/gamebooklib_countpagesperseed.sh \ + gamebooklib/gamebooklib.dtx gamebooklib/gamebooklib.ins \ + gamebooklib/gamebooklib.pdf gamebooklib/gamebooklib_test.pdf \ + gamebooklib/gamebooklib_test.tex gamebooklib/Makefile \ + gamebooklib/README; cd gamebooklib + tidy: rm -f *.log *.ind *.idx *.glo *.gls *.aux *.ilg # TODO: should we really be deleting the .sty? Check CTAN rules. diff --git a/Master/texmf-dist/source/latex/gamebooklib/gamebooklib.dtx b/Master/texmf-dist/source/latex/gamebooklib/gamebooklib.dtx index 0251127fb04..deef74af4da 100644 --- a/Master/texmf-dist/source/latex/gamebooklib/gamebooklib.dtx +++ b/Master/texmf-dist/source/latex/gamebooklib/gamebooklib.dtx @@ -17,7 +17,7 @@ % \iffalse % \NeedsTeXFormat{LaTeX2e}[2005/12/01] % \ProvidesPackage{gamebooklib} -% [2021/08/24 v1.1 gamebooklib typesetting] +% [2022/05/26 v1.3 gamebooklib typesetting] % %<*driver> \documentclass{ltxdoc} @@ -51,10 +51,11 @@ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % -% \CheckSum{539} +% \CheckSum{708} % % \changes{v1.0}{2021/08/10}{Initial Release} % \changes{v1.1}{2021/08/24}{Bugfix: edge case with clashing fixed-index entries} +% \changes{v1.2}{2021/09/11}{Bugfix: footnotes set justified on last line} % % \GetFileInfo{gamebooklib.sty} % @@ -67,6 +68,7 @@ % \DoNotIndex{\endgroup, \equal, \expandafter, \fi} % \DoNotIndex{\gdef, \global, \head, \hspace, \Huge, \if} % \DoNotIndex{\ifcsname, \ifhmode, \ifnum, \ifthenelse, \ifvmode} +% \DoNotIndex{\numexpr} % \DoNotIndex{\interlinepenalty, \interlinefootnotepenalty} % \DoNotIndex{\large, \leftskip, \mark, \NeedsTeXFormat} % \DoNotIndex{\newcounter, \newenvironment, \newtoks, \noexpand} @@ -74,7 +76,7 @@ % \DoNotIndex{\par, \PassOptionsToClass, \penalty, \ProcessOptions} % \DoNotIndex{\protected@xdef, \ProvidesPackage, \rand, \requirecommand} % \DoNotIndex{\RequirePackage, \rightskip, \rule, \setbox} -% \DoNotIndex{\setcounter, \stepcounter, \textbf, \typeout, \value} +% \DoNotIndex{\setcounter, \stepcounter, \textbf, \value} % \DoNotIndex{\vbox, \unvbox, \vfill, \vspace, \vsize} % \DoNotIndex{\WarningFilter, \whiledo, \Collect@Body, \CurrentOption} % \DoNotIndex{\DeclareOption, \g@addto@macro, \the, \noindent} @@ -82,6 +84,7 @@ % \DoNotIndex{\addtocounter, \refstepcounter, \label} % \DoNotIndex{\iffalse, \iftrue, \outputpenalty, \renewcommand} % \DoNotIndex{\noshuffle, \verbose, \endpage, \footnote} +% \DoNotIndex{\if\dots} % % \title{The Gamebooklib Package\thanks{This document corresponds to \textsf{Gamebooklib}~\fileversion, dated \filedate.}} % \author{Robert J Lee \\ latex@rjlee.homelinux.org} @@ -104,7 +107,7 @@ % paragraph or longer), each with a sequentially numbered value. At % the end of each entry, a link to one or more other numbered % entries is given; the reader selects one and they follow through -% the story in this order. gamebooks traditionally start at the +% the story in this order. Gamebooks traditionally start at the % entry numbered~``1'' and some gamebooks have multiple endings, % with the final section representing a success or victory for the % reader. @@ -138,8 +141,8 @@ % % To load the class, use |\usepackage[|\textit{options}|]{gamebook}| % -% The class options are described below; |[footnotes]| is normally a -% good choice, although there are some limitations. +% The class options are described below; |[footnotes,jukebox]| is +% normally a good choice, although there are some limitations. % % The user simply writes entries like this inside the document: % \begin{verbatim} @@ -239,6 +242,26 @@ % to avoid broken links. % \end{macro} % +% +% \begin{macro}{jukebox} +% \changes{v1.3}{2022/05/26}{Feature: "jukebox" shuffle} +% Use the Jukebox Index shuffling +% algorithm\footnote{\texttt{https://github.com/robertjlee/jukeboxshuffle}}. +% This is slightly slower, but tends to reduce the number of times you +% get a ``turn to~'' instrution referencing the next (or previous) +% entry in the original order, by modifying the shuffle to ensure that +% adjacent gentries in the input have much less chance of being +% adjacent in the final document. |jukebox| requires a \LaTeXe that +% supports \cs{numexpr}, and a minimum of 6 gentries. If fewer than +% 6~|gentry| environments are supplied before \cs{thegentries}, this +% option will only log a warning in verbose mode. +% +% The |jukebox| option guarantees no more adjacent entries than +% without the option, for a given |seed| value; it may not eliminate +% them completely unless the number of entries is large. The +% performance is linear to the number of entries. +% \end{macro} +% % \begin{macro}{noshuffle} % \changes{v1.0}{2021/08/10}{Noshuffle option} % In general, it's easier to write gamebooks in a more linear fashion, @@ -269,7 +292,11 @@ % each way and see which works better for your text. % \end{macro} % -% +% \begin{macro}{seed} +% It's suggested that users specify a value for ``seed'' for stable +% builds, by adding the following before including this package: +% |\usepackage[seed=123]{lcg}| +% \end{macro} % \section*{Footnotes} % % When typesetting a gamebook with footnotes, it is confusing if they @@ -295,7 +322,7 @@ % page. \TeX\ is asked not to break the page there, but this influence % is limited. It may be possible for the author to avoid this, eg by % adding a rubber length to the interline spacing (it may be easier to -% simply choose a different seed value for the |lcg| package to +% simply choose a different |seed| value for the |lcg| package to % reshuffle). % \item If you have a lot of rubber space in the text, or % variably-sized items, \LaTeX\ may expand the footnote at the end of @@ -333,7 +360,7 @@ %\StopEventually{\PrintChanges \pagebreak[4] \PrintIndex} % % \begin{macrocode} -\ProvidesPackage{gamebooklib}[2021/08/24 Gamebook by R Lee latex@rjlee.homelinux.org] +\ProvidesPackage{gamebooklib}[2022/05/25 Gamebook by R Lee latex@rjlee.homelinux.org] % \end{macrocode} % We need \LaTeXe, for the extra token registers. % \begin{macrocode} @@ -353,7 +380,7 @@ % % \begin{macro}{endpage} % The |endpage| option puts the last entry on its own page. This can -% work better when the last entryraph is about a page long, and also +% work better when the last entry is about a page long, and also % the final ``winning'' entry of the gamebook. % \begin{macrocode} \newcommand\gamebook@beforelast{} @@ -363,6 +390,19 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{jukebox} +% The |jukebox| option defines the \cs{gamebox@jukebox} macro; +% while the macro does nothing, \cs{ifcsname} can then be used to +% determine if the option was set. +% \begin{macrocode} +\DeclareOption{jukebox}{% + \newcommand\gamebook@jukebox{}% + \gamebook@info{Gamebook Library to perform jukebox index reshuffle + pass}% +}% +% \end{macrocode} +% \end{macro} +% % \begin{macro}{footnote} % The |footnote| option enables our footnote processing, to throw out % footnotes at the end of each |gentry| so that they don't appear to be @@ -370,7 +410,7 @@ % % This is genearlly recommended, unless you have a reason to turn it % off (such as a conflicting package). It's disabled by default -% because it could cause unexpected errors. +% because it could cause unexpected faults. % \begin{macrocode} \def\if@gamebook@footnotes{\iffalse} \DeclareOption{footnote}{% @@ -390,18 +430,15 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{seed} % All unknown options are passed to |lcg|, as it's our only dependency with options. -% It's suggested that users specify a value for ``seed'' for stable -% builds, by adding the following before including this package: -% -% |\usepackage[seed=123]{lcg}| % \begin{macrocode} \DeclareOption*{% \PassOptionsToClass{\CurrentOption}{lcg}% }% \ProcessOptions\relax% % \end{macrocode} -% We need to capture environment contents +% \end{macro}% We need to capture environment contents % \begin{macrocode} \RequirePackage{environ}% % \end{macrocode} @@ -504,7 +541,7 @@ % Later, we'll change the values of the $N$ bit of \cs{gentry$N$} % macros when we shuffle (the underlying token registers stay the same). % -% This relies on \cs{refstepcounter}\marg{gentryctr} before expanded +% This relies on \cs{refstepcounter}\marg{gentryctr} being expanded % before this macro. The label |gentry:\gentrycode| is thus set to the % current index of the final output entry. % \begin{macrocode} @@ -546,7 +583,7 @@ % |footnote| option was given; it sets up the output routine while the % gamebook is running. % \begin{macrocode} -\begingroup% +\begingroup% \if@gamebook@footnotes\gentry@footnotespergentry\fi% % \end{macrocode} % To begin, let's record the number of entries. This may come in @@ -561,7 +598,7 @@ % than replacing the definition of \cs{p@stkeysr@nd}. % The warning is simply that this package doesn't waste another % counter every time it changes the random limits (which happens a lot -% during Knuth shuffle): +% during the Fisher-Yates shuffle): % \begin{macrocode} \WarningFilter{lcg}{Using an already existing counter rand}% % \end{macrocode} @@ -587,22 +624,29 @@ % bottom of \cs{box255}. % \begin{macrocode} \if@gamebook@footnotes\output={% + \def\gentry@deferoutput{\the\gentry@oldoutput}% % \end{macrocode} % The \cs{outputpenalty} tells us why the output routine was called; generally, it's invoked whenever % a new floatable environment is generated, or when a page is full. Anything less than -1000 means that % the page was filled, so we should add any footnotes only in this case. % \begin{macrocode} \ifnum\outputpenalty<-\@M\else% - \edef\tmp@{footnotetoks\botmark} - \expandafter\ifcsname footnotetoks\botmark\endcsname% - \global\setbox255=\vbox to \vsize{% - \unvbox255\vfill\outputfootnotes@endpage}% - \fi% - \fi% - \the\gentry@oldoutput + \if\gentryshouldoutput0% + \unvbox255\def\gentry@deferoutput{}% + \else% + \expandafter\ifcsname footnotetoks\botmark\endcsname% + \expandafter\if\expandafter\relax\expandafter% + \detokenize\expandafter{\csname footnotetoks\botmark\endcsname}\relax\else% + \global\setbox255=\vbox to \vsize{% + \unvbox255\vfill\outputfootnotes@endpage}% + \fi\fi% + \fi\fi% + \gentry@deferoutput% +% \the\gentry@oldoutput }\fi% % \end{macrocode} % +% % \subsection*{The Shuffling Algorithm} % % The basic shuffling algorithm is to first shuffle all entries, @@ -610,7 +654,7 @@ % 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. +% fixed-index entries (now fixed). % In short, let $A$, $B$, and $C$ be indices; if $A\gentrycount}}{% \edef\gentryidxu{\arabic{gentryctr}}% \expandafter\xdef\csname paraIdx\gentryidxu\endcsname{\gentryidxu}% + \typeout{DEFINED paraIdx\gentryidxu}% \stepcounter{gentryctr}% }% % \end{macrocode} @@ -675,13 +724,13 @@ % 1, and this counter resets after each expansion of \cs{thegentries}). % \end{macro} % \begin{macrocode} - \if@gamebook@shuffle + \if@gamebook@shuffle% \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 +% Don't renumber para~1 or \cs{gentrycount}; Fisher-Yates-shuffle the rest % NB: we stop at \cs{gentrycount}$-2$, because \cs{gentrycount}$-1$ would only shuffle % with itself. % \begin{macrocode} @@ -734,9 +783,77 @@ \expandafter\global\expandafter\let\csname fixedat\mydest\endcsname\@undefined% \addtocounter{gentryctr}{-1}% \fi% +% \end{macrocode} +% if we are doing a jukebox shuffle, remember which final entries are fixed, so +% they don't get moved. +% \begin{macrocode} + \ifcsname gamebook@jukebox\endcsname% + \expandafter\def\csname fixedto\mydest\endcsname{}% + \fi% \fi% \stepcounter{gentryctr}% - }}\fi%SHUFFLE END + }% +% \end{macrocode} +% The jukebox shuffle requires an extra pass. This must come after +% moving fixed entries into their final place, to allow us to compare +% the initial indicies. +% We make a reasonable effort:\begin{itemize} +% \item $t$ is the current index +% \item $u$ is the next index +% \item $r$ is a random index after $u$ (make 3 attempts to find a +% non-fixed $r$) +% \item if abs$(t-u)=1$ and $r$ is not fixed, then swap $u$ and $r$ +% \textbf{if} $u$ is not fixed; otherwise: +% \item if abs$(t-u)=1$ and $r$ is not fixed, then swap $t$ and $r$ +% \textbf{if} $t$ is not fixed; +% \item otherwise, give up. +% \end{itemize} +% \begin{macrocode} + \ifcsname gamebook@jukebox\endcsname% + \ifnum\gentrycount<6% + \gamebook@info{Jukebox pass skipped; too few entries}% + \else% + \setcounter{gentryctr}{2}% + \whiledo{\not{\value{gentryctr}=\stoppoint}}{% + \edef\gentryidxt{\arabic{gentryctr}}% + \edef\curpos{\csname paraIdx\gentryidxt\endcsname}% + \stepcounter{gentryctr}% + \edef\gentryidxu{\arabic{gentryctr}}% + \edef\nextpos{\csname paraIdx\gentryidxu\endcsname}% + \edef\pdiff{\the\numexpr\curpos+\nextpos}% + \ifnum\pdiff<0\edef\pdiff{\the\numexpr-\pdiff}\fi% + \edef\sdiff{\the\numexpr\curpos-\nextpos}% + \ifnum\sdiff<0\edef\sdiff{\the\numexpr-\sdiff}\fi% + \ifnum\pdiff<\sdiff\relax\def\thediff{\pdiff}\else\def\thediff{\sdiff}\fi% + \ifnum\thediff=1% + \gamebook@info{Jukebox: entries are too close: % + \gentryidxt,\gentryidxu\space (original \curpos,\nextpos)}% + \chgrand[first=\numexpr\gentryidxu+1]% + \rand% + \expandafter\ifcsname fixedto\arabic{rand}\endcsname\rand\fi% + \expandafter\ifcsname fixedto\arabic{rand}\endcsname\rand\fi% + \expandafter\ifcsname fixedto\arabic{rand}\endcsname% + \gamebook@info{Can't reshuffle: failed to find non-fixed index}% + \else% + \ifcsname fixedto\gentryidxu\endcsname% + \ifcsname fixedto\gentryidxt\endcsname% + \gamebook@info{Can't reshuffle: \curpos\space and % + \nextpos\space are both fixed.}% + \else% + \gamebook@info{Reshuffling \gentryidxt\space to \arabic{rand}}% + \macroswap{paraIdx\gentryidxt}{paraIdx\arabic{rand}}% + \fi% + \else% + \gamebook@info{Reshuffling \gentryidxu\space to% + \arabic{rand} (alt)}% + \macroswap{paraIdx\gentryidxu}{paraIdx\arabic{rand}}% + \fi\fi\fi% + }% + \fi\fi% + }\fi%SHUFFLE END +% \end{macrocode} +% Now we can output the |gentry| token registers to let \LaTeX\ do its thing: +% \begin{macrocode} \gamebook@info{Shuffled! Gentry order:}% \setcounter{gentryctr}{1}% \whiledo{\not{\value{gentryctr}>\gentrycount}}{% @@ -749,7 +866,7 @@ % We can reuse the same counter again to output % \begin{macrocode} \setcounter{gentryctr}{0}% - \gamebook@info{Outputting \gentrycount\ gamebook entries}% + \gamebook@info{Outputting \gentrycount\space gamebook entries}% \whiledo{\value{gentryctr}<\gentrycount}{% % \end{macrocode} % Use refstepcounter in the loop to allow \cs{label} to work as expected. @@ -772,6 +889,7 @@ }% % \end{macrocode} % Finally, we clear the registers and reset the counter in case we want to start again +% (NB: fixedto is scope to the current block only, so no need to clear that) % \begin{macrocode} \gamebook@info{All gamebook entries added to main vertical list}% \setcounter{gentryctr}{1}% @@ -786,7 +904,7 @@ \stepcounter{gentryctr}% }% \setcounter{gentryctr}{0}% - \eject + \eject% \endgroup% }% % \end{macrocode} @@ -820,6 +938,30 @@ }% % \end{macrocode} % +% \begin{macro}{gentryshouldoutput} +% \changes{v1.3}{2022/05/26}{Suppress short pages option} +% This macro \textbf{may} be called from the output routine, and can +% be used to suppress page breaks. It was added because it proves +% fairly easy to write custom divider routines that can produce blank +% pages. If it expands to the number 1, then the page will be output; +% if it expands to 0, it will not be. +% +% For example, the following will prevent pages that are less than 80\% full. +% +% \verb!\renewcommand{\gentryshouldoutput}{%! +% +% \verb! \ifdim\pagetotal>0.8\pagegoal\relax1\else 0\fi}! +% +% \textbf{Caution:} if this macro continually tests false, then +% material will eventually be discarded from the main vertical list to +% ensure that \TeX\ can complete the output of the document. If you +% redefine this macro, make sure to check out output carefully for +% missing text. +% \begin{macrocode} +\newcommand{\gentryshouldoutput}{1} +% \end{macrocode} +% \end{macro} +% % \DescribeMacro{\gentryfooter} % This takes no arguments and is simply expanded after the entry is typeset. The default adds some vertical % space and a simple separator. @@ -831,9 +973,7 @@ % \end{macrocode} % % \DescribeMacro{\ignorespacesandallpars@} -% This is a technique described on StackExchange: -% -% {\small https://tex.stackexchange.com/questions/179016/\\ignore-spaces-and-pars-after-an-environment\#179034} +% This is a technique described on StackExchange\footnote{\small https://tex.stackexchange.com/questions/179016/\\\mbox{~}\hspace{1in}ignore-spaces-and-pars-after-an-environment\#179034}. % % This is used to ensure that extra space at the start and end of the |gentry| % environment is ignored. @@ -916,14 +1056,14 @@ % % This macro takes one argument, being the maximum index of footnotes to output, inclusive. % Footnotes after this index will be excluded. If not provided, the -% value provided by the counter \cs{@mfpn}, which in the default +% value provided by the counter \cs{@mfpn}, which is the default % \LaTeX\ counter, will be used. % \begin{macrocode} \newcounter{fncounter}% \newcommand{\outputfootnotes}[1]{% \begingroup% \def\in@out{}% flag that footnotes are outputting; suppresses marks - \setcounter{fncounter}{1} + \setcounter{fncounter}{1}% % \end{macrocode} % Called in vertical mode, and don't want to throw a page break. % @@ -931,7 +1071,7 @@ % \begin{macrocode} \def\footnote@rule{% % \end{macrocode} -% The next line comess from the TUGboat suggestions, and protect against various user changes +% The next line comes from the TUGboat suggestions, and protect against various user changes % \begin{macrocode} \leftskip=0pt\rightskip=0pt\interlinepenalty=1000% \penalty-1000% @@ -971,9 +1111,7 @@ \edef\tmp@@{\csname footnotetoks\arabic{fncounter}\endcsname}% % \end{macrocode} % This \cs{detokenize} black magic tests if a token reg is actually -% empty: -% -% https://tex.stackexchange.com/questions/263733/\\whats-the-best-practice-way-to-test-whether-parameter-is-empty +% empty\footnote{\texttt{https://tex.stackexchange.com/questions/263733/\\\mbox{~}\hspace{1in}whats-the-best-practice-way-to-test-whether-parameter-is-empty}} % \begin{macrocode} \expandafter\if\expandafter\relax\expandafter% \detokenize\expandafter{\the\tmp@@}\relax\else% @@ -1042,7 +1180,7 @@ % \cs{botmark} has a value, then we can output all footnotes up to % that index. % \begin{macrocode} -\g@addto@macro{\gentry@footnotespergentry}{ +\g@addto@macro{\gentry@footnotespergentry}{% \newcommand{\outputfootnotes@endpage}{% \expandafter\if\expandafter\relax\expandafter% \detokenize\expandafter{\botmark}\relax\else% diff --git a/Master/texmf-dist/tex/latex/gamebooklib/gamebooklib.sty b/Master/texmf-dist/tex/latex/gamebooklib/gamebooklib.sty index b85504a71a0..882565f7e2d 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/24 Gamebook by R Lee latex@rjlee.homelinux.org] +\ProvidesPackage{gamebooklib}[2022/05/25 Gamebook by R Lee latex@rjlee.homelinux.org] \NeedsTeXFormat{LaTeX2e}[1994/06/01] \newcommand{\gamebook@info}[1]{}% \DeclareOption{verbose}{% @@ -30,6 +30,11 @@ \DeclareOption{endpage}{% \renewcommand\gamebook@beforelast{\eject}% }% +\DeclareOption{jukebox}{% + \newcommand\gamebook@jukebox{}% + \gamebook@info{Gamebook Library to perform jukebox index reshuffle + pass}% +}% \def\if@gamebook@footnotes{\iffalse} \DeclareOption{footnote}{% \gdef\if@gamebook@footnotes{\iftrue}% @@ -92,14 +97,19 @@ \newtoks\gentry@oldoutput{}% \edef\mytmp@{\noexpand\gentry@oldoutput={\the\output}}\mytmp@% \if@gamebook@footnotes\output={% + \def\gentry@deferoutput{\the\gentry@oldoutput}% \ifnum\outputpenalty<-\@M\else% - \edef\tmp@{footnotetoks\botmark} - \expandafter\ifcsname footnotetoks\botmark\endcsname% - \global\setbox255=\vbox to \vsize{% - \unvbox255\vfill\outputfootnotes@endpage}% - \fi% - \fi% - \the\gentry@oldoutput + \if\gentryshouldoutput0% + \unvbox255\def\gentry@deferoutput{}% + \else% + \expandafter\ifcsname footnotetoks\botmark\endcsname% + \expandafter\if\expandafter\relax\expandafter% + \detokenize\expandafter{\csname footnotetoks\botmark\endcsname}\relax\else% + \global\setbox255=\vbox to \vsize{% + \unvbox255\vfill\outputfootnotes@endpage}% + \fi\fi% + \fi\fi% + \gentry@deferoutput% }\fi% \xdef\gentrycount{\arabic{gentryctr}}% \setcounter{gentryctr}{0}% @@ -107,9 +117,10 @@ \whiledo{\not{\value{gentryctr}>\gentrycount}}{% \edef\gentryidxu{\arabic{gentryctr}}% \expandafter\xdef\csname paraIdx\gentryidxu\endcsname{\gentryidxu}% + \typeout{DEFINED paraIdx\gentryidxu}% \stepcounter{gentryctr}% }% - \if@gamebook@shuffle + \if@gamebook@shuffle% \setcounter{rand}{\gentrycount}% \addtocounter{rand}{-1}\edef% \stoppoint{\arabic{rand}}% @@ -146,9 +157,54 @@ \expandafter\global\expandafter\let\csname fixedat\mydest\endcsname\@undefined% \addtocounter{gentryctr}{-1}% \fi% + \ifcsname gamebook@jukebox\endcsname% + \expandafter\def\csname fixedto\mydest\endcsname{}% + \fi% \fi% \stepcounter{gentryctr}% - }}\fi%SHUFFLE END + }% + \ifcsname gamebook@jukebox\endcsname% + \ifnum\gentrycount<6% + \gamebook@info{Jukebox pass skipped; too few entries}% + \else% + \setcounter{gentryctr}{2}% + \whiledo{\not{\value{gentryctr}=\stoppoint}}{% + \edef\gentryidxt{\arabic{gentryctr}}% + \edef\curpos{\csname paraIdx\gentryidxt\endcsname}% + \stepcounter{gentryctr}% + \edef\gentryidxu{\arabic{gentryctr}}% + \edef\nextpos{\csname paraIdx\gentryidxu\endcsname}% + \edef\pdiff{\the\numexpr\curpos+\nextpos}% + \ifnum\pdiff<0\edef\pdiff{\the\numexpr-\pdiff}\fi% + \edef\sdiff{\the\numexpr\curpos-\nextpos}% + \ifnum\sdiff<0\edef\sdiff{\the\numexpr-\sdiff}\fi% + \ifnum\pdiff<\sdiff\relax\def\thediff{\pdiff}\else\def\thediff{\sdiff}\fi% + \ifnum\thediff=1% + \gamebook@info{Jukebox: entries are too close: % + \gentryidxt,\gentryidxu\space (original \curpos,\nextpos)}% + \chgrand[first=\numexpr\gentryidxu+1]% + \rand% + \expandafter\ifcsname fixedto\arabic{rand}\endcsname\rand\fi% + \expandafter\ifcsname fixedto\arabic{rand}\endcsname\rand\fi% + \expandafter\ifcsname fixedto\arabic{rand}\endcsname% + \gamebook@info{Can't reshuffle: failed to find non-fixed index}% + \else% + \ifcsname fixedto\gentryidxu\endcsname% + \ifcsname fixedto\gentryidxt\endcsname% + \gamebook@info{Can't reshuffle: \curpos\space and % + \nextpos\space are both fixed.}% + \else% + \gamebook@info{Reshuffling \gentryidxt\space to \arabic{rand}}% + \macroswap{paraIdx\gentryidxt}{paraIdx\arabic{rand}}% + \fi% + \else% + \gamebook@info{Reshuffling \gentryidxu\space to% + \arabic{rand} (alt)}% + \macroswap{paraIdx\gentryidxu}{paraIdx\arabic{rand}}% + \fi\fi\fi% + }% + \fi\fi% + }\fi%SHUFFLE END \gamebook@info{Shuffled! Gentry order:}% \setcounter{gentryctr}{1}% \whiledo{\not{\value{gentryctr}>\gentrycount}}{% @@ -157,7 +213,7 @@ \stepcounter{gentryctr}% }% \setcounter{gentryctr}{0}% - \gamebook@info{Outputting \gentrycount\ gamebook entries}% + \gamebook@info{Outputting \gentrycount\space gamebook entries}% \whiledo{\value{gentryctr}<\gentrycount}{% \refstepcounter{gentryctr}% \ifthenelse{\value{gentryctr}=\gentrycount}{% @@ -182,7 +238,7 @@ \stepcounter{gentryctr}% }% \setcounter{gentryctr}{0}% - \eject + \eject% \endgroup% }% \newcommand{\gentryheader}[4]{% @@ -193,6 +249,7 @@ \par% \marginpar{#3}% }% +\newcommand{\gentryshouldoutput}{1} \newcommand{\gentryfooter}{% \par\vspace{2em}\centerline{---}\vspace{2em plus 1in}\par% }% @@ -230,7 +287,7 @@ \newcommand{\outputfootnotes}[1]{% \begingroup% \def\in@out{}% flag that footnotes are outputting; suppresses marks - \setcounter{fncounter}{1} + \setcounter{fncounter}{1}% \def\footnote@rule{% \leftskip=0pt\rightskip=0pt\interlinepenalty=1000% \penalty-1000% @@ -262,7 +319,7 @@ \fi% }% \newcommand{\noentryfoot}{\def\outputfootnotes@endgentry{}} -\g@addto@macro{\gentry@footnotespergentry}{ +\g@addto@macro{\gentry@footnotespergentry}{% \newcommand{\outputfootnotes@endpage}{% \expandafter\if\expandafter\relax\expandafter% \detokenize\expandafter{\botmark}\relax\else% -- cgit v1.2.3