summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2022-05-28 20:18:12 +0000
committerKarl Berry <karl@freefriends.org>2022-05-28 20:18:12 +0000
commit7d948ae1e94a78e333748f27292be16da078074b (patch)
tree3173124565a32ae706e7318d0cc27dc9f90c0ac0
parent282d86452c6ed49026b345932f198ecfce65ea6f (diff)
gamebooklib (28may22)
git-svn-id: svn://tug.org/texlive/trunk@63424 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdfbin263005 -> 273926 bytes
-rw-r--r--Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdfbin117057 -> 117057 bytes
-rw-r--r--Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.tex2
-rw-r--r--Master/texmf-dist/source/latex/gamebooklib/Makefile10
-rw-r--r--Master/texmf-dist/source/latex/gamebooklib/gamebooklib.dtx228
-rw-r--r--Master/texmf-dist/tex/latex/gamebooklib/gamebooklib.sty85
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
--- a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdf
+++ b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib.pdf
Binary files 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
--- a/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdf
+++ b/Master/texmf-dist/doc/latex/gamebooklib/gamebooklib_test.pdf
Binary files 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
% <package>\NeedsTeXFormat{LaTeX2e}[2005/12/01]
% <package>\ProvidesPackage{gamebooklib}
-% <package> [2021/08/24 v1.1 gamebooklib typesetting]
+% <package> [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<B$ and
% (unshuffled) entry number $A$ was fixed at (shuffled)
% location $B$, while (unshuffled) entry number $B$ was fixed at
@@ -624,8 +668,8 @@
% \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 dispirate numbers, not an
+% The |LCG| package provides a suitable pseudo-random number generator.
+% What we want is a repeatable series of disparate numbers, not an
% especially random one.
%
%\begin{enumerate}
@@ -641,14 +685,18 @@
% \item If $R\ne i$ then swap macros \cs{gentrytoks}$R$ and \cs{gentrytoks}$i$
% \item If $R\ne i$ then swap macros \cs{paraIdx}$R$ and \cs{gentryidx}$i$
% \end{enumerate}
+% \item If a jukebox index sort is requested, perform an optimisation
+% pass (see below)
% \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''
+% original gentry number to be put out on the $n$th output gentry.
+% \begin{macro}{gentrycount}
% \begin{macrocode}
\xdef\gentrycount{\arabic{gentryctr}}%
% \end{macrocode}
+% \end{macro}
% we can reuse |gentryctr|; we've finished this set of paras and
% kept the total count.
% \begin{macrocode}
@@ -660,6 +708,7 @@
\whiledo{\not{\value{gentryctr}>\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%