% sgame.sty (for formatting strategic games)
% <title>LaTeX style file for typesetting strategic games</title>
% Martin J. Osborne (based on suggestions of Michael Carter)
% Version 2.14, 2008/12/2
% Please report bugs to: martin.osborne@utoronto.ca
% The latest version may be found at
% http://www.economics.utoronto.ca/osborne/latex
%
% This material is subject to the LaTeX Project Public License.  See
%   http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html
% for details.

\def\sglinecolor{black}
\def\sgtextcolor{black}

% The character to be centrally vertically aligned in a cell.
\def\sg@alignchar{I}

\newskip\sglabelsep
\sglabelsep=5pt

\newdimen\sgcolsep
\sgcolsep=\tabcolsep

\let\gamestretch=\arraystretch

\newdimen\sg@colwd
\newdimen\sg@xcolwd

\newcount\sg@colnum
\newcount\sg@colindex
\newcount\sg@numcols
\newcount\sg@xnumcols
\newcount\sg@rowindex
\newcount\sg@numrows

\newbox\sg@strutbox
\def\sg@strut{\relax\ifmmode\copy\sg@strutbox\else\unhcopy\sg@strutbox\fi}

\newif\ifsg@label
\newif\ifgamemath\gamemathfalse
\newif\ifgamevalign\gamevalignfalse
\newif\ifssual\ssualtrue
\newif\ifirpawcgl
\newif\ifirplwcgl

\newdimen\sg@tempsep

% Redefine \@array from LATEX.LTX so that when \gamevaligntrue (as within a
% game environment), \@arstrutbox has correct depth and height to position
% rows in tabular environment so that distance from bottom of row to baseline
% of text is equal to distance from top of text to top of row.  (Note that
% characters with positive "depth" (like y, g, and commas) hang below the
% baseline.)

