% game.cls --- base class for all Template documents
%
% Written by Jamie Morris starting spring 1998, incorporating 
% some earlier code of Jeremy Brown's.

% The Czar should never need to touch this file; it contains the
% hackery that makes other stuff work.  If you want to establish a
% macro for all your game documents, do it in the custom.sty file;
% there's lots of stuff there for you to customize (*everything* there
% is for you to customize).


      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      %%                                                         %%
      %%                  BEWARE OF CODE                         %%
      %%                                                         %%
      %%     Here dwells the magic TeX stuff that makes          %%
      %%     everything work.  It's very much black magic.       %%
      %%     If you play with it and aren't a TeX master,        %%
      %%     it will eat your soul and those of your team.       %%
      %%                                                         %%
      %%     You have been warned.                               %%
      %%                                                         %%
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



% The ``Date'' keyword would get us the date from CVS automatically, but UTC;
% use LocalDateChanged pseudo-keyword provided by CVSROOT/commitinfo instead.
% Make sure Name parses with and without keywords/dollars (dev vs release).
\begingroup
  \catcode`$=13  \def$#1 {}
  \xdef\cvs@date{$LocalDateChanged: 2004/03/20 EST$ }
  \xdef\cvs@name{v1-6-0 }
  \ifx\cvs@name\empty \gdef\cvs@name{dev} \fi
\endgroup
\ProvidesClass{game}[\cvs@date\space Assassins' Guild game template \cvs@name]
\LoadClassWithOptions{article}

\RequirePackage{newdef}
\RequirePackage{geometry}[2002/07/08]


% simulate latex.ltx's \g@addto@macro
%
\newcommand\tmp@str{} % check name not take
\newtoks\tmp@str
\newcommand\add@to@macro[2]{%
  \begingroup
    \tmp@str\expandafter{#1#2}%
    \xdef#1{\the\tmp@str}%
  \endgroup
}

\def\de@lim{\de@lim}
\def\g@bble#1\g@bblethis{}

% tossing stuff a group ahead
\def\end@toss{\end@toss}
\def\?{\futurelet\0\@toss}
\def\@toss{%
  \ifx\0\end@toss\let\@NEXT\finish@toss%
  \else\ifx\0 \let\@NEXT\toss@space%
  \else\ifx\0\bgroup\let\@NEXT\toss@arg%
  \else\let\@NEXT\toss@usual%
  \fi\fi\fi%
  \@NEXT%
}
\def\finish@toss#1{}
\def\toss@usual#1{\aftergroup#1\?}
\let\space@tossed\space
\def\toss@space#1 {\expandafter\aftergroup\space@tossed\?}
\def\toss@arg#1{\aftergroup{\?#1\end@toss\aftergroup}\?}
% \toss@without@braces should only be called locally!
\def\toss@without@braces{\def\toss@arg##1{\?##1\end@toss\?}}

% fake arrays
\newcommand\set@array[3]{\expandafter\def\csname ARRAY#1-#2\endcsname{#3}}
\newcommand\get@array[2]{\csname ARRAY#1-#2\endcsname}


% Czar calls \usestats in custom.sty; 
% prepare for charsheet \saystats and for statcards
\newcount\stat@count
\def\stat@bad{}  % we'll use this like a boolean and not waste an \if
\def\usestats#1{\stat@count=0{}\do@stats#1\de@lim\de@lim\de@lim}
\def\do@stats#1#2#3{%
  \def\@temp{#1}%
  \ifx\@temp\de@lim
    \edef\stat@total@count{\the\stat@count}
    \let\@NEXT\relax
  \else
    \set@array{stat-field}{\the\stat@count}{#1}
    \set@array{stat-short}{\the\stat@count}{#2}
    \set@array{stat-long}{\the\stat@count}{#3}
    \expandafter\ifx\csname BASE-#1\endcsname\relax
      \expandafter\ifx\csname COMP-#1\endcsname\relax
        \def\stat@bad{bad}
        \@warn{Stat #1 unknown; Czar should fix in custom.sty}
    \fi\fi
    \advance\stat@count by 1
    \let\@NEXT\do@stats
  \fi
  \@NEXT
}
\def\get@stat{%
  \edef\cur@stat@field{\get@array{stat-field}{\the\stat@count}}%
  \begingroup
    \aftergroup\me
    \aftergroup{%
    \expandafter\?\cur@stat@field\end@toss
    \aftergroup}%
  \endgroup
}



% \Czar calls \usecharacterformat and \useplayerformat to
% set the format of \newchar and \player respectively
\def\usecharacterformat#1{\use@format\format@char{#1}}
\def\useplayerformat#1{\use@format\format@player{#1}}
\def\use@format#1#2{
  \begingroup
    \aftergroup\gdef
    \aftergroup#1
    \aftergroup{
    \outer@format#2\de@lim
    \aftergroup}
  \endgroup
}

% outer loop of figuring out charinfo formats
\def\outer@format#1{
  \def\@temp{#1}
  \ifx\@temp\de@lim
    \let\@NEXT\relax  % done with outer loop
  \else
    \inner@format#1; \de@lim; % inner fields delimited by "; "
    \aftergroup\an@outer
    \let\@NEXT\outer@format
  \fi
  \@NEXT
}

\def\split@semi#1;#2\end@split{#1; #2}

% inner loop of figuring out charinfo formats
\def\inner@format#1; {  % inner fields delimited by "; "
  \def\@temp{#1}
  \ifx\@temp\de@lim
    \let\@NEXT\relax  % done with inner loop
  \else
    \test@semicolon{#1}
    \if@semicolon    % arrange for ";" wo space to also work
      \expandafter\inner@format\split@semi#1\end@split; \de@lim; % need "; "
    \else
      \set@format#1//\end@setformat
    \fi
    \let\@NEXT\inner@format
  \fi
  \@NEXT
}

% set that the field is a base field, and what its default value is
\def\set@format#1/#2/#3\end@setformat{
  \check@letters{#1}
  \def\@temp{#2}
  \expandafter\ifx\csname BASE-#1\endcsname\relax
    \ifx\@temp\empty\tmp@str={\ignorespaces}\else\tmp@str={#2}\fi
    \expandafter\xdef\csname BASE-#1\endcsname{\the\tmp@str}
    \?#1\end@toss\aftergroup\an@inner
  \else
    \@die{Char base info field ``#1'' illegally duplicated in custom.sty!
	  Production Czar should fix this immediately.}
  \fi
}


\def\check@letters#1{
  \begingroup
    \def\5{\futurelet\0\do@check}
    \def\do@check##1{
      \ifx\0\de@lim
        \let\@NEXT\relax
      \else
        \ifcat\0A
        \else
          \@die{Char base/combo/pronoun info field ``#1'' contains non-letters
                in custom.sty!  Production Czar should fix this immediately.}
        \fi
        \let\@NEXT\5
      \fi
      \@NEXT
    }
    \5#1\de@lim
  \endgroup
}
\def\make@combo#1#2{
  \check@letters{#1}
  \expandafter\ifx\csname COMP-#1\endcsname\relax
    \expandafter\ifx\csname BASE-#1\endcsname\relax
      \expandafter\def\csname COMP-#1\endcsname{#2}
    \else
      \@die{Char combo/pronoun ``#1'' illegally duplicates base info field 
            in custom.sty!  Production Czar should fix this immediately.}
    \fi
  \else
    \@die{Char combo/pronoun ``#1'' illegally duplicated in custom.sty!
          Production Czar should fix this immediately.}
  \fi
}


% Czar calls \usecombos in custom.sty; set the combo charinfo fields
\def\usecombos#1{\do@combos#1\de@lim\de@lim}
\def\do@combos#1#2{
  \def\@temp{#1}
  \ifx\@temp\de@lim
    \let\@NEXT\relax
  \else
    \make@combo{#1}{#2\unskip}
    \let\@NEXT\do@combos
  \fi
  \@NEXT
}


% Czar calls \newpronoun in custom.sty, GMs can do it in sheets;
% define the special pronoun combos
\newdef\newpronoun[5]{%
  \make@pronoun{#1}{#2}{#3}{#4}%
  \make@pronoun{#2}{#1}{#3}{@#4}%
  \make@pronoun{\@uc#1}{\@uc#2}{\@uc#3}{#5}%
  \make@pronoun{\@uc#2}{\@uc#1}{\@uc#3}{@#5}%
}
\def\@uc#1{\uppercase{#1}}
\def\make@pronoun#1#2#3#4{%
  \make@combo{#4}{\csname PRONOUN#4\endcsname{gender}}%
  \expandafter\def\csname PRONOUN#4\endcsname##1{%
    \ifx##1M#1\else\ifx##1F#2\else\ifx##1N#3\else
    \ifx##1m#1\else\ifx##1f#2\else\ifx##1n#3\else
    #1/#2\fi\fi\fi\fi\fi\fi
  }%
}


% \newchar\Ccontrol_sequence{data}
\newcommand\eachchar{}
\newcommand\eachcharaction{\@die{\string\eachcharaction not set}}
\def\newchar#1#2{
  \ifx#1\@this@macro@had@better@not@be@defined@\else
    \@die{\string#1 in Lists/characters.tex is redefined!}
  \fi
  \newdef#1[1]{\eval@char#1{##1}}
  \expandafter\outer@descend\format@char\de@lim#1\de@lim#2\de@lim\g@bblethis
  \add@to@macro\eachchar{\eachcharaction#1}
  \expandafter\def\csname CHARACTER-\string#1\endcsname{}
}

\def\player#1#2{
  \expandafter\ifx\csname CHARACTER-\string#1\endcsname\relax
    \@die{\string#1: Can only give player info in Lists/players.tex for 
      character macros (defined in Lists/characters.tex with \string\newchar)}
  \fi
  \expandafter\ifx\csname PLAYER-\string#1\endcsname\relax\else
    \@die{Can't give player info twice for \string#1 in Lists/players.tex}
  \fi
  \expandafter\outer@descend\format@player\de@lim#1\de@lim#2\de@lim\g@bblethis
  \expandafter\def\csname PLAYER-\string#1\endcsname{}
}


\def\spaces@only{ }  % any number of spaces/tabs are equivalent

\def\eval@char#1#2{%  char macro, requested info string
  \def\@temp{#2}%
  \ifx\@temp\empty            \eval@char{#1}{default}%
  \else\ifx\@temp\spaces@only \eval@char{#1}{default}%
  \else
    \def\dump@datum##1{%
      \begingroup
        \aftergroup\expandafter
        \aftergroup\?%
        \expandafter\aftergroup\csname\string#1.##1\endcsname
        \aftergroup\end@toss
      \endgroup
    }%
    \begingroup
      % \< works like \? but since \< has actual use in normal tex
      % (in tabbing env) we redefine it only locally.
      \def\<{\futurelet\1\@scan}%
      \gdef\scan@str{}%
      \<#2\end@scan
    \endgroup
    \unskip
  \fi\fi
}

% similar to \? stuff; \< is defined locally in \eval@char above
\def\end@scan{\end@scan}
\def\@scan{%
  \ifx\1\end@scan\let\@then\finish@scan%
  \else\ifx\1 \let\@then\scan@space%
  \else\ifx\1\bgroup\let\@then\scan@arg%
  \else\ifcat\noexpand\1A\let\@then\scan@letter%
  \else\if\noexpand\1@\let\@then\scan@letter%
  \else\let\@then\scan@other%
  \fi\fi\fi\fi\fi%
  \@then%
}
\newcommand\scan@str{}  % check name not taken
\def\do@dump{\expandafter\dump@scan\scan@str\@dumped}
\def\finish@scan#1{\do@dump}
\def\scan@space#1 {\do@dump\expandafter\aftergroup\space@tossed\<}
\def\scan@arg#1{\do@dump\aftergroup{\<#1\end@scan\aftergroup}\<}
\def\scan@letter#1{\add@to@macro\scan@str#1\<}% no do@dump!
\def\scan@other#1{\do@dump\aftergroup#1\<}

\def\dump@scan#1\@dumped{%
  \gdef\scan@str{}%
  \expandafter\ifx\csname BASE-#1\endcsname\relax
    \expandafter\ifx\csname COMP-#1\endcsname\relax
     \?#1\end@toss
    \else
      \begingroup
        \aftergroup\expandafter
        \aftergroup\<%
        \expandafter\aftergroup\csname COMP-#1\endcsname
        \aftergroup\end@scan
      \endgroup
    \fi
  \else
    \dump@datum{#1}%
  \fi
}


% outer loop of defining fields for specific char
% gets next outer field; remaining outer fields; control seq; next char outer
\def\outer@descend#1\an@outer#2\de@lim#3\de@lim#4{
  \def\@temp{#4}
  \ifx\@temp\de@lim % that's all the data this char has
    \blank@outer#3#1\an@outer#2\de@lim\an@outer
    \let\@NEXT\g@bble
  \else
    \inner@descend#3#1\de@lim#4; \de@lim; \g@bblethis % use "; "
    \def\@temp{#2}
    \ifx\@temp\empty % that's all the outer fields there are
      \let\@NEXT\g@bble
    \else % keep going
      \def\@NEXT{\outer@descend#2\de@lim#3\de@lim}
    \fi
  \fi
  \@NEXT
}

\def\blank@outer#1#2\an@outer{
  \def\@temp{#2}
  \ifx\@temp\de@lim % finished blanking stuff out
    \let\@NEXT\relax
  \else
    \blank@inner#1#2\de@lim\an@inner
    \def\@NEXT{\blank@outer#1}
  \fi
  \@NEXT
}

% inner loop of defining fields for specific char
% gets control seq; next inner field; remaining inner fields; next char inner
\def\inner@descend#1#2\an@inner#3\de@lim#4; {
  \def\@temp{#4}
  \ifx\@temp\de@lim % that's all the data this char has there
    \blank@inner#1#2\an@inner#3\de@lim\an@inner
    \let\@NEXT\g@bble
  \else
    \test@semicolon{#4}
    \if@semicolon
      \begingroup
        \?\def\@NEXT\end@toss
        \aftergroup{
        \?\inner@descend#1#2\an@inner#3\de@lim\end@toss
        \expandafter\?\split@semi#4\end@split\end@toss
        \?; \end@toss
        \aftergroup}
      \endgroup
    \else
      \def\@temp{#4}
      \ifx\@temp\empty\tmp@str={\csname BASE-#2\endcsname}\else\tmp@str={#4}\fi
      \expandafter\edef\csname\string#1.#2\endcsname{\the\tmp@str}
      \def\@temp{#3}
      \ifx\@temp\empty % that's all the inner fields there are
        \let\@NEXT\g@bble
      \else % keep going
        \def\@NEXT{\inner@descend#1#3\de@lim}
      \fi
    \fi
  \fi
  \@NEXT
}

\def\blank@inner#1#2\an@inner{
  \def\@temp{#2}
  \ifx\@temp\de@lim % finshed blanking stuff out
    \let\@NEXT\relax
  \else
    \expandafter\edef\csname\string#1.#2\endcsname{\csname BASE-#2\endcsname}
    \def\@NEXT{\blank@inner#1}
  \fi
  \@NEXT
}


\newdef\@warn[1]{%
  \immediate\write16{}%
  \immediate\write16{#1}%
  \immediate\write16{}%
}

\newdef\@die[1]{%
  \immediate\write16{}%
  \scrollmode
  \errmessage{#1}%
  \batchmode
  \@@end
}

% for literal (not field delimiter) semicolons in fields
\newdef\semicolon[0]{;}  % \newdef [0] --> no args but requires braces

\newif\if@semicolon
\def\Literal@Semicolon{;} % a \newdef'd one wouldn't be the same as ; !
\def\test@semicolon#1{\@semicolonfalse\dotest@semicolon#1\de@lim}
\def\dotest@semicolon#1{
  \def\@temp{#1}
  \ifx\@temp\de@lim
    \let\@NEXT\relax
  \else 
    \ifx\@temp\Literal@Semicolon\@semicolontrue\fi
    \let\@NEXT\dotest@semicolon
  \fi
  \@NEXT
}


% Czar calls \usenumbers in custom.sty; use auto-generated numbers files
\def\usenumbers#1{\do@numbers#1\de@lim}
\def\do@numbers#1{
  \def\@temp{#1}
  \ifx\@temp\de@lim
    \let\@NEXT\relax
  \else
    \expandafter\def\csname#1\endcsname##1##2{%
      \expandafter\ifx\csname NUMBER-#1-##1\endcsname\relax
        UNASSIGNED%
      \else
        \csname NUMBER-#1-##1\endcsname
      \fi
    }
    \def\assign@number##1##2{
      \expandafter\def\csname NUMBER-#1-##1\endcsname{##2}
    }
    \InputIfFileExists{#1-assigned.tex}{}{}
    \let\@NEXT\do@numbers
  \fi
  \@NEXT
}


% \testnonzero sees if its argument, fully expanded and typeset, is
% zero width, and sets \nonzerotrue or \nonzerofalse accordingly;
% you use it by doing \testnonzero{blah blah blah} \ifnonzero... \else... \fi
\newbox\test@box
\newif\ifnonzero
\def\testnonzero#1{%
	\setbox\test@box=\hbox{#1}%
	\ifdim\wd\test@box>0sp \nonzerotrue \else \nonzerofalse \fi
}


% \testinfo\Cchar{info} checks whether the char has a blank entry 
% for that info; if so, it sets \infofalse, otherwise \infotrue.
% use with \testinfo\Cchar{info} \ifinfo... \else... \fi.
% If you call with anything but a base info, it's always true, since
% the char has *no* entry for anything else, therefore not a blank one! 
% Note that getting a non-blank default value counts as non-blank.
\newif\ifinfo
\def\Ignorespaces{\ignorespaces}
\def\testinfo#1#2{%
  #1{\def\extract@temp{#2}}%
  \ifx\extract@temp\Ignorespaces\infofalse\else\infotrue\fi
}


\def\name#1{
	\gdef\me{#1}%
	\doname%
}
% defaults:
\def\doname{}
\def\me#1{Unowned}



% a random useful macro for mechanics, \rot{n}{text} alphabet-rotates
% 'text' by n; see macro glossary
\newcount\rot@from 
\newcount\rot@to
\newdef\rot[2]{%
	\begingroup
	\def\set@rot##1##2{%
		\rot@from=##1\relax
		\rot@to=#1\relax
		\ifnum#1>0\relax \advance\rot@to by ##1\relax
		\else \advance\rot@to by ##2\relax \advance\rot@to by 1\relax
		\fi
		\loop \ifnum\rot@to>##2\relax \rot@to=##1\relax \fi
		      \lccode\rot@from=\rot@to\relax
		\ifnum\rot@from<##2\relax
		      \advance\rot@from by 1\relax
		      \advance\rot@to by 1\relax
		\repeat
	}%
	\set@rot{`a}{`z}%
	\set@rot{`A}{`Z}%
	\lowercase{#2}%
	\endgroup
}


% now get the Czar's customizations, which (among other things) invoke
% the macros that set up charinfo fields, auto-numbers, etc
\RequirePackage{custom}

% and now the actual charinfo
\makeatother
\input Lists/characters.tex
\input Lists/players.tex
\makeatletter

% now we check for characters that don't have player info
\let\missing@player\empty
\def\miss@player#1{\gdef\missing@player{#1}}
\renewcommand\eachcharaction[1]{
  \expandafter\ifx csname PLAYER-\string#1\endcsname\relax
    \player#1{}      % set info to blank so things work
    \miss@player#1   % prepare to warn about it below
  \fi
}
\eachchar
%
\ifx\missing@player\empty\else
  \@warn{Warning: \expandafter\string\missing@player,
	 possibly others as well, is in Lists/characters.tex
	 but not in Lists/players.tex.}
\fi


% now set up the usual meaning of \listsheet, in terms of which
% list-type extractables should be defined; character extraction
% magic will locally redefine it as appropriate
%% \listsheet{filename}{code}
\newdef\listsheet[2]{#2}


\endinput