\def\@array[#1]#2{%
  \if #1t\vtop \else \if#1b\vbox \else \vcenter \fi\fi
  \bgroup
  \ifgamevalign
    \setbox0=\hbox{\sg@alignchar}%
    \@tempdima\arraystretch\baselineskip
    \advance\@tempdima -\ht0
    \@tempdimb .5\@tempdima
    \@tempdima \@tempdimb
    \advance\@tempdima \ht0
    \setbox\@arstrutbox=\hbox{%
       \vrule\@height\@tempdima
             \@depth\@tempdimb
             \@width\z@}%
  \else
    \setbox\@arstrutbox\hbox{%
       \vrule\@height\arraystretch\ht\strutbox
             \@depth\arraystretch \dp\strutbox
             \@width\z@}%
  \fi%
  \@mkpream{#2}%
  \edef\@preamble{%
    \ialign \noexpand\@halignto
      \bgroup \@arstrut \@preamble \tabskip\z@skip \cr}%
  \let\@startpbox\@@startpbox \let\@endpbox\@@endpbox
  \let\tabularnewline\\%
    \let\par\@empty
    \let\@sharp##%
    \set@typeset@protect
    \lineskip\z@skip\baselineskip\z@skip
    \ifhmode \@preamerr\z@ \@@par\fi
    \@preamble}

% The \sg@strut in the following is needed to put some space between the first
% row (which contains no verticals) and the following row.  It differs from
% \@arstrut (used in the second and following rows) in that its height
% is the height of an u.c. letter in the current font plus half the
% difference between the \baselineskip (*not* \arraystretch times
% \baselineskip) and that height (so that extra white space is not
% added above the labels in the top row beyond that normally above a row of
% text on a page).  (Definition of \@gifnextchar is at end of this file.)

\let\@@amp=&

\def\sg@initgame{%
  \global\gamevaligntrue%
  \color{\sgtextcolor}%
  \sg@colwd 0pt%
  \sg@colnum 1%
  \sg@rowindex 0%
  \let\tempstretch=\arraystretch%
  \let\arraystretch=\gamestretch%
  \let\sg@tempsep=\tabcolsep%
  \let\tabcolsep=\sgcolsep%
}

%------------------%
% game environment %
%------------------%

\def\game#1#2{%
  \sg@initgame%
  \sg@xcolwd 0pt%
  \@gifnextchar[{\@gameo{#1}{#2}}{\sg@labelfalse\@game{#1}{#2}}%
}

\def\@gameo#1#2[#3]{%
  \@gifnextchar[{\@gameoo{#1}{#2}[#3]}{\sg@labeltrue\@gamelabel{#1}{#2}[#3]}%
}

\def\@gameoo#1#2[#3][#4]{%
  \@gifnextchar[{\sg@labeltrue\@gameplslabel{#1}{#2}[#3][#4]}%
        {\sg@labelfalse\@gamepls{#1}{#2}[#3][#4]}%
}

\gdef\@gamelab{}

\def\sg@makegstrutbox#1{%
  \setbox0=\hbox{#1}%
  \@tempdima\arraystretch\baselineskip%
  \advance\@tempdima -\ht0%
  \@tempdima .5\@tempdima%
  \@tempdimb\baselineskip%
  \advance\@tempdimb-\ht0%
  \@tempdimb .5\@tempdimb%
  \ifssual\else\@tempdima\@tempdimb\fi%
  \advance\@tempdimb \ht0%
  \setbox\sg@strutbox=\hbox{\vrule height\@tempdimb depth\@tempdima width\z@}%
}

{\catcode`\&=\active
%
  \gdef\@gamelabel#1#2[#3]{\gdef\@gamelab{#3}\@game{#1}{#2}}
%
  \gdef\@game#1#2{%
    \catcode`\&=\active%
    \sg@makegstrutbox{\sg@alignchar}%
    \def&{%
      \unskip\egroup%
      \ifdim\sg@colwd<\wd0%
        \global\sg@colwd\wd0%
      \else\fi%
      \hfil\box0\hfil\sg@strut\@@amp\omit%
% \color setting on next line can be removed if it causes problems
      \setbox0=\hbox\bgroup\color{\sgtextcolor}\ignorespaces%
    }%
    \sg@numrows=#1\sg@numcols=#2\sg@xnumcols=#2\advance\sg@numcols by 1%
% setting on next line reestablishes black as text color after sgame is done
% (in case of a float to the top of the page(?))
    \color{black}%
    \begin{gtabular}{@{}r|*{#2}{c|}}\omit\setbox0=\hbox\bgroup\ignorespaces%
  }

  \gdef\@gameplslabel#1#2[#3][#4][#5]{%
\gdef\@gamelab{#5}\@gamepls{#1}{#2}[#3][#4]}

  \gdef\@gamepls#1#2[#3][#4]{%
    \catcode`\&=\active%
    \sg@makegstrutbox{\sg@alignchar}%
    \gdef\@rowpllabel{#3}%
    \def&{\unskip\egroup%
       \ifdim\sg@colwd<\wd0%
         \global\sg@colwd\wd0%
       \else\fi%
       \hfil\box0\hfil\sg@strut\@@amp\omit%
% \color setting on next line can be removed if it causes problems
       \setbox0=\hbox\bgroup\color{\sgtextcolor}\ignorespaces%
    }%
    \sg@numrows=#1\sg@numcols=#2\sg@xnumcols=#2\advance\sg@numcols by 1%
% Row player label is not part of alignment.  To get its vertical position
% right, need to compensate for rows of action labels at top of game, column
% player label, and, if it exists, game label at bottom plus \sglabelsep.
    \@tempdima\ht\sg@strutbox%
    \advance\@tempdima\dp\sg@strutbox%
    \multiply\@tempdima by -1%
    \ifsg@label%
      \@tempdimb\sglabelsep%
      \divide\@tempdimb by 2%
      \advance\@tempdima by \@tempdimb%
      \@tempdimb\ht\sg@strutbox%
      \advance\@tempdimb by\dp\sg@strutbox%
      \divide\@tempdimb by 2%
      \advance\@tempdima by \@tempdimb%
    \fi%
    \raisebox{\@tempdima}{#3}\nobreak\hskip\sgcolsep\nobreak%
% setting on next line reestablishes black as text color after sgame is done
% (in case of a float to the top of the page(?))
    \color{black}%
    \begin{gtabular}{@{}r|*{#2}{c|}}\omit\@@amp%
% \color command on next line can be omitted if it causes problems
    \multispan{#2}\hfil\makebox[0pt]{\color{\sgtextcolor}#4}\sg@strut\hfil%
    \@tabularcr\omit\setbox0=\hbox\bgroup%
    \ignorespaces%
  }%
}

\def\gtabular{\def\@halignto{}\@gtabular}

% In the following, \\ redefines & the first time it is executed (so that
% the second and subsequent rows can be set differently from the first one);
% & redefines \\ to be null on the bottom row, so that the final row can
% end in \\.  [Other less convoluted ways of achieving the same effect fail
% because parts of \if can't contains \cr and \omit has to immediately follow
% \cr.]

{\catcode`\&=\active
  \gdef\@gtabular{%
    \leavevmode \hbox \bgroup $\let\@acol\@tabacol%
    \let\@classz\@tabclassz%
    \let\@classiv\@tabclassiv%
    \def\\{%
      \gdef&{\color{\sglinecolor}%
        \ifgamemath%
          \ifnum\sg@colindex=1%
          \else$\fi%
        \fi%
        \unskip\egroup%
        \ifdim\sg@colwd<\wd0%
          \global\sg@colwd\wd0%
        \else\fi%
        \hfil\box0%
        \ifnum\sg@colindex=1%
          {\global\sg@colwd\sg@xcolwd\global\sg@colindex2}%
        \else\hfil\fi%
        \sg@strut\@@amp%
        \setbox0=\hbox\bgroup\ignorespaces%
        \ifgamemath$\fi%
        \ifnum\sg@rowindex=\sg@numrows%
% 2005-7-8: next line replaced by following one (to avoid losing definition
% of \\ permanently)
%          \gdef\\{\unskip}%
          \let\\=\unskip%
        \else\fi\ignorespaces%
      }%
      \color{\sglinecolor}%
      \ifgamemath%
        \ifnum\sg@rowindex=0%
          \else$%
        \fi%
      \fi%
      \unskip\egroup%
      \ifdim\sg@colwd<\wd0%
        \global\sg@colwd\wd0%
      \else\fi%
      \hfil\box0\hfil\global\sg@colindex 1\relax%
% 2008-12-2: \noalign{\vskip-\arrayrulewidth} added to align thick 
% rules correctly
      \sg@strut\cr\noalign{\vskip-\arrayrulewidth}\cline{2-\sg@numcols}%
      {\global\advance\sg@rowindex by 1}%
      {\global\sg@xcolwd\sg@colwd}%
      {\global\sg@colwd 0pt}%
      \setbox0=\hbox\bgroup\ignorespaces%
    }%
    \@tabarray%
  }
}

\def\endgame{%
  \end{gtabular}%
  \global\gamevalignfalse%
  \let\arraystretch=\tempstretch%
  \let\tabcolsep=\sg@tempsep%
  \catcode`\&=4\relax%
}

\def\sg@putlabel#1{%
  \ifirpawcgl%
    \noalign{\vspace\sglabelsep}%
    \multispan\sg@numcols\hfil%
    \hbox to 0pt{\color{\sgtextcolor}\hss\@gamelab\hss}\hfil\sg@strut\cr%
  \else\ifirplwcgl%
    \noalign{\vspace\sglabelsep}%
    \multispan\sg@numcols\hfil\hbox to 0pt{%
      \setbox1=\hbox{\@rowpllabel}%
      \@tempdima\wd1%
      \advance\@tempdima by \sgcolsep%
      \color{\sgtextcolor}\hss\@gamelab\hss\hspace*{\@tempdima}}%
    \hfil\sg@strut\cr%
  \else%
    \noalign{\vspace\sglabelsep}%
    \if#1u
      \omit&\multispan\sg@xnumcols\hfil%
    \else
      \multispan\sg@numcols\hfil%
    \fi
  \hbox to 0pt{\color{\sgtextcolor}\hss\@gamelab\hss}\hfil\sg@strut\cr
  \fi\fi
}

% The following sets a "phantom" line below the table in which each
% entry under the payoff matrix has the width of the widest entry in 
% the payoff matrix (so that all columns of the matrix have the same width).

\def\endgtabular{%
  \unskip\color{\sglinecolor}%
  \ifgamemath$\fi%
  \egroup%
  \ifdim\sg@colwd<\wd0
    \global\sg@colwd\wd0
  \fi
  \hfil\box0\hfil\sg@strut%
  \cr%
% 2008-12-2: \noalign{\vskip-\arrayrulewidth} added to align thick 
% rules correctly
  \noalign{\vskip-\arrayrulewidth}\cline{2-\sg@numcols}%
% If game has a label, add a row with the label
  \ifsg@label%
    \sg@putlabel{u}%
  \fi
%
  \omit
% Set a phantom row to make all the columns have the same width
  \xdef\enoughcols{}%       see p. 373 of TeXbook re. next few lines
  \loop
    \ifnum\sg@colnum<\sg@numcols
    \xdef\enoughcols{%
      \enoughcols\@@amp%
      \omit\hskip\sgcolsep\hbox to\sg@colwd{\hfil}\hskip\sgcolsep%
    }
    \advance\sg@colnum by1%
  \repeat%
  \enoughcols\crcr\egroup\egroup $\egroup%
}

%---------------------%
%  game* environment  %
%---------------------%

\expandafter \def\csname game*\endcsname #1#2{%
  \sg@initgame%
  \advance\sg@rowindex by1
  \@gifnextchar[{\@gamestaro{#1}{#2}}{\sg@labelfalse\@gamestar{#1}{#2}}%
}

\def\@gamestaro#1#2[#3]{%
  \@gifnextchar[{\@gamestaroo{#1}{#2}[#3]}%
{\sg@labeltrue\@gamestarlabel{#1}{#2}[#3]}%
}

\def\@gamestaroo#1#2[#3][#4]{%
  \@gifnextchar[{\sg@labeltrue\@gamestarplslabel{#1}{#2}[#3][#4]}%
        {\sg@labelfalse\@gamestarpls{#1}{#2}[#3][#4]}%
}

{\catcode`\&=\active
%
  \gdef\@gamestarlabel#1#2[#3]{\gdef\@gamelab{#3}\@gamestar{#1}{#2}}
%
  \gdef\@gamestar#1#2{%
    \catcode`\&=\active%
    \sg@makegstrutbox{\sg@alignchar}%
    \gdef&{\color{\sglinecolor}%
      \ifgamemath$\fi%
      \unskip\egroup%
      \ifdim\sg@colwd<\wd0
        \global\sg@colwd\wd0
      \else\fi%
      \hfil\box0\hfil%
      \sg@strut\@@amp%
      \setbox0=\hbox\bgroup\ignorespaces%
      \ifgamemath$\fi%
      \ifnum\sg@rowindex=\sg@numrows%
        \gdef\\{\unskip}%
        \let\\=\unskip%
      \else\fi\ignorespaces%
    }%
    \sg@numrows=#1\sg@numcols=#2%
    \color{\sglinecolor}%
    \begin{gstartabular}{@{}|*{#2}{c|}}%
\hline\setbox0=\hbox\bgroup\ignorespaces%
  }

  \gdef\@gamestarplslabel#1#2[#3][#4][#5]{%
\gdef\@gamelab{#5}\@gamestarpls{#1}{#2}[#3][#4]}

  \gdef\@gamestarpls#1#2[#3][#4]{%
    \catcode`\&=\active%
    \sg@makegstrutbox{\sg@alignchar}%
    \gdef\@rowpllabel{#3}%
    \def&{\unskip\egroup%
       \ifdim\sg@colwd<\wd0%
         \global\sg@colwd\wd0%
       \else\fi%
       \hfil\color{\sgtextcolor}\box0\hfil\sg@strut\@@amp%
       \setbox0=\hbox\bgroup\ignorespaces%
    }%
    \sg@numrows=#1\sg@numcols=#2%
% Row player label is not part of alignment.  To get its vertical position
% right, need to compensate for rows of action labels at top of game, column
% player label, and, if it exists, game label at bottom plus \sglabelsep.
    \@tempdima\ht\sg@strutbox%
    \advance\@tempdima\dp\sg@strutbox%
    \multiply\@tempdima by -1%
    \divide\@tempdima by2%
    \ifsg@label%
      \@tempdimb\sglabelsep%
      \divide\@tempdimb by 2%
      \advance\@tempdima by \@tempdimb%
      \@tempdimb\ht\sg@strutbox%
      \advance\@tempdimb by\dp\sg@strutbox%
      \divide\@tempdimb by 2%
      \advance\@tempdima by\@tempdimb%
    \fi%
    \raisebox{\@tempdima}{#3}\nobreak\hskip\sgcolsep\nobreak%
    \color{\sglinecolor}%
    \begin{gstartabular}{@{}|*{#2}{c|}}%
    \multispan#2\hfil\makebox[0pt]{\color{\sgtextcolor}#4}\sg@strut\hfil%
    \@tabularcr\hline\setbox0=\hbox\bgroup%
    \ignorespaces%
  }
}

\def\gstartabular{\def\@halignto{}\@gstartabular}

{\catcode`\&=\active%
  \gdef\@gstartabular{%
    \leavevmode \hbox \bgroup $\let\@acol\@tabacol%
    \let\@classz\@tabclassz%
    \let\@classiv\@tabclassiv%
    \def\\{%
      \color{\sglinecolor}%
      \ifgamemath$\fi%
      \unskip\egroup%
      \ifdim\sg@colwd<\wd0%
        \global\sg@colwd\wd0%
      \else\fi%
      \hfil\box0\hfil%
      \sg@strut\cr\hline%
      {\global\advance\sg@rowindex by 1}%
      \setbox0=\hbox\bgroup\ignorespaces%
    }%
    \@tabarray%
  }%
}

\expandafter \def \csname endgame*\endcsname{%
  \end{gstartabular}%
  \global\gamevalignfalse%
  \let\arraystretch=\tempstretch%
  \let\tabcolsep=\sg@tempsep%
  \catcode`\&=4\relax%
}

% The following sets a "phantom" line below the matrix in which each
% entry has the width of the widest entry in the matrix (so that all
% columns have the same width).

\def\endgstartabular{%
  \unskip\color{\sglinecolor}%
  \ifgamemath$\fi%
  \egroup%
  \ifdim\sg@colwd<\wd0%
    \global\sg@colwd\wd0%
  \fi%
  \hfil\box0\hfil\sg@strut%
  \cr%
  \hline%
% If game has a label, add a row with the label
  \ifsg@label%
    \sg@putlabel{s}%
  \fi%
%
  \omit\hskip\sgcolsep\hbox to\sg@colwd{\hfil}\hskip\sgcolsep%
% Set a phantom row to make all the columns have the same width
  \xdef\enoughcols{}%       see p. 373 of TeXbook re. next few lines
  \loop
    \ifnum\sg@colnum<\sg@numcols%
    \xdef\enoughcols{%
      \enoughcols\@@amp%
      \omit\hskip\sgcolsep\hbox to\sg@colwd{\hfil}\hskip\sgcolsep%
    }%
    \advance\sg@colnum by1%
  \repeat%
  \enoughcols\crcr\egroup\egroup $\egroup%
}

%--------------------------------------------------------------------%
% Define \@gifnextchar along the lines of LATEX's \@ifnextchar,      %
% except do not gobble spaces: if next token is a space then execute %
% #3.  (\@ifnextchar doesn't work for some reason: if & is the next  %
% token then something goes wrong.)                                  %
%--------------------------------------------------------------------%
\def\@gifnextchar#1#2#3{\let\@tempe#1\def\@tempa{#2}\def\@tempb{#3}%
\futurelet\@tempc\@gifnch}

\def\@gifnch{\ifx\@tempc\@sptoken\let\@tempd\@tempb%
\else\ifx\@tempc\@tempe\let\@tempd\@tempa\else\let\@tempd\@tempb\fi\fi\@tempd}

