summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex')
-rw-r--r--Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.chit.code.tex741
-rw-r--r--Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.hex.code.tex370
-rw-r--r--Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.natoapp6c.code.tex414
-rw-r--r--Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.util.code.tex11
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wargame.beach.pdfbin14443 -> 14443 bytes
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wargame.city.pdfbin17802 -> 17802 bytes
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wargame.fields.pdfbin0 -> 3397 bytes
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wargame.light_woods.pdfbin14745 -> 14745 bytes
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wargame.mountains.pdfbin14444 -> 14444 bytes
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wargame.rough.pdfbin19733 -> 19733 bytes
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wargame.speckle.pdfbin0 -> 20677 bytes
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wargame.swamp.pdfbin5589 -> 5589 bytes
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wargame.town.pdfbin6321 -> 6321 bytes
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wargame.village.pdfbin4066 -> 4066 bytes
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wargame.woods.pdfbin16470 -> 16470 bytes
-rw-r--r--Master/texmf-dist/tex/latex/wargame/wgexport.cls170
-rwxr-xr-xMaster/texmf-dist/tex/latex/wargame/wgexport.py1620
-rwxr-xr-xMaster/texmf-dist/tex/latex/wargame/wgmakenato.py756
18 files changed, 3379 insertions, 703 deletions
diff --git a/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.chit.code.tex b/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.chit.code.tex
index 3e5b240b7a8..21a42dddecd 100644
--- a/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.chit.code.tex
+++ b/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.chit.code.tex
@@ -78,10 +78,12 @@
bevel/SW/.style = {/chit/bev=3},
bevel/SE/.style = {/chit/bev=4},
bevel/.default = north west,
- clip/.is if=chit@clip%
+ clip/.is if=chit@clip,%
+ nato shape/.store in=\chit@n@to@shape,
}
+\def\chit@sym@sc@le{.4}
\tikzset{
- chit/symbol/.style={scale=.4,transform shape},
+ chit/symbol/.style={scale=\chit@sym@sc@le,transform shape},
chit/parts/.style={shape=rectangle,transform shape},
chit/factors/.style={chit/parts,anchor=south},
chit/left/.style={chit/parts,anchor=base,rotate=90},%Anchor was south
@@ -118,7 +120,7 @@
chit/.code={%
\chit@dbg{2}{chit arguments are `#1'}%
\pgfkeys{/tikz/transform shape,/tikz/shape=chit}%
- \pgfkeys{/chit/.cd,#1}}}
+ \pgfkeys{/chit/.cd,nato shape=natoapp6c,#1}}}
\newcounter{chit@id}\setcounter{chit@id}{0}
\def\chit@n@to#1#2{%
%% Without a following start square bracket '[' by-pass to final
@@ -129,12 +131,16 @@
%\message{^^JNo start square bracket}%
\@chit@n@to@{#1}{#2}}%]]
}
+\def\chit@n@to@shape{natoapp6c}
\def\@chit@n@to@#1#2#3\@end@chit@n@to{%
\chit@dbg{1}{Chit NATO App6(c) w/o offset:
- ^^J Options: #3
- ^^J ID: #1
- ^^J Position: #2}
- \node[chit/symbol,natoapp6c={#3,id=#1}] (#1) at (#2) {};
+ ^^J Options: `#3'
+ ^^J ID: `#1'
+ ^^J Position: `#2'
+ ^^J Style: `\chit@n@to@shape'
+ }
+ \chit@dbg{2}{NATO shape: `\chit@n@to@shape'}
+ \node[chit/symbol,\chit@n@to@shape={#3,id=#1}] (#1) at (#2) {};
\chit@dbg{4}{Chit NATO App6(c) ended}%
}
\def\@chit@n@to#1#2[#3]{%
@@ -147,30 +153,73 @@
^^J ID: #1
^^J Position: #2
^^J Offset: #4}
- \node[chit/symbol,natoapp6c={#3,id=#1}] (#1) at ($(#2)+(#4)$) {};}
-\def\chit@tr@ns@nchor#1{%
- \pgf@x=0.4\pgf@x%
- \pgf@y=0.4\pgf@y\advance\pgf@y#1}
-\def\chit@nchor#1#2#3{%
- \wg@sub@nchor{#1}{#2}
- \chit@tr@ns@nchor{#3}}
+ \chit@dbg{10}{==== NATO shape: `\chit@n@to@shape' ====}
+ \node[chit/symbol,\chit@n@to@shape={#3,id=#1}] (#1) at ($(#2)+(#4)$) {};}
+\def\chit@tr@ns@nchor{%
+ \chit@dbg{10}{Translating anchor `\the\pgf@x',`\the\pgf@y'}
+ \wg@tmpa=\pgf@x%
+ \wg@tmpb=\pgf@y%
+ \symbol%
+ \chit@dbg{10}{Symbol origin `\the\pgf@x',`\the\pgf@y'}
+ \wg@tmpc=\pgf@x%
+ \wg@tmpd=\pgf@y%
+ \pgf@x=\chit@sym@sc@le\wg@tmpa%
+ \pgf@y=\chit@sym@sc@le\wg@tmpb%
+ \chit@dbg{10}{Scaled anchor `\the\pgf@x',`\the\pgf@y'}
+ \advance\pgf@x\wg@tmpc%
+ \advance\pgf@y\wg@tmpd%
+ \chit@dbg{10}{Offset anchor `\the\pgf@x',`\the\pgf@y'}
+}
+\def\chit@nchor#1#2{%
+ \chit@dbg{10}{Get chit sub anchor of `#1' `#2'}%
+ \wg@sub@nchor{#1}{#2}%
+ \chit@tr@ns@nchor%
+ \chit@dbg{10}{Got chit sub anchor of `\the\pgf@x `\the\pgf@y}%
+}
+\def\chit@sym@nchor#1{%
+ \chit@dbg{10}{Get chit symbol `#1'}%
+ \edef\tmpid{\id symbol}%
+ \chit@nchor{\tmpid}{#1}}
\def\chit@report{}
\tikzset{
zone turn/.style={},
zone mult/.style={}
}
+\def\chit@bkg@p@th{%
+ \northeast%
+ \wg@tmpa=\pgf@x\wg@tmpb=\pgf@y%
+ \pgfpathmoveto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ \wg@tmpa=-\wg@tmpa \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ \wg@tmpb=-\wg@tmpb \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ \wg@tmpa=-\wg@tmpa \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ \pgfclosepath%
+}
\def\chit@bevel@path#1{
\scope[#1]
- \wg@tmpc=\wg@tmpa\multiply\wg@tmpc by \chit@bevel@frac
- \wg@tmpd=\wg@tmpb\multiply\wg@tmpd by \chit@bevel@frac
- \divide\wg@tmpc100
- \divide\wg@tmpd100
+ \wg@tmpc=\wg@tmpa%
+ \wg@tmpd=\wg@tmpb%
+ %% Absolute values
+ \ifdim\wg@tmpa<0pt\multiply\wg@tmpc by -1\fi%
+ \ifdim\wg@tmpb<0pt\multiply\wg@tmpd by -1\fi%
+ % Why the hell do I need this?
+ \chit@dbg{10}{`\the\wg@tmpa' `\the\wg@tmpb'}%
+ %% Smallest dimension
+ \ifdim\wg@tmpc>\wg@tmpd \wg@tmpc=\wg@tmpd\fi%
+ \ifdim\wg@tmpc<\wg@tmpd \wg@tmpd=\wg@tmpc\fi%
+ %% Restore sign
+ \ifdim\wg@tmpa<0pt\multiply\wg@tmpc by -1\fi%
+ \ifdim\wg@tmpb<0pt\multiply\wg@tmpd by -1\fi%
+ %% Take the fraction
+ \multiply\wg@tmpc by \chit@bevel@frac%
+ \multiply\wg@tmpd by \chit@bevel@frac%
+ \divide\wg@tmpc100%
+ \divide\wg@tmpd100%
\pgfpathmoveto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
% Move down along edge
- \wg@tmpb=-\wg@tmpb
+ \wg@tmpb=-\wg@tmpb%
\pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
% Move left along edge
- \wg@tmpa=-\wg@tmpa
+ \wg@tmpa=-\wg@tmpa%
\pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
% Move in and up
\advance\wg@tmpa\wg@tmpc%
@@ -185,14 +234,13 @@
\advance\wg@tmpb-\wg@tmpd%
\pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
\pgfclosepath%
- \pgfusepath{fill}
- \endscope
+ \pgfusepath{fill}%
+ \endscope%
}
-
\pgfdeclareshape{chit}{
\savedanchor\center{\pgf@x=0cm\pgf@y=0cm}
- \savedanchor\northeast{\pgf@x=0.6cm\pgf@y=0.6cm}
- \savedanchor\symbol{\pgf@x=0cm\pgf@y=0.2cm}
+ \savedanchor\northeast{\pgf@x=0.6cm\pgf@y=\pgf@x}
+ \savedanchor\symbol{\pgf@x=0cm\pgf@y=0.1cm}
\savedanchor\factors{\pgf@x=0cm\pgf@y=-0.5cm}
\saveddimen\margin{\pgf@x=0.04cm}
\savedmacro\id{%
@@ -212,6 +260,7 @@
\edef\chitframeopt{\chit@frame}}
\chit@dbg{3}{Chit Frame options: \meaning\chitframeopt}%
}
+ \savedmacro\thisname{\def\thisname{chit}}
\anchor{center}{\center}
\anchor{north east}{\northeast}
\anchor{north west}{\northeast\pgf@x=-\pgf@x}
@@ -221,24 +270,24 @@
\anchor{south} {\northeast\pgf@x=0cm\pgf@y=-\pgf@y}
\anchor{east} {\northeast\pgf@y=0cm}
\anchor{west} {\northeast\pgf@x=-\pgf@x\pgf@y=0cm}
- \anchor{symbol north east}{\chit@nchor{M\id symbol}{north east}{0.2cm}}
- \anchor{symbol north west}{\chit@nchor{M\id symbol}{north west}{0.2cm}}
- \anchor{symbol south east}{\chit@nchor{M\id symbol}{south east}{0.2cm}}
- \anchor{symbol south west}{\chit@nchor{M\id symbol}{south west}{0.2cm}}
- \anchor{symbol north} {\chit@nchor{M\id symbol}{north}{0.2cm}}
- \anchor{symbol west} {\chit@nchor{M\id symbol}{west}{0.2cm}}
- \anchor{symbol south} {\chit@nchor{M\id symbol}{south}{0.2cm}}
- \anchor{symbol east} {\chit@nchor{M\id symbol}{east}{0.2cm}}
- \anchor{symbol upper} {\chit@nchor{M\id symbol}{upper}{0.2cm}}
- \anchor{symbol lower} {\chit@nchor{M\id symbol}{lower}{0.2cm}}
- \anchor{symbol left} {\chit@nchor{M\id symbol}{left}{0.2cm}}
- \anchor{symbol right} {\chit@nchor{M\id symbol}{right}{0.2cm}}
- \anchor{symbol echelon} {\chit@nchor{M\id symbol}{north}{0.2cm}}
- \anchor{symbol below} {\chit@nchor{M\id symbol}{south}{0.1cm}}
+ \anchor{symbol north east}{\chit@sym@nchor{north east}}
+ \anchor{symbol north west}{\chit@sym@nchor{north west}}
+ \anchor{symbol south east}{\chit@sym@nchor{south east}}
+ \anchor{symbol south west}{\chit@sym@nchor{south west}}
+ \anchor{symbol north} {\chit@sym@nchor{north}}
+ \anchor{symbol west} {\chit@sym@nchor{west}}
+ \anchor{symbol south} {\chit@sym@nchor{south}}
+ \anchor{symbol east} {\chit@sym@nchor{east}}
+ \anchor{symbol upper} {\chit@sym@nchor{upper}}
+ \anchor{symbol lower} {\chit@sym@nchor{lower}}
+ \anchor{symbol left} {\chit@sym@nchor{left}}
+ \anchor{symbol right} {\chit@sym@nchor{right}}
+ \anchor{symbol echelon} {\chit@sym@nchor{echelon}}
+ \anchor{symbol below} {\chit@sym@nchor{below}}
\anchor{symbol} {\symbol}
\anchor{factors} {\factors}
- \anchor{left} {\chit@nchor{M\id symbol}{west}{.2cm}\advance\pgf@x-\margin}
- \anchor{right}{\chit@nchor{M\id symbol}{east}{.2cm}\advance\pgf@x+\margin}
+ \anchor{left} {\chit@sym@nchor{west}\advance\pgf@x-\margin}
+ \anchor{right}{\chit@sym@nchor{east}\advance\pgf@x+\margin}
\anchor{upper right} {%
\northeast \advance\pgf@x-\margin \advance\pgf@y-\margin%
}
@@ -256,13 +305,14 @@
%% This is the outline of the chit only. The rest of the chit is
%% made on the foreground "path".
\chit@dbg{1}{Chit drawing background path}
- \northeast%
- \wg@tmpa=\pgf@x\wg@tmpb=\pgf@y%
- \pgfpathmoveto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
- \wg@tmpa=-\wg@tmpa \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
- \wg@tmpb=-\wg@tmpb \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
- \wg@tmpa=-\wg@tmpa \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
- \pgfclosepath
+ \chit@bkg@p@th%
+ % \northeast%
+ % \wg@tmpa=\pgf@x\wg@tmpb=\pgf@y%
+ % \pgfpathmoveto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ % \wg@tmpa=-\wg@tmpa \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ % \wg@tmpb=-\wg@tmpb \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ % \wg@tmpa=-\wg@tmpa \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ % \pgfclosepath
}
\behindforegroundpath{%
\chit@dbg{1}{Chit drawing foreground path}
@@ -288,13 +338,14 @@
%
\ifchit@clip%
\chit@dbg{1}{Chit clip path}
- \northeast%
- \wg@tmpa=\pgf@x\wg@tmpb=\pgf@y%
- \pgfpathmoveto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
- \wg@tmpa=-\wg@tmpa \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
- \wg@tmpb=-\wg@tmpb \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
- \wg@tmpa=-\wg@tmpa \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
- \pgfclosepath%
+ \chit@bkg@p@th%
+ % \northeast%
+ % \wg@tmpa=\pgf@x\wg@tmpb=\pgf@y%
+ % \pgfpathmoveto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ % \wg@tmpa=-\wg@tmpa \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ % \wg@tmpb=-\wg@tmpb \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ % \wg@tmpa=-\wg@tmpa \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}%
+ % \pgfclosepath%
\pgfusepath{clip}%
\fi%
\@ifundefined{chit@symbol}{%
@@ -309,26 +360,22 @@
\symbol%
\edef\args{{\symid}{\the\pgf@x,\the\pgf@y}\chit@symbol}%
\chit@dbg{6}{Arguments to chit NATO symbol: \meaning\args}%
- \chit@dbg{1}{Chit draw nato image}
+ \chit@dbg{1}{Chit draw nato image `\symid'}
\expandafter\chit@n@to\args\@end@chit@n@to%
\chit@dbg{6}{After making NATO symbol in chit}%
% Put in left of symbol
\@ifundefined{chit@left}{}{%
- \chit@dbg{1}{Chit draw left: `\meaning\chit@left'}
+ \chit@dbg{2}{Chit draw left: `\meaning\chit@left'}
+ \wg@nchor{\thisname}{left}
\begin{scope}[]
- \pgfpointanchor{\symid}{west}%
- \wg@tmpa=\pgf@x\advance\wg@tmpa-\margin%
- \wg@tmpb=\pgf@y%
- \wg@pic@all{\chit@left}{}{\the\wg@tmpa,\the\wg@tmpb}{chit/left}%
+ \wg@pic@all{\chit@left}{}{\pgf@x,\pgf@y}{chit/left}%
\end{scope}}%
% Put in right of symbol
\@ifundefined{chit@right}{}{%
- \chit@dbg{1}{Chit draw left: `\meaning\chit@right'}
+ \chit@dbg{2}{Chit draw right: `\meaning\chit@right'}
+ \wg@nchor{\thisname}{right}
\begin{scope}[]
- \pgfpointanchor{\symid}{east}%
- \wg@tmpa=\pgf@x\advance\wg@tmpa+\margin%
- \wg@tmpb=\pgf@y%
- \wg@pic@all{\chit@right}{}{\the\wg@tmpa,\the\wg@tmpb}{chit/right}%
+ \wg@pic@all{\chit@right}{}{\pgf@x,\pgf@y}{chit/right}%
\end{scope}}%
% Get coordinates
\northeast%
@@ -338,31 +385,31 @@
\advance\wg@tmpb-\margin%
% Put in upper left corner
\@ifundefined{chit@upper@left}{}{%
- \chit@dbg{1}{Chit draw upper left: `\meaning\chit@upper@left'}
+ \chit@dbg{1}{Chit draw upper left: `\meaning\chit@upper@left'}%
+ \wg@nchor{\thisname}{upper left}
\begin{scope}[]
- \wg@pic@all{\chit@upper@left}{}{-\the\wg@tmpa,\the\wg@tmpb}{%
- chit/upper left}%
+ \wg@pic@all{\chit@upper@left}{}{\pgf@x,\pgf@y}{chit/upper left}%
\end{scope}}
% Put in upper right corner
\@ifundefined{chit@upper@right}{}{%
\chit@dbg{1}{Chit draw upper right: `\meaning\chit@upper@right'}
+ \wg@nchor{\thisname}{upper right}%
\begin{scope}[]
- \wg@pic@all{\chit@upper@right}{}{\the\wg@tmpa,\the\wg@tmpb}{%
- chit/upper right}%
+ \wg@pic@all{\chit@upper@right}{}{\pgf@x,\pgf@y}{chit/upper right}%
\end{scope}}
% Put in lower left corner
\@ifundefined{chit@lower@left}{}{%
\chit@dbg{1}{Chit draw lower left: `\meaning\chit@lower@left'}
+ \wg@nchor{\thisname}{lower left}%
\begin{scope}[]
- \wg@pic@all{\chit@lower@left}{}{-\the\wg@tmpa,-\the\wg@tmpb}{%
- chit/lower left}%
+ \wg@pic@all{\chit@lower@left}{}{\pgf@x,\pgf@y}{chit/lower left}%
\end{scope}}
% Put in lower right corner
\@ifundefined{chit@lower@right}{}{%
\chit@dbg{1}{Chit draw lower right: `\meaning\chit@lower@right'}
+ \wg@nchor{\thisname}{lower right}%
\begin{scope}[]
- \wg@pic@all{\chit@lower@right}{}{\the\wg@tmpa,-\the\wg@tmpb}{%
- chit/lower right}%
+ \wg@pic@all{\chit@lower@right}{}{\pgf@x,\pgf@y}{chit/lower right}%
\end{scope}}
% Put in factors
\@ifundefined{chit@factors}{}{%
@@ -451,10 +498,83 @@
\fi%
\@ifnextchar;{\@gobble}{}%
}
+\tikzset{
+ /chit/kriegspiel/.code={
+ \pgfkeys{%
+ /tikz/shape=kriegspiel,%
+ /chit/nato shape=kriegspiel symbol}
+ }
+}
+\pgfdeclareshape{kriegspiel}{
+ \inheritsavedanchors[from=chit]
+ \savedanchor\northeast{\pgf@x=0.8cm\pgf@y=0.4cm}
+ \savedanchor\symbol{\pgf@x=0cm\pgf@y=0.15cm}
+ \savedanchor\factors{\pgf@x=.2cm\pgf@y=-.4cm}
+ \savedmacro\thisname{\def\thisname{kriegspiel}}
+ \saveddimen\margin{\pgf@x=0.03cm}
+ \inheritanchor[from=chit]{center}
+ \inheritanchor[from=chit]{north east}
+ \inheritanchor[from=chit]{north west}
+ \inheritanchor[from=chit]{south west}
+ \inheritanchor[from=chit]{south east}
+ \inheritanchor[from=chit]{north}
+ \inheritanchor[from=chit]{south}
+ \inheritanchor[from=chit]{east}
+ \inheritanchor[from=chit]{west}
+ \inheritanchor[from=chit]{symbol north east}
+ \inheritanchor[from=chit]{symbol north west}
+ \inheritanchor[from=chit]{symbol south east}
+ \inheritanchor[from=chit]{symbol south west}
+ \inheritanchor[from=chit]{symbol north}
+ \inheritanchor[from=chit]{symbol west}
+ \inheritanchor[from=chit]{symbol south}
+ \inheritanchor[from=chit]{symbol east}
+ \inheritanchor[from=chit]{symbol upper}
+ \inheritanchor[from=chit]{symbol lower}
+ \inheritanchor[from=chit]{symbol left}
+ \inheritanchor[from=chit]{symbol right}
+ \inheritanchor[from=chit]{symbol echelon}
+ \inheritanchor[from=chit]{symbol below}
+ \inheritanchor[from=chit]{symbol}
+ \inheritanchor[from=chit]{factors}
+ \inheritanchor[from=chit]{left}
+ \inheritanchor[from=chit]{right}
+ \inheritanchor[from=chit]{upper right}
+ \inheritanchor[from=chit]{upper left}
+ \inheritanchor[from=chit]{lower right}
+ \inheritanchor[from=chit]{lower left}
+ % \anchor{upper right} {%
+ % \northeast%
+ % \advance\pgf@x-\margin%
+ % \advance\pgf@y-\margin%
+ % \pgf@y=-\pgf@y%
+ % \advance\pgf@y5pt%
+ % }
+ % \anchor{upper left}{
+ % \northeast%
+ % \advance\pgf@x-\margin%
+ % \advance\pgf@y-\margin%
+ % \pgf@x=-\pgf@x%
+ % \pgf@y=-\pgf@y%
+ % \advance\pgf@y5pt%
+ % }
+ %%
+ \inheritbackgroundpath[from=chit]
+ \inheritbehindforegroundpath[from=chit]
+}
\DeclareRobustCommand\chit@sep[2][/]{%
\foreach[count=\is] \s in {#2}{%
\ifnum\is>1\relax#1\fi%
\s}}
+\def\chit@oset#1#2{%
+ %$\stackrel{{}_{\text{\scriptsize #1}}}{\text{#2}}$%
+ %$\stackrel{\lower2ex\hbox{\text{\scriptsize #1}}}{\text{#2}}$%
+ %${}\overset{\text{\scriptsize #1}}{\text{#2}}{}$%
+ \tikz[]{%
+ \node[inner sep=0pt](chit@dd){#2};%
+ \node[above=-.1ex of chit@dd,inner sep=0pt]{{\scriptsize #1}};%
+ }%
+}
\tikzset{%
chit/1 factor/.pic={
\chit@dbg{4}{ Chit 1 factor: #1}%
@@ -467,7 +587,7 @@
code={
\chit@dbg{4}{ Chit 2 factors w/artillery: `#1' `#2' `#3'}%
\node[chit/factor,chit/2 factors]{%
- {#1}$\overset{\text{\scriptsize #3}}{\text{--}}${#2}};}},
+ {#1}\chit@oset{#3}{--}{#2}};}},
pics/chit/3 factors/.style args={#1,#2,#3}{%
code={
\chit@dbg{4}{ Chit 3 factors: `#1' `#2' `#3'}%
@@ -626,28 +746,28 @@
\@ifstar{\wg@star@oob%
}{\wg@nostar@oob%
}%
-}
-\def\wg@oob#1#2#3#4{
- \def\r{0}
+}%
+\def\wg@oob#1#2#3#4{%
+ \def\r{0}%
\pgfmathparse{#3*(#2-1)}%
- \edef\a{\pgfmathresult}
- \chit@dbg{2}{OOB: `#1'}
- \foreach[count=\ti from 0] \t/\y in #1{
- \xdef\o{\r}
- \def\c{0}
- \ifx\t\y\def\y{0}\fi
- \chit@dbg{2}{Turn \ti\space(\r,\t,y=\y):'}
+ \edef\a{\pgfmathresult}%
+ \chit@dbg{2}{OOB: `#1'}%
+ \foreach[count=\ti from 0] \t/\y in #1{%
+ \xdef\o{\r}%
+ \def\c{0}%
+ \ifx\t\y\def\y{0}\fi%
+ \chit@dbg{2}{Turn \ti\space(\r,\t,y=\y):'}%
\ifwg@oob@inv%
\pic[transform shape] at ( .5*#3,\r) {chit/oob turn=\ti};% was dx=0.5
- \else
+ \else%
\pic[transform shape] at (-.5*#3,\r) {chit/oob turn=\ti};% was dx=-0.5
\fi%
\ifx\t\empty\else%
- \foreach \u/\m in \t{
+ \foreach \u/\m in \t{%
%% \chit@dbg{2}{ `\u'=`\m'}
- \ifx\u\empty\else
- \ifx\m\@empty\def\m{1}\fi
- \ifx\u\m\def\m{1}\fi
+ \ifx\u\empty\else%
+ \ifx\m\@empty\def\m{1}\fi%
+ \ifx\u\m\def\m{1}\fi%
\foreach \n in {1,...,\m}{%
\chit@dbg{2}{OOB Chit is `\u' `\chit@oob@spacer'}%
\ifx\u\chit@oob@spacer%
@@ -656,33 +776,33 @@
\xdef\c{\pgfmathresult}%
\else%
\ifx\u\chit@oob@vspacer%
- \chit@dbg{3}{Chit `\u' is vspacer `\chit@oob@vspacer'}
- \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)}
- \xdef\ll{\pgfmathresult}
- \chit@dbg{2}{\string\ll=`\ll'}
- \chit@oob@rowupdate(\c,\r){\ll}{#4}
+ \chit@dbg{3}{Chit `\u' is vspacer `\chit@oob@vspacer'}%
+ \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)}%
+ \xdef\ll{\pgfmathresult}%
+ \chit@dbg{2}{\string\ll=`\ll'}%
+ \chit@oob@rowupdate(\c,\r){\ll}{#4}%
\else
\ifnum\chitdbglvl>2%
\node[minimum width=#3cm,minimum height=#3cm,
- draw,transform shape] at (\c,\r) {};
+ draw,transform shape] at (\c,\r) {};%
\fi
\ifx\u\chit@blank\else%
\chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);%
\fi%
- \chit@oob@cellupdate(\c,\r){#2}{#3}{\y}
- \fi
- \fi
- }
- \fi
- }
- \fi
+ \chit@oob@cellupdate(\c,\r){#2}{#3}{\y}%
+ \fi%
+ \fi%
+ }%
+ \fi%
+ }%
+ \fi%
\chit@dbg{1}{ End of chits in turn
- \ti\space(c=`\c',r=`\r',o='\o',y='\y')}
+ \ti\space(c=`\c',r=`\r',o='\o',y='\y')}%
% IF no units where given, then we force \c to be non-zero so that
% \chit@oob@turnupdate increments the row
- \ifx\t\@empty
- \def\c{#3}
- \chit@dbg{2}{ Turn is empty, set c=`\c'}
+ \ifx\t\@empty%
+ \def\c{#3}%
+ \chit@dbg{2}{ Turn is empty, set c=`\c'}%
\fi
%\ifnum\y<0% No explicit number of rows given
% \def\c{#3}
@@ -696,22 +816,22 @@
% rows.
\ifnum\y>0%
\chit@dbg{2}{ Looping rows from 2 to \y, break when row > \y}%
- \foreach \rr in {2,...,\y}{
+ \foreach \rr in {2,...,\y}{%
%\ifnum\rr>\y% A little funny, but \y can be negative!
% \chit@dbg{2}{ \space Breaking loop \rr\space > \y}%
% \breakforeach%
%\else%
\chit@oob@rowupdate(\c,\r){#3}{0}% Extra spacing?
%\fi
- }
- \fi
+ }%
+ \fi%
% This will zero \c. However, if on entry |\c|>0, then we also
% increment the row
- \chit@oob@turnupdate(\c,\r){#3}{#4}
- \chit@dbg{2}{End of turn \ti\space(c=`\c',r=`\r',o='\o',y='\y')}
+ \chit@oob@turnupdate(\c,\r){#3}{#4}%
+ \chit@dbg{2}{End of turn \ti\space(c=`\c',r=`\r',o='\o',y='\y')}%
}
- \chit@dbg{3}{End of OOB (c=`\c',r=`\r',y=`\y')}
- \@ifnextchar;{\@gobble}{}}
+ \chit@dbg{3}{End of OOB (c=`\c',r=`\r',y=`\y')}%
+ \@ifnextchar;{\@gobble}{}}%
\def\wg@star@hoob{\wg@oob@invtrue\wg@hoob}
\def\wg@nostar@hoob{\wg@oob@invfalse\wg@hoob}
\def\hoob{%
@@ -719,49 +839,49 @@
}{\wg@nostar@hoob%
}%
}
-\def\wg@hoob#1#2#3#4{
- \def\r{0}
- \def\c{0}
+\def\wg@hoob#1#2#3#4{%
+ \def\r{0}%
+ \def\c{0}%
\pgfmathparse{#3*(#2-1)}%
- \edef\a{\pgfmathresult}
- \chit@dbg{2}{OOB: `#1'}
- \foreach[count=\ti from 0] \t/\y in #1{
- \xdef\o{\r}
+ \edef\a{\pgfmathresult}%
+ \chit@dbg{2}{OOB: `#1'}%
+ \foreach[count=\ti from 0] \t/\y in #1{%
+ \xdef\o{\r}%
% \def\c{0}
- \ifx\t\y\def\y{0}\fi
+ \ifx\t\y\def\y{0}\fi%
\chit@dbg{2}{Turn \ti\space(\r,\t,y=\y):'}
- \ifx\t\empty\else
+ \ifx\t\empty\else%
% Count how many are left for this turn
- \chit@dbg{2}{At start of turn \t\space\string\c=\c}
+ \chit@dbg{2}{At start of turn \t\space\string\c=\c}%
\def\l{\c}%
- \let\ig\empty
- \foreach \u/\m in \t{
- \ifx\ig\empty
- \ifx\u\empty\else
- \ifx\u\m\def\m{1}\fi
+ \let\ig\empty%
+ \foreach \u/\m in \t{%
+ \ifx\ig\empty%
+ \ifx\u\empty\else%
+ \ifx\u\m\def\m{1}\fi%
\ifx\u\chit@oob@spacer%
- \pgfmathparse{\l+\m*#4}\xdef\l{\pgfmathresult}
- \chit@dbg{2}{Got \m\space hspace (#4) -> \l}
- \else
+ \pgfmathparse{\l+\m*#4}\xdef\l{\pgfmathresult}%
+ \chit@dbg{2}{Got \m\space hspace (#4) -> \l}%
+ \else%
\ifx\u\chit@oob@vspace%
- \xdef\ig{1}
- \chit@dbg{2}{Got vspace -> \l (\ig)}
- \else
- \pgfmathparse{\l+\m*#3}
- \xdef\l{\pgfmathresult}
- \chit@dbg{2}{Got \m\space units -> \l}
- \fi
- \fi
- \fi
- \fi}
+ \xdef\ig{1}%
+ \chit@dbg{2}{Got vspace -> \l (\ig)}%
+ \else%
+ \pgfmathparse{\l+\m*#3}%
+ \xdef\l{\pgfmathresult}%
+ \chit@dbg{2}{Got \m\space units -> \l}%
+ \fi%
+ \fi%
+ \fi%
+ \fi}%
% Check if there's enough room
\chit@dbg{2}{To fill the rest of turn needs `\l' compared to
- `\a' (#3*(#2-1))}
+ `\a' (#3*(#2-1))}%
\pgfmathparse{ifthenelse(abs(\l)>=#3*(#2-1),0,1}%
\xdef\l{\pgfmathresult}%
- \chit@dbg{2}{Break or not `\l'}
- \ifnum\l=0\chit@oob@turnupdate(\c,\r){#3}{#4}\fi
- \fi
+ \chit@dbg{2}{Break or not `\l'}%
+ \ifnum\l=0\chit@oob@turnupdate(\c,\r){#3}{#4}\fi%
+ \fi%
\ifwg@oob@inv%
\pic[transform shape] at (\c+.5*#3,\r) {chit/oob turn=\ti};% was dx=0.5
\else
@@ -769,43 +889,43 @@
\fi%
%\chit@oob@cellupdate(\c,\r){#2}{#3}{\y}
\ifx\t\empty\else%
- \def\lv{0}
- \foreach \u/\m in \t{
+ \def\lv{0}%
+ \foreach \u/\m in \t{%
%% \chit@dbg{2}{ `\u'=`\m'}
- \ifx\u\empty\else
- \ifx\m\@empty\def\m{1}\fi
- \ifx\u\m\def\m{1}\fi
+ \ifx\u\empty\else%
+ \ifx\m\@empty\def\m{1}\fi%
+ \ifx\u\m\def\m{1}\fi%
\foreach \n in {1,...,\m}{%
\chit@dbg{2}{OOB Chit is `\u' `\chit@oob@spacer'}%
\ifx\u\chit@oob@spacer%
- \chit@dbg{3}{Chit `\u' is spacer `\chit@oob@spacer'}
+ \chit@dbg{3}{Chit `\u' is spacer `\chit@oob@spacer'}%
\pgfmathparse{\c+#4}%
\xdef\c{\pgfmathresult}%
\else%
\ifx\u\chit@oob@vspacer%
- \chit@dbg{3}{Chit `\u' is vspacer `\chit@oob@vspacer'}
- \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)}
- \xdef\ll{\pgfmathresult}
- \chit@dbg{2}{\string\ll=`\ll'}
- \chit@oob@rowupdate(\c,\r){\ll}{#4}
- \xdef\lv{1}
+ \chit@dbg{3}{Chit `\u' is vspacer `\chit@oob@vspacer'}%
+ \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)}%
+ \xdef\ll{\pgfmathresult}%
+ \chit@dbg{2}{\string\ll=`\ll'}%
+ \chit@oob@rowupdate(\c,\r){\ll}{#4}%
+ \xdef\lv{1}%
\else
\ifnum\chitdbglvl>2%
\node[minimum width=#3cm,minimum height=#3cm,
- draw,transform shape] at (\c,\r) {};
- \fi
+ draw,transform shape] at (\c,\r) {};%
+ \fi%
\ifx\u\chit@blank\else%
\chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);%
\fi%
\chit@oob@cellupdate(\c,\r){#2}{#3}{\y}
- \fi
- \fi
- }
- \fi
- }
- \fi
+ \fi%
+ \fi%
+ }%
+ \fi%
+ }%
+ \fi%
\chit@dbg{2}{ End of chits in turn
- \ti\space(c=`\c',r=`\r',o='\o',y='\y')}
+ \ti\space(c=`\c',r=`\r',o='\o',y='\y')}%
% --- Not relevant, I think
% IF no units where given, then we force \c to be non-zero so that
% \chit@oob@turnupdate increments the row
@@ -826,7 +946,7 @@
% rows.
\ifnum\y>0%
\chit@dbg{2}{ Looping rows from 2 to \y, break when row > \y}%
- \foreach \rr in {2,...,\y}{
+ \foreach \rr in {2,...,\y}{%
%\ifnum\rr>\y% A little funny, but \y can be negative!
% \chit@dbg{2}{ \space Breaking loop \rr\space > \y}%
% \breakforeach%
@@ -834,7 +954,7 @@
\chit@oob@rowupdate(\c,\r){#3}{0}% Extra spacing?
%\fi
}
- \fi
+ \fi%
% --- Not relevant I think
% This will zero \c. However, if on entry |\c|>0, then we also
% increment the row
@@ -856,12 +976,17 @@
\fi
\fi
% \xdef\y{0}
- \chit@dbg{2}{End of turn \ti\space(c=`\c',r=`\r',o='\o',y='\y')}
- }
- \chit@dbg{3}{End of OOB (c=`\c',r=`\r',y=`\y')}
- \@ifnextchar;{\@gobble}{}}
+ \chit@dbg{2}{End of turn \ti\space(c=`\c',r=`\r',o='\o',y='\y')}%
+ }%
+ \chit@dbg{3}{End of OOB (c=`\c',r=`\r',y=`\y')}%
+ \@ifnextchar;{\@gobble}{}}%
\tikzset{
- chit/cell background/.style={fill=black},
+ chit/cell background/.style={draw=black},
+ %% Define to not dp anyting to disable wings
+ chit/cell wings/.style={
+ dashed,
+ dash pattern=on 0pt off 3pt on 3pt off 0pt,
+ draw=black},
%chit/cell background flipped/.style={fill=black},
blank chit/.style={/chit/frame={draw=none,fill=none}},
chit/grid lines/.style={dashed},
@@ -882,12 +1007,35 @@
\pgfmathparse{ifthenelse(#1>=#4*(#3-1),0,#1+#4)}%
\xdef#1{\pgfmathresult}%
}
+\def\chit@cell@frame#1#2{%
+ \coordinate(cell@frame@north east) at ($(#1.north east)+( #2/2, #2/2)$);
+ \coordinate(cell@frame@north west) at ($(#1.north west)+(-#2/2, #2/2)$);
+ \coordinate(cell@frame@south east) at ($(#1.south east)+( #2/2,-#2/2)$);
+ \coordinate(cell@frame@south west) at ($(#1.south west)+(-#2/2,-#2/2)$);
+ \draw[chit/cell background,fill=none,scale line widths,line width=#2cm]
+ (cell@frame@south west) rectangle (cell@frame@north east);
+ \draw[scale line widths,line width=#2cm,chit/cell wings=10pt,fill=none,scale line widths,line width=#2cm]
+ (cell@frame@north east)--++( 0,10*#2)
+ (cell@frame@north east)--++( 10*#2,0)
+ (cell@frame@north west)--++( 0,10*#2)
+ (cell@frame@north west)--++(-10*#2,0)
+ (cell@frame@south east)--++( 0,-10*#2)
+ (cell@frame@south east)--++( 10*#2,0)
+ (cell@frame@south west)--++( 0,-10*#2)
+ (cell@frame@south west)--++(-10*#2,0)
+ ;
+}
\def\chits{%
\@ifstar{\chits@resetfalse\@chits}{\chits@resettrue\@chits}}
+\newcount\wg@col
+\newcount\wg@row
\def\@chits#1#2#3{
\ifchits@reset
- \def\r{0}%
- \def\c{0}%
+ %\def\r{0}%
+ %\def\c{0}%
+ \coordinate(wg@next) at (0,0);
+ \wg@col=1
+ \wg@row=1
\fi
\chit@dbg{1}{Chits to make: #1}%
\foreach[count=\ti from 0] \t/\x in #1{%
@@ -903,15 +1051,48 @@
\ifx\u\chit@blank%
\chit@dbg{3}{Ignoring blank chit:\u}%
\else%
- \chit@cellbg(\c,\r){#3}%
- \chit[\u=\ti](\c,\r)%
- \chit@sng@cellupdate(\c,\r){#2}{#3}%
+ \ifx\u\chit@oob@vspacer%
+ \chit@dbg{3}{Ignoring vertical spacer:\u}%
+ \else
+ \ifx\u\chit@oob@spacer%
+ \chit@dbg{3}{Ignoring horizontal spacer:\u}%
+ \else
+ % \chit@cellbg(\c,\r){#3}%
+ %\chit[\u=\ti](\c,\r)%
+ \chit[\u=\ti](wg@next)(wg@chit)%
+ \chit@cell@frame{wg@chit}{#3}
+ \global\advance\wg@col1
+ \ifnum\wg@col>#2%
+ \path
+ let
+ \p1=(wg@chit.north),
+ \p2=(wg@chit.south),
+ \p3=(wg@chit),
+ \n1={\y3-\y1+\y2-#3cm} in
+ coordinate(wg@next) at (0,\n1);
+ \global\wg@col=1
+ \global\advance\wg@row1
+ \chit@dbg{10}{Row row, next column `\the\wg@col'}
+ \else
+ \path
+ let
+ \p1=(wg@chit.east),
+ \p2=(wg@chit.west),
+ \p3=(wg@chit),
+ \n1={\x3+\x1-\x2+#3cm} in
+ coordinate(wg@next) at (\n1,\y3);
+ \chit@dbg{10}{Next column `\the\wg@col'}
+ \fi
+ %\chit@sng@cellupdate(\c,\r){#2}{#3}%
+ \fi%
+ \fi%
\fi%
}%
\fi%
}%
\fi%
}%
+ \chit@dbg{10}{Table is `\the\wg@col'x`\the\wg@row'}
\@ifnextchar;{\@gobble}{}}
\def\chitgrid#1#2#3{%
\pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}%
@@ -936,14 +1117,22 @@
}
\def\doublechits{%
\@ifstar{\chits@resetfalse\@doublechits}{\chits@resettrue\@doublechits}}
+\newdimen\chit@w
+\newdimen\chit@h
\def\@doublechits#1#2#3{%
\chit@dbg{1}{Setting double-sided chits: #1}
- \ifchits@reset
- \pgfmathparse{-(#2-.5)*#3}
- \xdef\c{\pgfmathresult}
- \def\r{0}
- \fi
-
+ \ifchits@reset%
+ %\pgfmathparse{-(#2-.5)*#3}
+ %\xdef\c{\pgfmathresult}
+ %\def\r{0}
+ \coordinate(wg@next) at (0,0);%
+ \coordinate(wg@fnxt) at (0,0);%
+ \wg@col=1%
+ \wg@row=1%
+ \chit@w=0pt%
+ \chit@h=0pt%
+ \fi%
+ %
\foreach[count=\ti from 0] \t/\x in #1{
\ifx\t\empty\else%
\foreach \u/\m in \t{
@@ -955,21 +1144,105 @@
\ifx\u\chit@blank
\chit@dbg{3}{Ignoring blank chit:\u}
\else
- \chit@cellbg(\c,\r){#3}
- \chit[\u=\ti](\c,\r)
- \chit@dbl@flip(\c,\r){#3}
- \chit@celldblbg(\mc,\r){#3}
- \chit[\u\space flipped=\ti,zone turn=\t,zone mult=\n](\mc,\r)
- \chit@dbl@cellupdate(\c,\r){#2}{#3}
- \fi
- }
- \fi
- }
- \fi
- }
- \draw[dashed](0,-3*#3/4)--(0,\r-#3/4);%
- \draw[dashed,<-] (#3/5,-2*#3/3)--(#3/2,-2*#3/3) node[transform shape,anchor=west]{Back};%
- \draw[dashed,<-] (-#3/5,-2*#3/3)--(-#3/2,-2*#3/3) node[transform shape,anchor=east]{Front};%
+ \ifx\u\chit@oob@vspacer%
+ \chit@dbg{3}{Ignoring vertical spacer:\u}%
+ \else
+ \ifx\u\chit@oob@spacer%
+ \chit@dbg{3}{Ignoring horizontal spacer:\u}%
+ \else
+ \chit@dbg{10}{Drawing `\u' at wg@next}
+ \chit[\u=\ti](wg@next)(wg@chit)%
+ \chit@cell@frame{wg@chit}{#3}
+ \ifdim\chit@w=0pt
+ \pgfextractx\chit@w{\pgfpointanchor{wg@chit}{east}}%
+ \pgfextractx\wg@tmpa{\pgfpointanchor{wg@chit}{west}}%
+ \advance\chit@w-\wg@tmpa%
+ \global\advance\chit@w#3cm%
+ \pgfextracty\chit@h{\pgfpointanchor{wg@chit}{north}}%
+ \pgfextracty\wg@tmpa{\pgfpointanchor{wg@chit}{south}}%
+ \advance\chit@h-\wg@tmpa%
+ \global\advance\chit@h#3cm%
+ \fi
+ \ifnum\wg@col=1
+ \pgfextractx\wg@tmpa{\pgfpointanchor{wg@chit}{center}}%
+ \advance\wg@tmpa+\chit@w%
+ \coordinate(wg@fnxt) at ($(wg@chit)+(\the\chit@w,0pt)$);
+ %\coordinate(wg@fnxt
+ %\chit@dbg{10}{Calculating wg@fnxt since `\the\wg@col'==1}
+ %\path
+ %let
+ %\p1=(wg@chit.east),
+ %\p2=(wg@chit.west),
+ %\p3=(wg@chit),
+ %\n1={\x3+\x1-\x2+#3cm} in
+ %coordinate(wg@fnxt) at (\n1,\y3);
+ \fi
+ %\chit@dbg{10}{Drawing `\u\space flipped' at wg@fnxt}
+ \chit[\u\space flipped=\ti,
+ zone turn=\t,
+ zone mult=\n](wg@fnxt)(wg@flip)%
+ \chit@cell@frame{wg@flip}{#3}
+ \chit@dbg{10}{Next column: `\the\wg@col'}
+ \ifnum\wg@col=1
+ \ifnum\wg@row=1
+ \coordinate(wg@table@top) at (wg@chit.north east);
+ \fi
+ \coordinate(wg@table@bot) at (wg@chit.south east);
+ \fi
+ \global\advance\wg@col1
+ \ifnum\wg@col>#2%
+ % \path
+ % let
+ % \p1=(wg@chit.north),
+ % \p2=(wg@chit.south),
+ % \p3=(wg@chit),
+ % \n1={\y3-\y1+\y2-#3cm} in %1.21991
+ % coordinate(wg@next) at (0,\n1);
+ \coordinate(wg@next) at (0,-\wg@row\chit@h);
+ \global\wg@col=1
+ \global\advance\wg@row1
+ \chit@dbg{10}{Row row, next column `\the\wg@col'}
+ \else
+ % \path
+ % let
+ % \p1=(wg@chit.east),
+ % \p2=(wg@chit.west),
+ % \p3=(wg@chit),
+ % \p4=(wg@flip.east),
+ % \p5=(wg@flip.west),
+ % \p6=(wg@flip),
+ % \n1={\x3-\x1+\x2-#3cm},
+ % \n2={\x6+\x4-\x5+#3cm} in
+ % coordinate(wg@next) at (\n1,\y3)
+ % coordinate(wg@fnxt) at (\n2,\y6);
+ \coordinate(wg@next) at ($(wg@chit)+(-\the\chit@w,0)$);
+ \coordinate(wg@fnxt) at ($(wg@flip)+(+\the\chit@w,0)$);
+ \chit@dbg{10}{Next column `\the\wg@col'}
+ \fi
+ \fi%
+ \fi%
+ \fi%
+ }%
+ \fi%
+ }%
+ \fi%
+ }%
+ \draw[dashed,scale line widths](wg@table@top)--++(0,.4);
+ \draw[dashed,scale line widths](wg@table@bot)--++(0,-.4);
+ \draw[dashed,scale line widths,{Stealth[]}-]
+ ($(wg@table@top)+(0,.2)$) -- ++(.5,0)
+ node[transform shape,anchor=west]{Back};
+ \draw[dashed,scale line widths,{Stealth[]}-]
+ ($(wg@table@top)+(0,.2)$) -- ++(-.5,0)
+ node[transform shape,anchor=east]{Front};
+ \draw[dashed,scale line widths,{Stealth[]}-]
+ ($(wg@table@bot)+(0,-.2)$) -- ++(.5,0)
+ node[transform shape,anchor=west]{Back};
+ \draw[dashed,scale line widths,{Stealth[]}-]
+ ($(wg@table@bot)+(0,-.2)$) -- ++(-.5,0)
+ node[transform shape,anchor=east]{Front};
+ % \draw[dashed,<-] (#3/5,-2*#3/3)--(#3/2,-2*#3/3) node[transform shape,anchor=west]{Back};%
+ % \draw[dashed,<-] (-#3/5,-2*#3/3)--(-#3/2,-2*#3/3) node[transform shape,anchor=east]{Front};%
% \foreach \cc in {0,...,#2}{
% \draw[dashed] (\cc*#3,-3*#3/4)--(\cc*#3,\r-#3/4);
% \draw[dashed] (-\cc*#3,-3*#3/4)--(-\cc*#3,\r-#3/4);}
@@ -980,15 +1253,18 @@
% \draw[dashed] (-#2*#3-#3/4,\rr)--(#2*#3+#3/4,\rr);}
\@ifnextchar;{\@gobble}{}}
\def\doublechitgrid#1#2#3{%
+ \message{^^JWARNING - the grid table might be messed up!}
+ %\iffalse
\pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}%
\pgfmathparse{#2*#3-#3/2}\edef\rmax{\pgfmathresult}%
\foreach \cc in {0,...,#1}{
- \draw[chit/grid lines] (\cc*#3,-3*#3/4)--(\cc*#3,\rmax+#3/4);
- \draw[chit/grid lines] (-\cc*#3,-3*#3/4)--(-\cc*#3,\rmax+#3/4);}
+ \draw[chit/grid lines] (\cc*#3+\rmin,3*#3/4)--(\cc*#3+\rmin,-\rmax-#3/4);
+ \draw[chit/grid lines] (-\cc*#3+\rmin,3*#3/4)--(-\cc*#3+\rmin,-\rmax-#3/4);}
%\chit@dbg{0}{Drawing horizontal lines from `-\rmin, `\rmin', ..., `\rmax'}
- \foreach \rr in {-\rmin,\rmin,...,\rmax}{
- %\chit@dbg{0}{Horizontal line at `\rr'}
- \draw[chit/grid lines] (-#1*#3-#3/4,\rr)--(#1*#3+#3/4,\rr);}
+ \foreach \rr in {\rmin,-\rmin,...,-\rmax}{
+ \chit@dbg{0}{Horizontal line at `\rr'}
+ \draw[chit/grid lines] (-#1*#3-#3/4+\rmin,\rr)--(#1*#3+#3/4+\rmin,\rr);}
+ %\fi
}
\tikzset{%
battle marker/.pic={
@@ -1023,7 +1299,7 @@
\tikzset{
pics/result marker/.style args={#1,#2}{
code={
- \message{^^JResults marker #1 (#2)}
+ \chit@dbg{3}{Results marker #1 (#2)}
\node[shape=circle,
font=\sffamily\bfseries\large,
inner sep=0pt,
@@ -1097,6 +1373,12 @@
% \pgfusepath{draw} %draw border
% \pgfusepath{draw} %draw rectangle
}}
+\newif\ifwg@dsixdot\wg@dsixdotfalse
+\tikzset{
+ d6 dots/.is if=wg@dsixdot,
+ d6 dots/.initial=false,
+ d6 dots/.default=true
+}
\pgfdeclareshape{d6}{
\anchor{center}{\pgfpointorigin} % within the node, (0,0) is the center
\anchor{text}{
@@ -1105,7 +1387,48 @@
\backgroundpath{ % draw border
\pgfpathrectanglecorners{\pgfpoint{.4cm}{.4cm}}{\pgfpoint{-.4cm}{-.4cm}}
% \pgfusepath{draw} %draw rectangle
- }}
+ }
+ \behindforegroundpath{ % draw border
+ \ifwg@dsixdot%
+ \edef\numdots{\tikz@node@content}%
+ % Draw over text
+ \pgfpathrectanglecorners{\pgfpoint{.4cm}{.4cm}}{\pgfpoint{-.4cm}{-.4cm}}%
+ \pgfusepath{fill} %draw rectangle
+ \ifx\tikz@textcolor\pgfutilempty%
+ \pgfutil@colorlet{.}{pgfstrokecolor}%
+ \else
+ % \pgfsetfillcolor{\tikz@textcolor}%
+ \pgfutil@colorlet{.}{\tikz@textcolor}%
+ \fi
+ \pgfsetfillcolor{.}%
+ \ifodd\numdots
+ %\message{^^JCenter dot}
+ \pgfpathcircle{\pgfpoint{0cm}{0cm}}{.09cm}
+ \fi
+ \ifnum\numdots=2%
+ %\message{^^JSpecial 2}
+ \pgfpathcircle{\pgfpointpolar{-45}{.32cm}}{.09cm}
+ \pgfpathcircle{\pgfpointpolar{135}{.32cm}}{.09cm}
+ \fi%
+ \ifnum\numdots>2%
+ %\message{^^JAt least 2}
+ \pgfpathcircle{\pgfpointpolar{-45}{.35cm}}{.09cm}
+ \pgfpathcircle{\pgfpointpolar{135}{.35cm}}{.09cm}
+ \fi%
+ \ifnum\numdots>3%
+ %\message{^^JAt least 4}
+ \pgfpathcircle{\pgfpointpolar{ 45}{.35cm}}{.09cm}
+ \pgfpathcircle{\pgfpointpolar{-135}{.35cm}}{.09cm}
+ \fi%
+ \ifnum\numdots=6%
+ %\message{^^JLucky 6}
+ \pgfpathcircle{\pgfpoint{-.247cm}{0cm}}{.09cm}
+ \pgfpathcircle{\pgfpoint{ .247cm}{0cm}}{.09cm}
+ \fi
+ \pgfusepath{fill} %draw rectangle
+ \fi%
+ }
+}
\pgfdeclareshape{d8}{
\anchor{center}{\pgfpointorigin} % within the node, (0,0) is the center
\anchor{text}{
@@ -1226,7 +1549,7 @@
\pgfkeysalso{%
chit has drop=true,
/tikz/blur shadow={shadow blur steps=5,
- shadow opacity=25,
+ shadow opacity=30,
shadow xshift=.05cm,
shadow yshift=-.05cm,
shadow blur radius=.05cm,
diff --git a/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.hex.code.tex b/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.hex.code.tex
index 2dde041e313..f08d0574e02 100644
--- a/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.hex.code.tex
+++ b/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.hex.code.tex
@@ -9,6 +9,8 @@
%% hex/shape.dtx (with options: `hex')
%% hex/terrain.dtx (with options: `hex')
%% hex/terrain/beach.dtx (with options: `hex')
+%% hex/terrain/fields.dtx (with options: `hex')
+%% hex/terrain/speckle.dtx (with options: `hex')
%% hex/terrain/light_woods.dtx (with options: `hex')
%% hex/terrain/woods.dtx (with options: `hex')
%% hex/terrain/swamp.dtx (with options: `hex')
@@ -223,7 +225,7 @@
\xdef\hex@eff@row{\pgfmathresult}%
\hex@dbg{2}{Effective row: \hex@coords@row@fac * (\hex@row +
\hex@coords@row@off) -> \hex@eff@row}%
- \pgfmathparse{(2*\hex@eff@row-mod(round((\hex@col+\hex@coords@col@off)),2))*\hex@yy}%
+ %\pgfmathparse{(2*\hex@eff@row-mod(round((\hex@col+\hex@coords@col@off)),2))*\hex@yy}%
\pgfmathparse{(2*\hex@eff@row-mod(abs(round(\hex@col+\hex@coords@col@off)),2))*\hex@yy}%
\xdef\hex@y{\pgfmathresult}%
\ifx\hex@vtx\@empty\else%
@@ -533,15 +535,19 @@
code/.store in=\hex@t@code,%
clip/.store in=\hex@t@clip,%
random rotation/.is if=@hex@t@rot,
+ rotate/.store in=\hex@t@s@angle,
pic/.default=,
image/.default=,
code/.default=,
clip/.default=,
+ rotate/.default=,
}
\iffalse
\tikzset{
/hex/terrain/.cd,%
beach/.style={pic=hex/terrain/beach},
+ fields/.style={pic=hex/terrain/fields},
+ speckle/.style={pic=hex/terrain/speckle},
light woods/.style={pic=hex/terrain/light woods},
woods/.style={pic=hex/terrain/woods},
swamp/.style={pic=hex/terrain/swamp},
@@ -555,6 +561,8 @@
\tikzset{
/hex/terrain/.cd,%
beach/.style={image=wargame.beach},
+ fields/.style={image=wargame.fields},
+ speckle/.style={image=wargame.speckle},
light woods/.style={image=wargame.light_woods},
woods/.style={image=wargame.woods},
swamp/.style={image=wargame.swamp},
@@ -597,6 +605,12 @@
\if@hex@t@rot%
\pgfmathrandominteger{\hex@t@angle}{0}{5}
\pgfmathparse{int(60*\hex@t@angle)}\edef\hex@t@angle{\pgfmathresult}%
+ \else%
+ \@ifundefined{hex@t@s@angle}{}{
+ \ifx\hex@t@s@angle\@empty%
+ \else%
+ \edef\hex@t@angle{\hex@t@s@angle}%
+ \fi}%
\fi%
\hex@dbg{5}{Will rotate terrain by `\hex@t@angle'}%
\scope[rotate=\hex@t@angle]%
@@ -671,7 +685,7 @@
pics/hex/#2sextant/S/.style=hex/#2sextant/south,
pics/hex/#2sextant/SE/.style=hex/#2sextant/south east,
pics/hex/#2sextant/C/.style=hex/#2sextant/center,
- }
+ }%
}
\hex@make@sextants{.7}{}
\hex@make@sextants{.3}{large }
@@ -1347,6 +1361,83 @@
}
\fi
\tikzset{
+ hex/terrain/fields/.style={%
+ draw=none%
+ }%
+}
+\ifhex@terrain@pic
+\tikzset{
+ hex/terrain/fields/.pic={
+ \path[draw=none,fill=none](1,0)
+ --(60:1)
+ --(120:1)
+ --(180:1)
+ --(240:1)
+ --(300:1)
+ --cycle;
+ \fill[black,opacity=.05] ( .1, .3)rectangle++(.5,.4);
+ \fill[white,opacity=.15] (-.65, -.5)rectangle++(.3,.5);
+ \fill[white,opacity=.25] (-.60, .2)rectangle++(.6,.5);
+ \fill[black,opacity=.02] (-.30, -.1)rectangle++(.4,.2);
+ \fill[black,opacity=.02] (-.50, -.8)rectangle++(.4,.25);
+ \fill[black,opacity=.05] (-.30, -.5)rectangle++(.4,.35);
+ \fill[white,opacity=.15] ( .15, -.6)rectangle++(.4,.8);
+ \fill[black,opacity=.02] (-.05, -.8)rectangle++(.5,.15);
+ \fill[black,opacity=.02] (-.8, -.3)rectangle++(.1,.6);
+ \fill[black,opacity=.02] ( .6, -.35)rectangle++(.2,.6);
+ }
+}
+\fi
+\tikzset{
+ hex/terrain/speckle/.style={%
+ }%
+}
+\ifhex@terrain@pic
+\pgfmathdeclarerandomlist{black white speckles}{{black}{white}}
+\pgfmathdeclarerandomlist{gray white speckles}{{gray}{white}}
+\tikzset{
+ hex/terrain/speckle/minimum radius/.initial=3,
+ hex/terrain/speckle/maximum radius/.initial=10,
+ hex/terrain/speckle/minimum opacity/.initial=3,
+ hex/terrain/speckle/maximum opacity/.initial=7,
+ %%
+ pics/hex/terrain/speckle/.style args={#1,#2}{
+ code={
+ \tikzset{
+ hex/terrain/speckle/minimum radius/.get=\minR,
+ hex/terrain/speckle/maximum radius/.get=\maxR,
+ hex/terrain/speckle/minimum opacity/.get=\minO,
+ hex/terrain/speckle/maximum opacity/.get=\maxO,
+ }
+ \foreach \i in {1,...,#1}{
+
+ \pgfmathrandominteger{\R}{\minR}{\maxR}
+ \pgfmathrandominteger{\n}{1}{3}% Sub trapezoid
+ \pgfmathrandominteger{\x}{0}{100}% X coordinate
+ \pgfmathrandominteger{\y}{0}{100}% Y coordinate
+ \pgfmathrandominteger{\o}{\minO}{\maxO}% Opacity
+ \pgfmathrandomitem{\c}{#2}
+ \pgfmathparse{\x/100}\edef\x{\pgfmathresult}
+ \pgfmathparse{\y/100}\edef\y{\pgfmathresult}
+ \pgfmathparse{\R/100}\edef\R{\pgfmathresult}
+ \pgfmathparse{\o/100}\edef\o{\pgfmathresult}
+ \pgfmathparse{1-\R}\edef\O{\pgfmathresult}
+ \ifnum\n=1
+ \fill[\c,opacity=\o]($\y*(120:\O)+(\x-\R,0)$) circle(\R);
+ \else
+ \ifnum\n=2
+ \fill[\c,opacity=\o]($\y*(240:\O)+(\x-\R,0)$) circle(\R);
+ \else
+ \fill[\c,opacity=\o]($\x*(120:\O)+\y*(240:\O)$) circle(\R);
+ \fi
+ \fi
+ }
+ }
+ },
+ pics/hex/terrain/speckle/.default={200,gray white speckles}
+}
+\fi
+\tikzset{
hex/terrain/light woods/.style={
draw=none,
fill={rgb,100:red,69;green,98;blue,69}
@@ -12832,170 +12923,170 @@
\@ifnextchar[{\bo@rdfr@me@}{\bo@rdfr@me@[]}%]
}
\def\bo@rdfr@me@u(#1)#2#3#4#5{
- \hex@coords@conv{#1}
+ \hex@coords@conv{#1}%
% \hex@dbg{0}{#1 -> `\hex@x',`\hex@y'}
- \pgfmathparse{min(#2,\hex@x)}\xdef#2{\pgfmathresult}
- \pgfmathparse{min(#3,\hex@y)}\xdef#3{\pgfmathresult}
- \pgfmathparse{max(#4,\hex@x)}\xdef#4{\pgfmathresult}
- \pgfmathparse{max(#5,\hex@y)}\xdef#5{\pgfmathresult}
- \hex@dbg{2}{#1 -> ll=`#2',`#3', ur=`#4',`#5'}
+ \pgfmathparse{min(#2,\hex@x)}\xdef#2{\pgfmathresult}%
+ \pgfmathparse{min(#3,\hex@y)}\xdef#3{\pgfmathresult}%
+ \pgfmathparse{max(#4,\hex@x)}\xdef#4{\pgfmathresult}%
+ \pgfmathparse{max(#5,\hex@y)}\xdef#5{\pgfmathresult}%
+ \hex@dbg{2}{#1 -> ll=`#2',`#3', ur=`#4',`#5'}%
}
-\def\bo@rdfr@me@[#1]#2#3#4#5{
+\def\bo@rdfr@me@[#1]#2#3#4#5{%
% Define rtmp and a ctmp to by directions
- \pgfmathparse{int(\hex@coords@row@fac)}\edef\rtmp{\pgfmathresult}
- \pgfmathparse{int(\hex@coords@col@fac)}\edef\ctmp{\pgfmathresult}
+ \pgfmathparse{int(\hex@coords@row@fac)}\edef\rtmp{\pgfmathresult}%
+ \pgfmathparse{int(\hex@coords@col@fac)}\edef\ctmp{\pgfmathresult}%
% Define vertices for path
- \def\ctfv{SW}
- \def\ctsv{SE}
- \def\cbfv{NE}
- \def\cbsv{NW}
- \def\rrfv{E}
- \def\rrsv{NE}
- \def\rlfv{W}
- \def\rlsv{SW}
+ \def\ctfv{SW}%
+ \def\ctsv{SE}%
+ \def\cbfv{NE}%
+ \def\cbsv{NW}%
+ \def\rrfv{E}%
+ \def\rrsv{NE}%
+ \def\rlfv{W}%
+ \def\rlsv{SW}%
% Swap around some definitions based on the row direction
- \ifnum\rtmp<0
- \let\max@short\hex@bot@short@col
- \let\min@short\hex@top@short@col
- \let\swp\ctfv\let\ctfv\cbsv\let\cbsv\swp
- \let\swp\ctsv\let\ctsv\cbfv\let\cbfv\swp
- \def\rrsv{SE}
- \def\rlsv{NW}
- \else
- \let\max@short\hex@top@short@col
- \let\min@short\hex@bot@short@col
- \fi
+ \ifnum\rtmp<0%
+ \let\max@short\hex@bot@short@col%
+ \let\min@short\hex@top@short@col%
+ \let\swp\ctfv\let\ctfv\cbsv\let\cbsv\swp%
+ \let\swp\ctsv\let\ctsv\cbfv\let\cbfv\swp%
+ \def\rrsv{SE}%
+ \def\rlsv{NW}%
+ \else%
+ \let\max@short\hex@top@short@col%
+ \let\min@short\hex@bot@short@col%
+ \fi%
% Swap around some definitions based on the column direction
- \ifnum\ctmp<0
- \let\swp\ctfv\let\ctfv\ctsv\let\ctsv\swp
- \let\swp\cbfv\let\cbfv\cbsv\let\cbsv\swp
- \let\swp\rrfv\let\rrfv\rlsv\let\rlsv\swp
- \let\swp\rrsv\let\rrsv\rlfv\let\rlfv\swp
- \fi
+ \ifnum\ctmp<0%
+ \let\swp\ctfv\let\ctfv\ctsv\let\ctsv\swp%
+ \let\swp\cbfv\let\cbfv\cbsv\let\cbsv\swp%
+ \let\swp\rrfv\let\rrfv\rlsv\let\rlsv\swp%
+ \let\swp\rrsv\let\rrsv\rlfv\let\rlfv\swp%
+ \fi%
% Define tmp = 0 if no shorts, 1 if top short, 2 if both
\pgfmathparse{ifthenelse(\hex@got@top@short,
- ifthenelse(\hex@got@bot@short,2,1),0)}\edef\tmp{\pgfmathresult}
+ ifthenelse(\hex@got@bot@short,2,1),0)}\edef\tmp{\pgfmathresult}%
% If top-short, set factors
- \ifnum\tmp=1
- \def\mnf{-1}
- \def\mxf{-1}
- \def\mnn{}
- \def\mxn{}
+ \ifnum\tmp=1%
+ \def\mnf{-1}%
+ \def\mxf{-1}%
+ \def\mnn{}%
+ \def\mxn{}%
% If both short, set factors
- \else\ifnum\tmp=2
- \def\mnf{\rtmp}
- \def\mxf{(-\rtmp)}
+ \else\ifnum\tmp=2%
+ \def\mnf{\rtmp}%
+ \def\mxf{(-\rtmp)}%
% If inverse rows, set factors
- \ifnum\rtmp<0
- \def\mnn{}
- \def\mxn{not}
- \else
- \def\mnn{not}
- \def\mxn{}
- \fi
+ \ifnum\rtmp<0%
+ \def\mnn{}%
+ \def\mxn{not}%
+ \else%
+ \def\mnn{not}%
+ \def\mxn{}%
+ \fi%
% If none is short
- \else
- \def\mnf{1}
- \def\mxf{1}
- \def\mnn{not}
- \def\mxn{not}
- \fi\fi
+ \else%
+ \def\mnf{1}%
+ \def\mxf{1}%
+ \def\mnn{not}%
+ \def\mxn{not}%
+ \fi\fi%
% Define row@mn to give least row of column
\def\row@mn##1{%
\pgfmathparse{int(#3+\mnf*
\hex@coords@row@fac*\min@short(##1)*
- \mnn(\min@short(\hex@coords@col@off)))}
- \edef\lr{\pgfmathresult}}
+ \mnn(\min@short(\hex@coords@col@off)))}%
+ \edef\lr{\pgfmathresult}}%
% Define row@mx to give largest row of column
\def\row@mx##1{%
\pgfmathparse{int(#5+\mxf*
\hex@coords@row@fac*\max@short(##1)*
- \mxn(\max@short(\hex@coords@col@off)))}
- \edef\ur{\pgfmathresult}}
+ \mxn(\max@short(\hex@coords@col@off)))}%
+ \edef\ur{\pgfmathresult}}%
%
%
% Below defines a path around the perimeter of the hexes.
%
- \def\@llx{10000}
- \def\@lly{10000}
- \def\@urx{-10000}
- \def\@ury{-10000}
+ \def\@llx{10000}%
+ \def\@lly{10000}%
+ \def\@urx{-10000}%
+ \def\@ury{-10000}%
% Start with an empty path
\def\p{}
% Loop across least row (can be top if \rtmp<0)
\foreach \c in {#2,...,#4}{%
- \row@mn{\c}
- \row@mx{\c}
+ \row@mn{\c}%
+ \row@mx{\c}%
% \message{^^JColumn: `\c' -> `\lr',`\ur' (#3,#5)}
}
\foreach \c in {#2,...,#4}{%
- \row@mn{\c}
+ \row@mn{\c}%
\xdef\p{\p
(hex cs:c=\c,r=\lr,v=\ctfv)--
- (hex cs:c=\c,r=\lr,v=\ctsv)--}
- \bo@rdfr@me@u(c=\c,r=\lr,v=\ctfv)\@llx\@lly\@urx\@ury
- \bo@rdfr@me@u(c=\c,r=\lr,v=\ctsv)\@llx\@lly\@urx\@ury
- }
+ (hex cs:c=\c,r=\lr,v=\ctsv)--}%
+ \bo@rdfr@me@u(c=\c,r=\lr,v=\ctfv)\@llx\@lly\@urx\@ury%
+ \bo@rdfr@me@u(c=\c,r=\lr,v=\ctsv)\@llx\@lly\@urx\@ury%
+ }%
% Go up (down if \rtmp<0) right side
- \row@mn{#4}
- \row@mx{#4}
+ \row@mn{#4}%
+ \row@mx{#4}%
\foreach \r in {\lr,...,\ur}{%
\xdef\p{\p
(hex cs:c=#4,r=\r,v=\rrfv)--
- (hex cs:c=#4,r=\r,v=\rrsv)--}
- \bo@rdfr@me@u(c=#4,r=\r,v=\rrfv)\@llx\@lly\@urx\@ury
- \bo@rdfr@me@u(c=#4,r=\r,v=\rrsv)\@llx\@lly\@urx\@ury
- }
+ (hex cs:c=#4,r=\r,v=\rrsv)--}%
+ \bo@rdfr@me@u(c=#4,r=\r,v=\rrfv)\@llx\@lly\@urx\@ury%
+ \bo@rdfr@me@u(c=#4,r=\r,v=\rrsv)\@llx\@lly\@urx\@ury%
+ }%
% Go across largest row (can be bottom if \rtmp<0)
\foreach \c in {#4,...,#2}{%
- \row@mx{\c}
+ \row@mx{\c}%
% \message{^^JColumn: `\c', max:`\ur'}
\xdef\p{\p
(hex cs:c=\c,r=\ur,v=\cbfv)--
- (hex cs:c=\c,r=\ur,v=\cbsv)--}
- \bo@rdfr@me@u(c=\c,r=\ur,v=\cbfv)\@llx\@lly\@urx\@ury
- \bo@rdfr@me@u(c=\c,r=\ur,v=\cbsv)\@llx\@lly\@urx\@ury
+ (hex cs:c=\c,r=\ur,v=\cbsv)--}%
+ \bo@rdfr@me@u(c=\c,r=\ur,v=\cbfv)\@llx\@lly\@urx\@ury%
+ \bo@rdfr@me@u(c=\c,r=\ur,v=\cbsv)\@llx\@lly\@urx\@ury%
}
% Go up (down if \rtmp<0) left side.
- \row@mn{#2}
- \row@mx{#2}
+ \row@mn{#2}%
+ \row@mx{#2}%
\foreach \r in {\ur,...,\lr}{%
\xdef\p{\p
(hex cs:c=#2,r=\r,v=\rlfv)--
- (hex cs:c=#2,r=\r,v=\rlsv)--}
- \bo@rdfr@me@u(c=#2,r=\r,v=\rlfv)\@llx\@lly\@urx\@ury
- \bo@rdfr@me@u(c=#2,r=\r,v=\rlsv)\@llx\@lly\@urx\@ury
- }
+ (hex cs:c=#2,r=\r,v=\rlsv)--}%
+ \bo@rdfr@me@u(c=#2,r=\r,v=\rlfv)\@llx\@lly\@urx\@ury%
+ \bo@rdfr@me@u(c=#2,r=\r,v=\rlsv)\@llx\@lly\@urx\@ury%
+ }%
% End path with cycle
- \edef\p{\p cycle}
+ \edef\p{\p cycle}%
% Define global path
- \global\let\hex@board@path\p
- \hex@dbg{3}{Hex board path: `\meaning\hex@board@path'}
+ \global\let\hex@board@path\p%
+ \hex@dbg{3}{Hex board path: `\meaning\hex@board@path'}%
% If an optional argument was given, then use that to actually make
% hexes.
- \ifx|#1|\else
+ \ifx|#1|\else%
\foreach[count=\nc] \c in {#2,...,#4}{%
- \row@mn{\c}
- \row@mx{\c}
+ \row@mn{\c}%
+ \row@mx{\c}%
\foreach \r in {\lr,...,\ur}{%
- \hex[#1={\c,\r}](c=\c,r=\r)
- }
- }
- \fi
-}
+ \hex[#1={\c,\r}](c=\c,r=\r)%
+ }%
+ }%
+ \fi%
+}%
\tikzset{%
- /hex/board/no op/.style args={#1,#2}{}}
+ /hex/board/no op/.style args={#1,#2}{}}%
\def\boardhexes{%
\@ifnextchar[{\bo@rdhexes}{\bo@rdhexes[board/no op]}%]
-}
+}%
\def\bo@rdhexes[#1](#2)(#3){%
- \hex@coords@conv{#2}
- \edef\llc{\hex@col}
- \edef\llr{\hex@row}
- \hex@coords@conv{#3}
- \edef\urc{\hex@col}
- \edef\urr{\hex@row}
- \bo@rdfr@me[#1]{\llc}{\llr}{\urc}{\urr}}
+ \hex@coords@conv{#2}%
+ \edef\llc{\hex@col}%
+ \edef\llr{\hex@row}%
+ \hex@coords@conv{#3}%
+ \edef\urc{\hex@col}%
+ \edef\urr{\hex@row}%
+ \bo@rdfr@me[#1]{\llc}{\llr}{\urc}{\urr}}%
\tikzset{board frame bb/.code={
\pgfkeys{
%/tikz/local bounding box=tmp board frame,
@@ -13011,65 +13102,66 @@
}}}}
\def\bo@rdframe[#1](#2)(#3){%
- \hex@coords@conv{#2}
- \edef\llc{\hex@col}
- \edef\llr{\hex@row}
+ \hex@coords@conv{#2}%
+ \edef\llc{\hex@col}%
+ \edef\llr{\hex@row}%
%
\hex@coords@conv{#3}
- \edef\urc{\hex@col}
- \edef\urr{\hex@row}
+ \edef\urc{\hex@col}%
+ \edef\urr{\hex@row}%
%
- \def\margin{#1}
+ \def\margin{#1}%
%
% This will store the bounding box in tmp node `board frame'
\bo@rdfr@me{\llc}{\llr}{\urc}{\urr}%
- \begin{scope}[board frame bb]
- \expandafter\path\hex@board@path;
- \end{scope}
- \hex@dbg{1}{Board frame LL: -> `\llx',`\lly'}
- \pgfmathparse{\llx+ifthenelse(\llx<0,-1,1)*\margin}\edef\llx{\pgfmathresult}
- \pgfmathparse{\lly+ifthenelse(\lly<0,-1,1)*\margin}\edef\lly{\pgfmathresult}
+ \begin{scope}[board frame bb]%
+ \expandafter\path\hex@board@path;%
+ \end{scope}%
+ \hex@dbg{1}{Board frame LL: -> `\llx',`\lly'}%
+ \pgfmathparse{\llx+ifthenelse(\llx<0,-1,1)*\margin}\edef\llx{\pgfmathresult}%
+ \pgfmathparse{\lly+ifthenelse(\lly<0,-1,1)*\margin}\edef\lly{\pgfmathresult}%
%
- \hex@dbg{1}{Board frame UR: -> `\urx',`\ury'}
- \pgfmathparse{\urx+ifthenelse(\urx<0,-1,1)*\margin}\edef\urx{\pgfmathresult}
- \pgfmathparse{\ury+ifthenelse(\ury<0,-1,1)*\margin}\edef\ury{\pgfmathresult}
+ \hex@dbg{1}{Board frame UR: -> `\urx',`\ury'}%
+ \pgfmathparse{\urx+ifthenelse(\urx<0,-1,1)*\margin}\edef\urx{\pgfmathresult}%
+ \pgfmathparse{\ury+ifthenelse(\ury<0,-1,1)*\margin}\edef\ury{\pgfmathresult}%
%
- \pgfmathparse{\urx-\llx}\edef\w{\pgfmathresult}
- \pgfmathparse{\ury-\lly}\edef\h{\pgfmathresult}
+ \pgfmathparse{\urx-\llx}\edef\w{\pgfmathresult}%
+ \pgfmathparse{\ury-\lly}\edef\h{\pgfmathresult}%
%% Print to the log
- \hex@dbg{0}{Board Frame: (\llx,\lly)x(\urx,\ury) (\w x\h) (\llc,\llr)x(\urc,\urr)}
+ \hex@dbg{0}{Board Frame: (\llx,\lly)x(\urx,\ury) (\w x\h) (\llc,\llr)x(\urc,\urr)}%
%% Possibly draw
- \draw[hex/board frame/.try](\llx,\lly) rectangle(\urx,\ury);
+ \draw[hex/board frame/.try](\llx,\lly) rectangle(\urx,\ury);%
%% Store macros
\xdef\boardXmin{\llx}%
\xdef\boardYmin{\lly}%
\xdef\boardXmax{\urx}%
\xdef\boardYmax{\ury}%
+ \@ifnextchar;{\@gobble}{}%
}
-\def\boardpath(#1)(#2){
+\def\boardpath(#1)(#2){%
\hex@coords@reset%
- \tikzset{/hex/coords/.cd, #1}
- \edef\llc{\hex@col}
- \edef\llr{\hex@row}
+ \tikzset{/hex/coords/.cd, #1}%
+ \edef\llc{\hex@col}%
+ \edef\llr{\hex@row}%
%%
\hex@coords@reset%
- \tikzset{/hex/coords/.cd, #2}
- \edef\urc{\hex@col}
- \edef\urr{\hex@row}
-
+ \tikzset{/hex/coords/.cd, #2}%
+ \edef\urc{\hex@col}%
+ \edef\urr{\hex@row}%
% This will store the bounding box in tmp node `board frame'
\bo@rdfr@me{\llc}{\llr}{\urc}{\urr}%
%% Use the path to extract the bounding box
%\begin{scope}[local bounding box=board frame]
% \expandafter\path\hex@board@path;
%\end{scope}
- \global\let\hexboardpath\hex@board@path
+ \global\let\hexboardpath\hex@board@path%
+ \@ifnextchar;{\@gobble}{}%
}
\def\boardclip(#1)(#2)#3{%
- \boardpath(#1)(#2)
+ \boardpath(#1)(#2)%
\draw \ifx|#3|\else[preaction={#3}]\fi%
- [clip] \hexboardpath;
+ [clip] \hexboardpath;%
}
\def\debuggrid{%
diff --git a/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.natoapp6c.code.tex b/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.natoapp6c.code.tex
index fe65f5779e2..531065c91b9 100644
--- a/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.natoapp6c.code.tex
+++ b/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.natoapp6c.code.tex
@@ -297,8 +297,8 @@
\pgfdeclareshape{natoapp6c friendly equipment}{%
\inheritsavedanchors[from=natoapp6c base]
\savedanchor\northeast{%
- \pgf@x=\n@to@pp@r%
- \pgf@y=\n@to@pp@r}
+ \pgf@x=1.2\n@to@pp@r%
+ \pgf@y=1.2\n@to@pp@r}
\anchor{north east}{\northeast}
\anchor{north west}{\northeast\pgf@x=-\pgf@x}
\anchor{south east}{\northeast\pgf@y=-\pgf@y}
@@ -484,6 +484,49 @@
\backgroundpath{}
\behindforegroundpath{}
}
+\def\n@to@friendly@l@nd{%
+ \northeast \wg@tmpa=\pgf@x\wg@tmpb=\pgf@y%
+ \pgfpathmoveto{\pgfqpoint{ \wg@tmpa}{ \wg@tmpb}}%
+ \pgfpathlineto{\pgfqpoint{-\wg@tmpa}{ \wg@tmpb}}%
+ \pgfpathlineto{\pgfqpoint{-\wg@tmpa}{-\wg@tmpb}}%
+ \pgfpathlineto{\pgfqpoint{ \wg@tmpa}{-\wg@tmpb}}%
+ \pgfclosepath}
+\def\n@to@pp@friendl@dismounted{%
+ \northeast\wg@tmpa=\pgf@x\wg@tmpb\pgf@y%
+ \pgfpathmoveto{\pgfpoint{-\wg@tmpa}{-.5\wg@tmpb}}%
+ \pgfpathlineto{\pgfpoint{-\wg@tmpa}{ .5\wg@tmpb}}%
+ \pgfpathlineto{\pgfpoint{0cm} { \wg@tmpb}}%
+ \pgfpathlineto{\pgfpoint{ \wg@tmpa}{ .5\wg@tmpb}}%
+ \pgfpathlineto{\pgfpoint{ \wg@tmpa}{-.5\wg@tmpb}}%
+ \pgfpathlineto{\pgfpoint{0cm} { -\wg@tmpb}}%
+ \pgfclosepath%
+}%
+\pgfdeclareshape{natoapp6c friendly dismounted}{%
+ \inheritsavedanchors[from=natoapp6c base]
+ \savedanchor\northeast{%
+ \pgf@x=1.1\n@to@pp@r%
+ \pgf@y=1.1\n@to@pp@r}
+ \anchor{north east}{\northeast}
+ \anchor{north west}{\northeast\pgf@x=-\pgf@x}
+ \anchor{south east}{\northeast\pgf@y=-\pgf@y}
+ \anchor{south west}{\northeast\pgf@x=-\pgf@x\pgf@y=-\pgf@y}
+ \anchor{north}{\northeast\pgf@x=0cm}
+ \anchor{south}{\northeast\pgf@x=0cm\pgf@y=-\pgf@y}
+ \anchor{east}{\northeast\pgf@y=0cm}
+ \anchor{west}{\northeast\pgf@x=-\pgf@x\pgf@y=0cm}
+ \inheritanchor[from=natoapp6c base]{upper}
+ \inheritanchor[from=natoapp6c base]{lower}
+ \inheritanchor[from=natoapp6c base]{left}
+ \inheritanchor[from=natoapp6c base]{right}
+ \inheritanchor[from=natoapp6c base]{center}
+ \backgroundpath{%
+ \n@to@pp@friendl@dismounted%
+ }
+ \behindforegroundpath{%
+ \n@to@pp@friendl@dismounted%
+ \pgfusepath{stroke}%
+ }
+}
\def\n@to@hostile@@ir{%
\southeast \wg@tmpa=\pgf@x\wg@tmpb=\pgf@y%
\cntrl \wg@tmpc=\pgf@y%
@@ -813,6 +856,28 @@
\pgfusepath{stroke}%
}
}
+\pgfdeclareshape{natoapp6c hostile dismounted}{%
+ \inheritsavedanchors[from=natoapp6c hostile land]
+ \inheritanchor[from=natoapp6c hostile land]{inner north east}
+ \inheritanchor[from=natoapp6c hostile land]{inner north west}
+ \inheritanchor[from=natoapp6c hostile land]{inner south west}
+ \inheritanchor[from=natoapp6c hostile land]{inner south east}
+ \inheritanchor[from=natoapp6c hostile land]{north east}
+ \inheritanchor[from=natoapp6c hostile land]{north west}
+ \inheritanchor[from=natoapp6c hostile land]{south east}
+ \inheritanchor[from=natoapp6c hostile land]{south west}
+ \inheritanchor[from=natoapp6c hostile land]{north}
+ \inheritanchor[from=natoapp6c hostile land]{west}
+ \inheritanchor[from=natoapp6c hostile land]{east}
+ \inheritanchor[from=natoapp6c hostile land]{south}
+ \inheritanchor[from=natoapp6c hostile land]{upper}
+ \inheritanchor[from=natoapp6c hostile land]{lower}
+ \inheritanchor[from=natoapp6c hostile land]{left}
+ \inheritanchor[from=natoapp6c hostile land]{right}
+ \inheritanchor[from=natoapp6c hostile land]{center}
+ \inheritbackgroundpath[from=natoapp6c hostile land]
+ \inheritbehindforegroundpath[from=natoapp6c hostile land]
+}
\def\n@to@pp@neutr@l@init{%
\northeast\wg@tmpa=\pgf@x\wg@tmpb=\pgf@y%
\def\n@to@pp@neutr@l@left {\pgflineto{\pgfqpoint{-\wg@tmpa}{-\wg@tmpb}}}%
@@ -1111,6 +1176,29 @@
\pgfusepath{stroke}%
}
}
+\pgfdeclareshape{natoapp6c neutral dismounted}{%
+ \inheritsavedanchors[from=natoapp6c neutral land]
+ \inheritanchor[from=natoapp6c neutral land]{center}
+ \inheritanchor[from=natoapp6c neutral land]{inner north east}
+ \inheritanchor[from=natoapp6c neutral land]{inner north west}
+ \inheritanchor[from=natoapp6c neutral land]{inner south west}
+ \inheritanchor[from=natoapp6c neutral land]{inner south east}
+ \inheritanchor[from=natoapp6c neutral land]{north east}
+ \inheritanchor[from=natoapp6c neutral land]{north west}
+ \inheritanchor[from=natoapp6c neutral land]{south east}
+ \inheritanchor[from=natoapp6c neutral land]{south west}
+ \inheritanchor[from=natoapp6c neutral land]{north}
+ \inheritanchor[from=natoapp6c neutral land]{west}
+ \inheritanchor[from=natoapp6c neutral land]{east}
+ \inheritanchor[from=natoapp6c neutral land]{south}
+ \inheritanchor[from=natoapp6c neutral land]{upper}
+ \inheritanchor[from=natoapp6c neutral land]{lower}
+ \inheritanchor[from=natoapp6c neutral land]{left}
+ \inheritanchor[from=natoapp6c neutral land]{right}
+ \inheritanchor[from=natoapp6c neutral land]{center}
+ \inheritbackgroundpath[from=natoapp6c neutral land]
+ \inheritbehindbackgroundpath[from=natoapp6c neutral land]
+}
\def\n@to@pp@unknown@init{%
\def\n@to@pp@unknown@top{%
\innernortheast \wg@tmpa=\pgf@x%
@@ -1485,6 +1573,28 @@
\n@to@pp@unknown@right %
\pgfusepath{stroke}}
}
+\pgfdeclareshape{natoapp6c unknown dismounted}{%
+ \inheritsavedanchors[from=natoapp6c unknown land]
+ \inheritanchor[from=natoapp6c unknown land]{inner north east}
+ \inheritanchor[from=natoapp6c unknown land]{inner north west}
+ \inheritanchor[from=natoapp6c unknown land]{inner south west}
+ \inheritanchor[from=natoapp6c unknown land]{inner south east}
+ \inheritanchor[from=natoapp6c unknown land]{north east}
+ \inheritanchor[from=natoapp6c unknown land]{north west}
+ \inheritanchor[from=natoapp6c unknown land]{south east}
+ \inheritanchor[from=natoapp6c unknown land]{south west}
+ \inheritanchor[from=natoapp6c unknown land]{north}
+ \inheritanchor[from=natoapp6c unknown land]{west}
+ \inheritanchor[from=natoapp6c unknown land]{east}
+ \inheritanchor[from=natoapp6c unknown land]{south}
+ \inheritanchor[from=natoapp6c unknown land]{upper}
+ \inheritanchor[from=natoapp6c unknown land]{lower}
+ \inheritanchor[from=natoapp6c unknown land]{left}
+ \inheritanchor[from=natoapp6c unknown land]{right}
+ \inheritanchor[from=natoapp6c unknown land]{center}
+ \inheritbackgroundpath[from=natoapp6c unknown land]
+ \inheritbehindforegroundpath[from=natoapp6c unknown land]
+}
\def\n@to@pp@e@y{.12}
\def\n@to@pp@e@yy{.24}
\def\n@to@pp@e@d#1{($(#1*\n@to@pp@e@y,0)$) circle(0.09)}
@@ -1574,6 +1684,7 @@
fac/.store in=\natoapp@fac,
cmd/.store in=\natoapp@cmd,
ech/.store in=\natoapp@ech,
+ path/.store in=\n@to@ppp@th
}
\tikzset{
/natoapp6c/.cd,
@@ -1602,6 +1713,7 @@
command/space/.style={cmd=space},
command/sub surface/.style={cmd=sub surface},
command/sea mine/.style={cmd=sub surface},
+ command/dismounted/.style={cmd=dismounted},
command/none/.style={cmd=none},
}
\tikzset{
@@ -1656,7 +1768,7 @@
\tikzset{%
natoapp6c/.code={%
\pgfkeys{/tikz/transform shape,/tikz/shape=natoapp6c}
- \pgfkeys{/natoapp6c/.cd,#1}}}
+ \pgfkeys{/natoapp6c/.cd,path=natoapp6c/s/,#1}}}
\newcounter{natoappid}\setcounter{natoappid}{0}
\newif\ifn@to@pp@below\n@to@pp@belowfalse%
\newif\ifn@to@pp@mod\n@to@pp@modfalse%
@@ -1685,6 +1797,7 @@
\edef\frameopt{\natoapp@frame}}
\n@to@pp@dbg{3}{NATO App6(c) Frame options: \meaning\frameopt}%
}
+ \savedmacro\thisname{\def\thisname{natoapp6c}}
\anchor{center} {\center}
\anchor{north east}{\wg@sub@nchor{M\id}{north east}}
\anchor{north west}{\wg@sub@nchor{M\id}{north west}}
@@ -1699,17 +1812,26 @@
\anchor{left} {\wg@sub@nchor{M\id}{left}}
\anchor{right} {\wg@sub@nchor{M\id}{right}}
\anchor{echelon} {%
- \n@to@pp@dbg{3}{NATO App6(c) get echelon anchor}%
- \wg@sub@nchor{M\id}{north}%
- \wg@tmpa=\n@to@pp@e@y cm%
+ \wg@sub@nchor{M}{north}%
+ \wg@tmpa\pgflinewidth% by 1.5%
+ %\wg@getscale%
+ %\pgfmathparse{ifthenelse(\wg@scale>0.00001,\wg@tmpa/\wg@scale,\wg@tmpa)}
+ %\edef\wg@a{\pgfmathresult}\pgfmathsetlength{\wg@tmpa}{\wg@a pt}
+ %\n@to@pp@dbg{0}{Scale is `\wg@scale' -> `\the\wg@tmpa'}%
+ %\divide\wg@tmpa by \wg@scale%
+ \advance\wg@tmpa by\n@to@pp@e@y cm%
\advance\pgf@y\wg@tmpa%
- }%
+ }
\anchor{below} {%
\n@to@pp@dbg{3}{NATO App6(c) get below anchor}%
- \wg@sub@nchor{M\id}{south}
+ \wg@sub@nchor{M}{south}%
\wg@tmpa=\n@to@pp@e@yy cm%
- \advance\pgf@y-\wg@tmpa}
+ \advance\wg@tmpa-\pgflinewidth% by 1.5%
+ \advance\pgf@y-\wg@tmpa%
+ }
\behindbackgroundpath{%
+ \wg@ignore@sub@nchortrue%
+ \n@to@pp@dbg{3}{NATO App6(c) Before print}
\n@to@pp@dbg{3}{NATO App6(c) background path: \meaning\id
^^J ID: \meaning\natoapp@id
^^J Faction: \meaning\natoapp@fac
@@ -1734,7 +1856,7 @@
%% Clip to shape in scope
%% \message{^^JClipping to NATO App6(c) shape}
\n@to@pp@iscliptrue%
- \n@to@pp@dbg{2}{NATO App6(c) frame node M (clip)}
+ \n@to@pp@dbg{1}{NATO App6(c) frame node M (clip)}
\pgfnode{natoapp6c \frameshape}{center}{}{M}{\pgfusepath{clip}}
\n@to@pp@isclipfalse%
%% Start new scope including frame key options
@@ -1752,9 +1874,10 @@
\endscope%
% Render mains
\@ifundefined{natoapp@main}{}{
- \n@to@pp@dbg{2}{NATO App6(c) mains: \meaning\natoapp@main}
+ \n@to@pp@dbg{1}{NATO App6(c) mains: \meaning\natoapp@main}
\begin{scope}[natoapp6c/main]
- \wg@pic@all{\natoapp@main}{natoapp6c/s/}{M.center}{natoapp6c/main}%
+ \n@to@pp@dbg{1}{NATO symbol path `\n@to@ppp@th'}
+ \wg@pic@all{\natoapp@main}{\n@to@ppp@th}{M.center}{natoapp6c/main}%
\end{scope}}%
% Modififiers flagged
\n@to@pp@modtrue
@@ -1788,41 +1911,51 @@
\endpgfinterruptboundingbox
\end{scope}%
\fi%
+ \wg@ignore@sub@nchorfalse%
}
\behindforegroundpath{%
- \n@to@pp@dbg{2}{NATO App6(c) foreground path:
+ \wg@ignore@sub@nchortrue%
+ \n@to@pp@dbg{2}{NATO App6(c) foreground path: `\meaning\id'
^^J Echelon: \meaning\natoapp@ech
^^J Symbol: \meaning\frameshape
^^J Below: \meaning\natoapp@below
^^J Frame: \meaning\frameopt}
%
+ %
\ifx\frameshape\pgfutil@empty%
\n@to@pp@dbg{2}{NATO App6(c) has no frame shape!}%
\else%
-
- \edef\tmp@opt{[\frameopt]}
- \expandafter\scope\tmp@opt
- \n@to@pp@dbg{2}{NATO App6(c) inner node `M\id' ===}
- \pgfnode{natoapp6c \frameshape}{center}{}{M\id}{\pgfusepath{stroke}}
+ \edef\tmp@opt{[\frameopt]}
+ \expandafter\scope\tmp@opt
+ \edef\mid{M\id{}}
+ \n@to@pp@dbg{1}{NATO App6(c) inner node `M\id' ===}
+ \pgfnode{natoapp6c \frameshape}{center}{}{M\id}{\pgfusepath{stroke}}
+ \wg@ignore@sub@nchorfalse%
% Put in the echelon
- \@ifundefined{natoapp@ech}{}{%
- \ifx\natoapp@ech\pgfutil@empty\else%
- \def\args{echelon=\natoapp@ech}
- \expandafter\wg@pic\args\@endwg@pic%
- {natoapp6c/s/}{$(M.north)+(0,1.2*\n@to@pp@e@y)$}{natoapp6c/echelon}
- \fi%
- }
- % Put in stuff below main
- \@ifundefined{natoapp@below}{}{%
- \n@to@pp@belowtrue
- \begin{scope}
- \wg@pic@all{\natoapp@below}{natoapp6c/s/}{%
- $(M.south)+(0,-\n@to@pp@e@yy)$}{%
- natoapp6c/below}%
- \end{scope}%
- \n@to@pp@belowfalse}
- \ifnatoapp@decoy%
- \scope[dash pattern=on 3\pgflinewidth off 2\pgflinewidth]%
+ \n@to@pp@dbg{2}{Echelon}
+ \@ifundefined{natoapp@ech}{}{%
+ \ifx\natoapp@ech\pgfutil@empty\else%
+ \def\args{echelon=\natoapp@ech}
+ \n@to@pp@dbg{3}{Make the echelon}%
+ \wg@nchor{\thisname}{echelon}%
+ \expandafter\wg@pic\args\@endwg@pic%
+ {natoapp6c/s/}{\pgf@x,\pgf@y}{natoapp6c/echelon}
+ \fi%
+ }
+ % Put in stuff below main
+ \n@to@pp@dbg{2}{Below}
+ \@ifundefined{natoapp@below}{}{%
+ \n@to@pp@belowtrue
+ \begin{scope}
+ \n@to@pp@dbg{3}{Make below}%
+ \wg@nchor{\thisname}{below}%
+ \wg@pic@all{\natoapp@below}{natoapp6c/s/}{\pgf@x,\pgf@y}{%
+ natoapp6c/below}%
+ \end{scope}%
+ \n@to@pp@belowfalse}
+ \n@to@pp@dbg{2}{Decoy}
+ \ifnatoapp@decoy%
+ \scope[dash pattern=on 3\pgflinewidth off 2\pgflinewidth]%
\n@to@pp@dbg{1}{Drawing decoy modifier}%
\wg@sub@nchor{M\id}{north east}
\wg@tmpa=\pgf@x%
@@ -1834,10 +1967,11 @@
\pgfpathlineto{\pgfqpoint{0cm}{\wg@tmpc}}%
\pgfpathlineto{\pgfqpoint{-\wg@tmpa}{\wg@tmpb}}%
\pgfusepath{stroke}%
+ \endscope%
+ \fi%
\endscope%
\fi%
- \endscope%
- \fi%
+ \wg@ignore@sub@nchorfalse%
}
}
\newcommand\natoapp[1][]{%
@@ -1850,13 +1984,129 @@
\@ifnextchar({\n@to@pp{#1}{#2}}{\n@to@pp{#1}{#2}()}%)
}
\def\n@to@pp#1#2(#3){%
- %\let\name\pgfutil@empty%
- %\ifx|#3|\else\edef\name{(#3)}\fi%
- %\n@to@pp@dbg{3}{Arguments: #1}%
- %\edef\args{[natoapp6c={#1},transform shape] \name at (#2) {}}
- %\expandafter\node\args;%
\node[draw,transform shape,natoapp6c={#1}] (#3) at (#2) {};%
\@ifnextchar;{\@gobble}{}}
+\tikzset{
+ kriegspiel symbol/.code={
+ \pgfkeys{%
+ /tikz/transform shape,%
+ /tikz/shape=kriegspiel symbol}
+ \n@to@pp@dbg{10}{Args for symbol `#1'}
+ \pgfkeys{/natoapp6c/.cd,%
+ path=kriegspiel/s/,%
+ #1}
+ }
+}
+\pgfdeclareshape{kriegspiel symbol}{
+ \inheritsavedanchors[from=natoapp6c]
+ \savedmacro\frameshape{%
+ \def\frameshape{kriegspiel}}
+ \inheritanchor[from=natoapp6c]{center}
+ \inheritanchor[from=natoapp6c]{north east}
+ \inheritanchor[from=natoapp6c]{north west}
+ \inheritanchor[from=natoapp6c]{south east}
+ \inheritanchor[from=natoapp6c]{south west}
+ \inheritanchor[from=natoapp6c]{north}
+ \inheritanchor[from=natoapp6c]{west}
+ \inheritanchor[from=natoapp6c]{south}
+ \inheritanchor[from=natoapp6c]{east}
+ \inheritanchor[from=natoapp6c]{upper}
+ \inheritanchor[from=natoapp6c]{lower}
+ \inheritanchor[from=natoapp6c]{left}
+ \inheritanchor[from=natoapp6c]{right}
+ \anchor{echelon} {%
+ \wg@sub@nchor{M\id}{north west}%
+ \wg@tmpa=\n@to@pp@e@y cm%
+ \divide\wg@tmpa by 2%
+ \advance\pgf@y\wg@tmpa%
+ }%
+ \inheritbackgroundpath[from=natoapp6c]
+ \inheritbehindforegroundpath[from=natoapp6c]
+ \inheritbehindbackgroundpath[from=natoapp6c]
+ \savedmacro\thisname{\def\thisname{kriegspiel symbol}}
+}
+\pgfdeclareshape{natoapp6c kriegspiel}{
+ \inheritsavedanchors[from=rectangle]
+ \inheritbackgroundpath[from=rectangle]
+ \savedanchor\northeast{\pgf@x=1.4cm\pgf@y=.3125cm}
+ \savedanchor\southwest{\pgf@x=-1.4cm\pgf@y=-.3125cm}
+ \inheritanchor[from=rectangle]{center}
+ \inheritanchor[from=rectangle]{north east}
+ \inheritanchor[from=rectangle]{north west}
+ \inheritanchor[from=rectangle]{south east}
+ \inheritanchor[from=rectangle]{south west}
+ \inheritanchor[from=rectangle]{north}
+ \inheritanchor[from=rectangle]{west}
+ \inheritanchor[from=rectangle]{south}
+ \inheritanchor[from=rectangle]{east}
+ \backgroundpath{}
+}
+\tikzset{
+ ks debug frame/.style={
+ draw=none,
+ %draw=magenta,
+ %dashed,
+ },
+ kriegspiel/s/infantry/.pic={
+ \coordinate(a) at (M.south west);
+ \coordinate(b) at ($(M.north east)+(0,-.2)$);
+ \@ifundefinedcolor{pgffillcolor}{}{
+ \path[fill=pgffillcolor](a)rectangle(b);}
+ \path[pic actions,fill=none](a)rectangle(b);
+ \path[pic actions,fill=none](a)--(b);
+ \path[pic actions,fill=none] let
+ \p1=(a),\p2=(b) in (\x2,\y1)--(\x1,\y2);
+ \path[fill=pgfstrokecolor] let
+ \p2=(b) in (-.05,\y2)rectangle++(.1,.2);
+ \draw[ks debug frame](M.south west)rectangle(M.north east);
+ },
+ kriegspiel/s/reconnaissance/.pic={
+ \coordinate(a) at (M.south west);
+ \coordinate(b) at ($(M.north east)+(0,-.2)$);
+ \@ifundefinedcolor{pgffillcolor}{}{
+ \path[fill=pgffillcolor](a)rectangle(b);}
+ \path[pic actions,fill=none](a)rectangle(b);
+ \path[fill=pgfstrokecolor] (a)--(b)--(a|-b)--cycle;
+ \path[fill=pgfstrokecolor] let
+ \p2=(b) in
+ (-.05,\y2)--++(0,.2)--++(-10:.4)--++(-170:.3)--(.05,\y2)--cycle;
+ \draw[ks debug frame](M.south west)rectangle(M.north east);
+ },
+ kriegspiel/s/artillery/.pic={
+ \coordinate(a) at (M.south west);
+ \coordinate(b) at ($(M.north east)+(0,-.5)$);
+ \@ifundefinedcolor{pgffillcolor}{}{
+ \path[fill=pgffillcolor](a)rectangle(b);}
+ \path[pic actions,fill=none](a)rectangle(b);
+ \foreach \s in {-.8,0,.8}{
+ \path[fill=pgfstrokecolor] let
+ \p2=(b),%
+ \n1={\y2+\pgflinewidth} in
+ (\s-.04,\y2)rectangle++( .08,.5)
+ ($(\s-.18,\n1)+(0,.05)$)rectangle++( .08,.2)
+ ($(\s+.18,\n1)+(0,.05)$)rectangle++(-.08,.2);
+ }
+ \draw[ks debug frame](M.south west)rectangle(M.north east);
+ },
+ kriegspiel/s/reconnaissance artillery/.pic={
+ \coordinate(a) at (M.south west);
+ \coordinate(b) at ($(M.north east)+(0,-.5)$);
+ \@ifundefinedcolor{pgffillcolor}{}{
+ \path[fill=pgffillcolor](a)rectangle(b);}
+ \path[pic actions,fill=none](a)rectangle(b);
+ \path[fill=pgfstrokecolor] (a)--(b)--(a|-b)--cycle;
+ \foreach \s in {-.8,0,.8}{
+ \path[fill=pgfstrokecolor] let
+ \p2=(b),%
+ \n1={\y2+\pgflinewidth} in
+ (\s-.04,\y2)rectangle++( .08,.5)
+ ($(\s-.18,\n1)+(0,.05)$)rectangle++( .08,.2)
+ ($(\s+.18,\n1)+(0,.05)$)rectangle++(-.08,.2);
+ }
+ \draw[ks debug frame](M.south west)rectangle(M.north east);
+ }
+}
+
\providecommand\natoappmark[2][]{%
\tikz[transform shape,
scale=.25,
@@ -3110,6 +3360,11 @@
natoapp6c/s/reconnaissance/.pic={%
\path[draw] (M.north east)--(M.south west);},
}
+\tikzset{
+ natoapp6c/s/reconnaissance artillery/.pic={
+ \path[draw] (M.north east)--(M.south west);,
+ \path[pic actions,fill=pgfstrokecolor] circle(0.2);},
+}
\tikzset{%
natoapp6c/s/recovery unmanned systems/.pic={%
\path[draw] (-.5,.15) to [out=-80,in=180] (0,-.15) to
@@ -3650,6 +3905,79 @@
(0,.15) circle(.07 and .1);
},
}
+\tikzset{
+ pics/kriegspiel/s/.unknown/.code={
+ \message{^^JTry regular `natoapp6c/s/\pgfkeyscurrentname'}
+ % \pic[pic actions,draw=black]{natoapp6c/s/\pgfkeyscurrentname};
+ \pgfkeysalso{/tikz/pics/natoapp6c/s/\pgfkeyscurrentname/.try}
+ },
+ ks debug frame/.style={
+ draw=none,
+ %draw=magenta,
+ %dashed,
+ },
+ kriegspiel/s/infantry/.pic={
+ \coordinate(a) at (M.south west);
+ \coordinate(b) at ($(M.north east)+(0,-.2)$);
+ \@ifundefinedcolor{pgffillcolor}{}{
+ \path[fill=pgffillcolor](a)rectangle(b);}
+ \path[pic actions,fill=none](a)rectangle(b);
+ \path[pic actions,fill=none](a)--(b);
+ \path[pic actions,fill=none] let
+ \p1=(a),\p2=(b) in (\x2,\y1)--(\x1,\y2);
+ \path[fill=pgfstrokecolor] let
+ \p2=(b) in (-.05,\y2)rectangle++(.1,.2);
+ \draw[ks debug frame](M.south west)rectangle(M.north east);
+ },
+ kriegspiel/s/reconnaissance/.pic={
+ \coordinate(a) at (M.south west);
+ \coordinate(b) at ($(M.north east)+(0,-.2)$);
+ \@ifundefinedcolor{pgffillcolor}{}{
+ \path[fill=pgffillcolor](a)rectangle(b);}
+ \path[pic actions,fill=none](a)rectangle(b);
+ \path[fill=pgfstrokecolor] (a)--(b)--(a|-b)--cycle;
+ \path[fill=pgfstrokecolor] let
+ \p2=(b) in
+ (-.05,\y2)--++(0,.2)--++(-10:.4)--++(-170:.3)--(.05,\y2)--cycle;
+ \draw[ks debug frame](M.south west)rectangle(M.north east);
+ },
+ kriegspiel/s/artillery/.pic={
+ \coordinate(a) at (M.south west);
+ \coordinate(b) at ($(M.north east)+(0,-.5)$);
+ \@ifundefinedcolor{pgffillcolor}{}{
+ \path[fill=pgffillcolor](a)rectangle(b);}
+ \path[pic actions,fill=none](a)rectangle(b);
+ %\path[pic actions](a)rectangle(b);
+ \foreach \s in {-.8,0,.8}{
+ \path[fill=pgfstrokecolor] let
+ \p2=(b),%
+ \n1={\y2+\pgflinewidth} in
+ (\s-.04,\y2)rectangle++( .08,.5)
+ ($(\s-.18,\n1)+(0,.05)$)rectangle++( .08,.2)
+ ($(\s+.18,\n1)+(0,.05)$)rectangle++(-.08,.2);
+ }
+ \draw[ks debug frame](M.south west)rectangle(M.north east);
+ },
+ kriegspiel/s/reconnaissance artillery/.pic={
+ \coordinate(a) at (M.south west);
+ \coordinate(b) at ($(M.north east)+(0,-.5)$);
+ \@ifundefinedcolor{pgffillcolor}{}{
+ \path[fill=pgffillcolor](a)rectangle(b);}
+ \path[pic actions,fill=none](a)rectangle(b);
+ %\path[pic actions](a)rectangle(b);
+ \path[fill=pgfstrokecolor] (a)--(b)--(a|-b)--cycle;
+ \foreach \s in {-.8,0,.8}{
+ \path[fill=pgfstrokecolor] let
+ \p2=(b),%
+ \n1={\y2+\pgflinewidth} in
+ (\s-.04,\y2)rectangle++( .08,.5)
+ ($(\s-.18,\n1)+(0,.05)$)rectangle++( .08,.2)
+ ($(\s+.18,\n1)+(0,.05)$)rectangle++(-.08,.2);
+ }
+ \draw[ks debug frame](M.south west)rectangle(M.north east);
+ }
+}
+
\def\n@to@pp@s@ll{
weapon=base,
weapon=top,
diff --git a/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.util.code.tex b/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.util.code.tex
index b9a5b211723..64c3185eed9 100644
--- a/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.util.code.tex
+++ b/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.util.code.tex
@@ -92,9 +92,18 @@
\toks@\expandafter\expandafter\expandafter{\expandafter#1#2}%
\xdef#1{\the\toks@}%
\endgroup}
+\def\wg@nchor#1#2{% shape name, anchor
+ \wg@dbg{10}{Get `#2' in `#1'}%
+ \expandafter\csname pgf@anchor@#1@#2\endcsname%
+ \wg@dbg{10}{Got `\pgf@x',`\pgf@y'}
+}
+\newif\ifwg@ignore@sub@nchor\wg@ignore@sub@nchorfalse%
\def\wg@sub@nchor#1#2{%
- \wg@dbg{3}{^^JGet `#2' in `#1'}%
+ \wg@dbg{10}{^^JGet `#2' in `#1'}%
\@ifundefined{pgf@sh@ns@#1}{%
+ \ifwg@ignore@sub@nchor%
+ \wg@dbg{0}{WARNING: Shape `#1' not defined, anchor `#2' unknown}
+ \fi
\pgf@x=0cm\pgf@y=0cm}{%
\pgf@process{%
\csname pgf@sh@ma@#1\endcsname% MW
diff --git a/Master/texmf-dist/tex/latex/wargame/wargame.beach.pdf b/Master/texmf-dist/tex/latex/wargame/wargame.beach.pdf
index bfb53528757..acaa753c50a 100644
--- a/Master/texmf-dist/tex/latex/wargame/wargame.beach.pdf
+++ b/Master/texmf-dist/tex/latex/wargame/wargame.beach.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/latex/wargame/wargame.city.pdf b/Master/texmf-dist/tex/latex/wargame/wargame.city.pdf
index 5cd11b2618d..3b0ead11ade 100644
--- a/Master/texmf-dist/tex/latex/wargame/wargame.city.pdf
+++ b/Master/texmf-dist/tex/latex/wargame/wargame.city.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/latex/wargame/wargame.fields.pdf b/Master/texmf-dist/tex/latex/wargame/wargame.fields.pdf
new file mode 100644
index 00000000000..72e3646ee29
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/wargame/wargame.fields.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/latex/wargame/wargame.light_woods.pdf b/Master/texmf-dist/tex/latex/wargame/wargame.light_woods.pdf
index 1986d919468..e400e6e3302 100644
--- a/Master/texmf-dist/tex/latex/wargame/wargame.light_woods.pdf
+++ b/Master/texmf-dist/tex/latex/wargame/wargame.light_woods.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/latex/wargame/wargame.mountains.pdf b/Master/texmf-dist/tex/latex/wargame/wargame.mountains.pdf
index 4ccadc4e536..2dc669dbd88 100644
--- a/Master/texmf-dist/tex/latex/wargame/wargame.mountains.pdf
+++ b/Master/texmf-dist/tex/latex/wargame/wargame.mountains.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/latex/wargame/wargame.rough.pdf b/Master/texmf-dist/tex/latex/wargame/wargame.rough.pdf
index 9dc4d625b59..1b374a7a8f6 100644
--- a/Master/texmf-dist/tex/latex/wargame/wargame.rough.pdf
+++ b/Master/texmf-dist/tex/latex/wargame/wargame.rough.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/latex/wargame/wargame.speckle.pdf b/Master/texmf-dist/tex/latex/wargame/wargame.speckle.pdf
new file mode 100644
index 00000000000..33392c9dd89
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/wargame/wargame.speckle.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/latex/wargame/wargame.swamp.pdf b/Master/texmf-dist/tex/latex/wargame/wargame.swamp.pdf
index bcaea332625..5c1f7d6b3c0 100644
--- a/Master/texmf-dist/tex/latex/wargame/wargame.swamp.pdf
+++ b/Master/texmf-dist/tex/latex/wargame/wargame.swamp.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/latex/wargame/wargame.town.pdf b/Master/texmf-dist/tex/latex/wargame/wargame.town.pdf
index 78b59768887..f07074c804a 100644
--- a/Master/texmf-dist/tex/latex/wargame/wargame.town.pdf
+++ b/Master/texmf-dist/tex/latex/wargame/wargame.town.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/latex/wargame/wargame.village.pdf b/Master/texmf-dist/tex/latex/wargame/wargame.village.pdf
index b9beeafce35..15982cd3f8c 100644
--- a/Master/texmf-dist/tex/latex/wargame/wargame.village.pdf
+++ b/Master/texmf-dist/tex/latex/wargame/wargame.village.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/latex/wargame/wargame.woods.pdf b/Master/texmf-dist/tex/latex/wargame/wargame.woods.pdf
index 9823bd52855..4c208af026d 100644
--- a/Master/texmf-dist/tex/latex/wargame/wargame.woods.pdf
+++ b/Master/texmf-dist/tex/latex/wargame/wargame.woods.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/latex/wargame/wgexport.cls b/Master/texmf-dist/tex/latex/wargame/wgexport.cls
index 52f2073aff5..9fcdcb22898 100644
--- a/Master/texmf-dist/tex/latex/wargame/wgexport.cls
+++ b/Master/texmf-dist/tex/latex/wargame/wgexport.cls
@@ -73,7 +73,7 @@
\mk@w{ \space "number": \thepage #1}%
\let\oldmk@i\mk@i%
\ifx#1,\relax\edef\mk@i{\mk@i\space\space}\fi}
-\def\end@info{%
+\def\endinfo{%
\let\mk@i\oldmk@i%
\mk@w{ \space \@rbchar,}}
\def\wg@add@drop@margin{%
@@ -104,30 +104,37 @@
\foreach \u/\m in \t{%
\ifx\u\empty\else% Ignore empty cells
\ifx\u\chit@blank\else%
- \chit@dbg{2}{Next chit `\u' with possible multiplicity `\m'}%
- \ifx\m\@empty\def\m{1}\fi% If no multiplicity defined
- \ifx\u\m\def\m{1}\fi% If the same as unit
- \chit@dbg{2}{Next chit `\u' multiplicity `\m'}%
- %% We only make one copy of the chit, since we can duplicate
- %% it in VASSAL
- \info*{\u}{counter}{\x}
- \nopagecolor%
- \gdef\wg@drop@margin{0pt}%
- \begin{tikzpicture}[chit has drop=false,#2]
- \chit[\u=\ti]%
- \wg@add@drop@margin%
- \end{tikzpicture}
- \end@info%
- %% \foreach \n in {1,...,\m}{% Make a number of copies
- %% \ifx\u\chit@blank%
- %% \chit@dbg{3}{Ignoring blank chit:\u}%
- %% \else%
- %% \info{\u}{counter}{#2}
- %% \begin{tikzpicture}
- %% \chit[\u=\ti](\c,\r)%
- %% \end{tikzpicture}
- %% \fi%
- %% }%
+ \ifx\u\chit@oob@vspacer\else%
+ \ifx\u\chit@oob@spacer\else%
+ \chit@dbg{2}{Next chit `\u' with possible multiplicity
+ `\m'}%
+ \chit@dbg{1}{Next chit `\u' not `\chit@blank',
+ `\chit@oob@vspacer', `\chit@oob@spacer'}
+ \ifx\m\@empty\def\m{1}\fi% If no multiplicity defined
+ \ifx\u\m\def\m{1}\fi% If the same as unit
+ \chit@dbg{2}{Next chit `\u' multiplicity `\m'}%
+ %% We only make one copy of the chit, since we can duplicate
+ %% it in VASSAL
+ \begin{info}*{\u}{counter}{\x}
+ \nopagecolor%
+ \gdef\wg@drop@margin{0pt}%
+ \begin{tikzpicture}[chit has drop=false,#2]
+ \chit[\u=\ti]%
+ \wg@add@drop@margin%
+ \end{tikzpicture}
+ \end{info}%
+ %% \foreach \n in {1,...,\m}{% Make a number of copies
+ %% \ifx\u\chit@blank%
+ %% \chit@dbg{3}{Ignoring blank chit:\u}%
+ %% \else%
+ %% \info{\u}{counter}{#2}
+ %% \begin{tikzpicture}
+ %% \chit[\u=\ti](\c,\r)%
+ %% \end{tikzpicture}
+ %% \fi%
+ %% }%
+ \fi%
+ \fi%
\fi%
\fi%
}%
@@ -155,39 +162,43 @@
\foreach \u/\m in \t{%
\ifx\u\empty\else% Ignore empty cells
\ifx\u\chit@blank\else%
- \chit@dbg{2}{Next chit `\u' with possible multiplicity `\m'}%
- \ifx\m\@empty\def\m{1}\fi% If not multiplicity defined
- \ifx\u\m\def\m{1}\fi% If the same as unit
- \chit@dbg{2}{Next chit `\u' multiplicity `\m'}%
- %% Flipped chit
- \edef\s{\u\space flipped}%
- %% We only make one copy of the chit, since we can duplicate
- %% it in VASSAL
- \info*{\u}{counter}{\x}%
- \nopagecolor%
- \gdef\wg@drop@margin{0pt}%
- \begin{tikzpicture}[chit has drop=false,#2]%
- \chit[\u=\ti]%
- \wg@add@drop@margin%
- \end{tikzpicture}%
- \end@info%
- \info*{\s}{counter}{\x}%
- \nopagecolor%
- \begin{tikzpicture}[chit has drop=false,#2]%
- \chit[\s=\ti]%
- \wg@add@drop@margin%
- \end{tikzpicture}%
- \end@info%
- %% \foreach \n in {1,...,\m}{% Make a number of copies
- %% \ifx\u\chit@blank%
- %% \chit@dbg{3}{Ignoring blank chit:\u}%
- %% \else%
- %% \info{\u}{counter}{#2}
- %% \begin{tikzpicture}
- %% \chit[\u=\ti](\c,\r)%
- %% \end{tikzpicture}
- %% \fi%
- %% }%
+ \ifx\u\chit@oob@vspacer\else%
+ \ifx\u\chit@oob@spacer\else%
+ \chit@dbg{2}{Next chit `\u' with possible multiplicity `\m'}%
+ \ifx\m\@empty\def\m{1}\fi% If not multiplicity defined
+ \ifx\u\m\def\m{1}\fi% If the same as unit
+ \chit@dbg{2}{Next chit `\u' multiplicity `\m'}%
+ %% Flipped chit
+ \edef\s{\u\space flipped}%
+ %% We only make one copy of the chit, since we can duplicate
+ %% it in VASSAL
+ \begin{info}*{\u}{counter}{\x}%
+ \nopagecolor%
+ \gdef\wg@drop@margin{0pt}%
+ \begin{tikzpicture}[chit has drop=false,#2]%
+ \chit[\u=\ti]%
+ \wg@add@drop@margin%
+ \end{tikzpicture}%
+ \end{info}%
+ \begin{info}*{\s}{counter}{\x}%
+ \nopagecolor%
+ \begin{tikzpicture}[chit has drop=false,#2]%
+ \chit[\s=\ti]%
+ \wg@add@drop@margin%
+ \end{tikzpicture}%
+ \end{info}%
+ %% \foreach \n in {1,...,\m}{% Make a number of copies
+ %% \ifx\u\chit@blank%
+ %% \chit@dbg{3}{Ignoring blank chit:\u}%
+ %% \else%
+ %% \info{\u}{counter}{#2}
+ %% \begin{tikzpicture}
+ %% \chit[\u=\ti](\c,\r)%
+ %% \end{tikzpicture}
+ %% \fi%
+ %% }%
+ \fi%
+ \fi%
\fi%
\fi%
}%
@@ -371,10 +382,10 @@
\mk@w{ \mk@i "name": "\bd@n" }%
\let\mk@i\oomk@i%
\mk@w{ \mk@i\@rbchar}%
- \end@info%
+ \endinfo%
}
\def\wg@gennumberm@rkers#1#2#3#4{
- \message{^^JNumbered markers: Type=`#1' Max=`#2' Category=`#3'}
+ \chit@dbg{2}{Numbered markers: Type=`#1' Max=`#2' Category=`#3'}
\def\markers{}
\def\keys{}
\foreach \i in {1,...,#2}{%
@@ -397,7 +408,7 @@
}%
\def\@@battlemarkers[#1][#2]#3{%
\wg@gennumberm@rkers{battle marker}{#3}{#2}{#1}%
- \message{^^JMake a hidden unit and add to Markers category}
+ \chit@dbg{1}{Make a hidden unit and add to Markers category}
{%
\nopagecolor%
\chitimages[Markers]{{wg hidden unit}}%
@@ -417,7 +428,7 @@
\foreach \o/\f/\n [count=\i] in {#2}{%
\ifx\n\f\def\n{\o}\fi%
\ifx\o\f\def\f{white}\fi%
- \message{^^JColour no \i marker `#1 \n' w/fill `\f' text `\o'}%
+ \chit@dbg{3}{Colour no `\i' marker `#1 \n' w/fill `\f' text `\o'}%
\protected@xdef\keys{/tikz/#1 \n/.style={/tikz/#1={\o,\f}},\keys}
\xdef\markers{\markers,#1 \n}
}%
@@ -477,22 +488,22 @@
\info{unit-icon}{icon}{}%
\tikz[auto icon,scale=.7,auto icon more/.try]{%
\chit[fill=#2,
- symbol={[
- scale line widths,
- line width=1pt,
- faction=friend,
- command=land,
- main=infantry,
- scale=1.3](0,-.15)}]}%
- %
- \info{layer-icon}{icon}{}%
- \begin{tikzpicture}[scale=.25]
- \foreach \i in {-1,0,1}{
- \scoped[shift={(0,\i*.15)}]{
- \draw[black,fill=white] (-.5,0)
- --(0,.3)--(.5,0)--(0,-.3)--cycle;
- }
+ symbol={[
+ scale line widths,
+ line width=1pt,
+ faction=friend,
+ command=land,
+ main=infantry,
+ scale=1.3](0,-.15)}]}%
+ %
+ \info{layer-icon}{icon}{}%
+ \begin{tikzpicture}[scale=.25]
+ \foreach \i in {-1,0,1}{
+ \scoped[shift={(0,\i*.15)}]{
+ \draw[black,fill=white] (-.5,0)
+ --(0,.3)--(.5,0)--(0,-.3)--cycle;
}
+ }
\end{tikzpicture}%
%
\info{los-icon}{icon}{}
@@ -521,8 +532,9 @@
%\node[shape=#4,transform shape,draw=none,fill=black,opacity=.5]
%at (.05,-.03){};
\node[shape=#4,#2,transform shape,
- chit drop
- ]{\p};\wg@add@drop@margin{}}}}
+ chit drop,
+ node contents={\p}
+ ]{};\wg@add@drop@margin{}}}}
\tikzset{
zone turn/.store in=\zone@turn,
zone mult/.store in=\zone@mult
diff --git a/Master/texmf-dist/tex/latex/wargame/wgexport.py b/Master/texmf-dist/tex/latex/wargame/wgexport.py
index d573b63d36d..2e5dfd243de 100755
--- a/Master/texmf-dist/tex/latex/wargame/wgexport.py
+++ b/Master/texmf-dist/tex/latex/wargame/wgexport.py
@@ -31,6 +31,7 @@
# command.py
# trait.py
# withtraits.py
+# traits/area.py
# traits/dynamicproperty.py
# traits/globalproperty.py
# traits/prototype.py
@@ -65,6 +66,7 @@
# save.py
# vsav.py
# vmod.py
+# upgrade.py
# exporter.py
#
# ====================================================================
@@ -766,6 +768,7 @@ class PredefinedSetup(GameElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : PredefinedSetup
@@ -779,6 +782,7 @@ class PredefinedSetup(GameElement):
----------
asdict : bool
If `True`, return a dictonary that maps key to `PredefinedSetup` elements. If `False`, return a list of all PredefinedSetup` children.
+
Returns
-------
children : dict or list
@@ -948,6 +952,7 @@ class GlobalOptions(GameElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Option
@@ -1266,6 +1271,7 @@ class Prototypes(GameElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Prototype
@@ -1279,6 +1285,7 @@ class Prototypes(GameElement):
----------
asdict : bool
If `True`, return a dictonary that maps key to `Prototype` elements. If `False`, return a list of all Prototype` children.
+
Returns
-------
children : dict or list
@@ -1491,7 +1498,25 @@ class SymbolicDice(GameElement):
backgroundColor = rgb(0xdd,0xdd,0xdd), # Window background
windowTitleResultFormat = "$name$", # Window title
windowX = '67', # Window size
- windowY = '65'):
+ windowY = '65',
+ doHotkey = False,
+ doLoop = False,
+ doReport = False,
+ doSound = False,
+ hideWhenDisabled = False,
+ hotkeys = '',
+ index = False,
+ indexProperty = '',
+ indexStart = 1,
+ indexStep = 1,
+ loopCount = 1,
+ loopType = 'counted',
+ postLoopKey = '',
+ reportFormat = '',
+ soundClip = '',
+ untilExpression = '',
+ whileExpression = ''
+ ):
super(SymbolicDice,self).\
__init__(game,
self.TAG,
@@ -1511,7 +1536,25 @@ class SymbolicDice(GameElement):
backgroundColor = backgroundColor,
windowTitleResultFormat = windowTitleResultFormat,
windowX = windowX,
- windowY = windowY)
+ windowY = windowY,
+ doHotkey = doHotkey,
+ doLoop = doLoop,
+ doReport = doReport,
+ doSound = doSound,
+ hideWhenDisabled = hideWhenDisabled,
+ hotkeys = hotkeys,
+ index = index,
+ indexProperty = indexProperty,
+ indexStart = indexStart,
+ indexStep = indexStep,
+ loopCount = loopCount,
+ loopType = loopType,
+ postLoopKey = postLoopKey,
+ reportFormat = reportFormat,
+ soundClip = soundClip,
+ untilExpression = untilExpression,
+ whileExpression = whileExpression)
+
def addDie(self,**kwargs):
return self.add(SpecialDie,**kwargs)
@@ -1549,6 +1592,9 @@ class SpecialDie(GameElement):
def getSymbolicDice(self):
return self.getParent(SymbolicDice)
+
+ def getFaces(self):
+ return self.getAllElements(DieFace,single=False)
registerElement(SpecialDie)
@@ -1622,6 +1668,7 @@ class PieceLayers(MapElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : LayerControl
@@ -1977,10 +2024,11 @@ class CounterDetailViewer(MapElement):
emptyHexReportForma = '$LocationName$',
enableHTML = True,
extraTextPadding = 0,
+ bgColor = None,
fgColor = rgb(0,0,0),
- fontSize = 9,
+ fontSize = 11,
graphicsZoom = 1.0,# Zoom on counters
- hotkey = key('\n',0),
+ hotkey = key('\n'),
layerList = '',
minDisplayPieces = 2,
propertyFilter = '',
@@ -1993,15 +2041,19 @@ class CounterDetailViewer(MapElement):
showOverlap = False,
showgraph = True,
showgraphsingle = False,
- showtext = False,
+ showtext = True,
showtextsingle = False,
stretchWidthSummary = False,
summaryReportFormat = '$LocationName$',
unrotatePieces = False,
version = 3,
- verticalOffset = 0,
- verticalTopText = 5,
- zoomlevel = 1.0): # showTerrain attributes
+ verticalOffset = 2,
+ verticalTopText = 0,
+ zoomlevel = 1.0,
+ stopAfterShowing = False): # showTerrain attributes
+
+ bg = '' if bgColor is None else bgColor
+ fg = '' if fgColor is None else fgColor
super(CounterDetailViewer,self)\
.__init__(map,self.TAG,node=node,
borderWidth = borderWidth,
@@ -2015,7 +2067,8 @@ class CounterDetailViewer(MapElement):
emptyHexReportForma = emptyHexReportForma,
enableHTML = enableHTML,
extraTextPadding = extraTextPadding,
- fgColor = fgColor,
+ bgColor = bg,
+ fgColor = fg,
fontSize = fontSize,
graphicsZoom = graphicsZoom,
hotkey = hotkey,
@@ -2039,7 +2092,8 @@ class CounterDetailViewer(MapElement):
version = version,
verticalOffset = verticalOffset,
verticalTopText = verticalTopText,
- zoomlevel = zoomlevel)
+ zoomlevel = zoomlevel,
+ stopAfterShowing = stopAfterShowing)
registerElement(CounterDetailViewer)
@@ -2198,7 +2252,26 @@ class AtStart(MapElement):
owningBoard = '',
x = 0,
y = 0):
- '''Pieces are existing PieceSlot elements'''
+ '''Pieces are existing PieceSlot elements
+
+
+ Parameters
+ ----------
+ node : xml.minidom.Node
+ Existing node or None
+ name : str
+ Name of node
+ location : str
+ Where the at-start element is put if `useGridLocation`
+ useGridLocation : bool
+ If true, use maps grid
+ owningBoard : str
+ Board that owns the at-start (can be empty)
+ x : float
+ Coordinate (ignored if `useGridLocation`)
+ y : float
+ Coordinate (ignored if `useGridLocation`)
+ '''
super(AtStart,self).\
__init__(map,self.TAG,node=node,
name = name,
@@ -2215,6 +2288,7 @@ class AtStart(MapElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Pieces
@@ -2235,6 +2309,7 @@ class AtStart(MapElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Piece
@@ -2264,7 +2339,7 @@ class AtStart(MapElement):
Dictionary or list of `Piece` children
'''
- return self.getElementsWithKey(PieceSlot,'entryName',asdict)
+ return self.getElementsByKey(PieceSlot,'entryName',asdict)
registerElement(AtStart)
@@ -2292,6 +2367,7 @@ class GlobalProperties(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Property
@@ -2347,6 +2423,7 @@ class TurnLevel(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Level
@@ -2374,6 +2451,7 @@ class TurnLevel(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Counter
@@ -2387,6 +2465,7 @@ class TurnLevel(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : List
@@ -2495,6 +2574,7 @@ class TurnTrack(TurnLevel):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Hotkey
@@ -2626,6 +2706,7 @@ class Documentation(GameElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : AboutScreen
@@ -2639,6 +2720,7 @@ class Documentation(GameElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : HelpFile
@@ -2652,6 +2734,7 @@ class Documentation(GameElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : BrowserHelpFile
@@ -2665,6 +2748,7 @@ class Documentation(GameElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : BrowserPDFFile
@@ -2678,6 +2762,7 @@ class Documentation(GameElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Tutorial
@@ -2909,6 +2994,7 @@ class PlayerRoster(GameElement):
buttonText='Retire',
buttonToolTip='Switch sides, become observer, or release faction'):
'''Add a player roster to the module
+
Parameters
----------
doc : Element
@@ -2931,6 +3017,7 @@ class PlayerRoster(GameElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Side
@@ -3150,6 +3237,7 @@ class ChessClockControl(GameElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : AboutScreen
@@ -3180,6 +3268,7 @@ class WidgetElement:
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Tabs
@@ -3192,6 +3281,7 @@ class WidgetElement:
Parameters
----------
Dictionary of attribute key-value pairs
+
Returns
-------
element : Combo
@@ -3205,6 +3295,7 @@ class WidgetElement:
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Panel
@@ -3218,6 +3309,7 @@ class WidgetElement:
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : List
@@ -3231,6 +3323,7 @@ class WidgetElement:
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : MapWidget
@@ -3244,6 +3337,7 @@ class WidgetElement:
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Chart
@@ -3257,6 +3351,7 @@ class WidgetElement:
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : PieceSlot
@@ -3270,6 +3365,7 @@ class WidgetElement:
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Piece
@@ -3288,6 +3384,7 @@ class WidgetElement:
----------
asdict : bool
If `True`, return a dictonary that maps key to `Tab` elements. If `False`, return a list of all Tab` children.
+
Returns
-------
children : dict or list
@@ -3301,6 +3398,7 @@ class WidgetElement:
----------
asdict : bool
If `True`, return a dictonary that maps key to `Tab` elements. If `False`, return a list of all Tab` children.
+
Returns
-------
children : dict or list
@@ -3314,6 +3412,7 @@ class WidgetElement:
----------
asdict : bool
If `True`, return a dictonary that maps key to `List` elements. If `False`, return a list of all List` children.
+
Returns
-------
children : dict or list
@@ -3327,6 +3426,7 @@ class WidgetElement:
----------
asdict : bool
If `True`, return a dictonary that maps key to `Panel` elements. If `False`, return a list of all Panel` children.
+
Returns
-------
children : dict or list
@@ -3340,6 +3440,7 @@ class WidgetElement:
----------
asdict : bool
If `True`, return a dictonary that maps key to `MapWidget` elements. If `False`, return a list of all MapWidget` children.
+
Returns
-------
children : dict or list
@@ -3353,6 +3454,7 @@ class WidgetElement:
----------
asdict : bool
If `True`, return a dictonary that maps key to `Chart` elements. If `False`, return a list of all Chart` children.
+
Returns
-------
children : dict or list
@@ -3366,6 +3468,7 @@ class WidgetElement:
----------
asdict : bool
If `True`, return a dictonary that maps key to `PieceSlot` elements. If `False`, return a list of all PieceSlot` children.
+
Returns
-------
children : dict or list
@@ -3470,6 +3573,7 @@ class MapWidget(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : WidgetMap
@@ -3483,6 +3587,7 @@ class MapWidget(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `WidgetMap` elements. If `False`, return a list of all WidgetMap` children.
+
Returns
-------
children : dict or list
@@ -3679,6 +3784,7 @@ class HexGrid(BaseGrid):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Numbering
@@ -3720,8 +3826,8 @@ class SquareGrid(BaseGrid):
dx = dx,
dy = dy,
edgesLegal = edgesLegal,
- x0 = 0,
- y0 = int(0.4*RECT_HEIGHT),
+ x0 = x0,
+ y0 = y0,
**kwargs)
def addNumbering(self,**kwargs):
'''Add a `Numbering` element to this
@@ -3730,6 +3836,7 @@ class SquareGrid(BaseGrid):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Numbering
@@ -3892,6 +3999,7 @@ class RegionGrid(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Region
@@ -4017,6 +4125,7 @@ class ZonedGrid(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Highlighter
@@ -4031,6 +4140,7 @@ class ZonedGrid(Element):
single : bool
If `True`, there can be only one `Highligter` child, otherwise fail.
If `False` return all `Highligter` children in this element
+
Returns
-------
children : list
@@ -4044,6 +4154,7 @@ class ZonedGrid(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Zone
@@ -4057,6 +4168,7 @@ class ZonedGrid(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `Zone` elements. If `False`, return a list of all Zone` children.
+
Returns
-------
children : dict or list
@@ -4080,6 +4192,7 @@ class ZonedGridHighlighter(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : ZoneHighlight
@@ -4093,6 +4206,7 @@ class ZonedGridHighlighter(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `Zone` elements. If `False`, return a list of all Zone` children.
+
Returns
-------
children : dict or list
@@ -4210,6 +4324,7 @@ class Zone(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : HexGrid
@@ -4223,6 +4338,7 @@ class Zone(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : SquareGrid
@@ -4236,6 +4352,7 @@ class Zone(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : RegionGrid
@@ -4249,6 +4366,7 @@ class Zone(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Property
@@ -4263,6 +4381,7 @@ class Zone(Element):
single : bool
If `True`, there can be only one `HexGrid` child, otherwise fail.
If `False` return all `HexGrid` children in this element
+
Returns
-------
children : list
@@ -4277,6 +4396,7 @@ class Zone(Element):
single : bool
If `True`, there can be only one `SquareGrid` child, otherwise fail.
If `False` return all `SquareGrid` children in this element
+
Returns
-------
children : list
@@ -4291,6 +4411,7 @@ class Zone(Element):
single : bool
If `True`, there can be only one `RegionGrid` child, otherwise fail.
If `False` return all `RegionGrid` children in this element
+
Returns
-------
children : list
@@ -4305,6 +4426,7 @@ class Zone(Element):
single : bool
If `True`, there can be only one `Grid` child, otherwise fail.
If `False` return all `Grid` children in this element
+
Returns
-------
children : list
@@ -4323,8 +4445,6 @@ class Zone(Element):
def getProperties(self):
'''Get all `Property` element from this
- Parameters
- ----------
Returns
-------
children : dict
@@ -4339,6 +4459,7 @@ class Zone(Element):
c = pp.split(',')
r.append([int(c[0]),int(c[1])])
return r
+
def getBB(self):
from functools import reduce
path = self.getPath()
@@ -4393,6 +4514,7 @@ class BoardPicker(MapElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Setup
@@ -4411,6 +4533,7 @@ class BoardPicker(MapElement):
single : bool
If `True`, there can be only one `Setup` child, otherwise fail.
If `False` return all `Setup` children in this element
+
Returns
-------
children : list
@@ -4424,6 +4547,7 @@ class BoardPicker(MapElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Board
@@ -4437,6 +4561,7 @@ class BoardPicker(MapElement):
----------
asdict : bool
If `True`, return a dictonary that maps key to `Board` elements. If `False`, return a list of all Board` children.
+
Returns
-------
children : dict or list
@@ -4512,6 +4637,7 @@ class Board(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : ZonedGrid
@@ -4526,6 +4652,7 @@ class Board(Element):
single : bool
If `True`, there can be only one `ZonedGrid` child, otherwise fail.
If `False` return all `ZonedGrid` children in this element
+
Returns
-------
children : list
@@ -4539,6 +4666,7 @@ class Board(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `Zone` elements. If `False`, return a list of all Zone` children.
+
Returns
-------
children : dict or list
@@ -4596,6 +4724,65 @@ class BaseMap(Element):
moveWithinFormat = '$pieceName$ moves $previousLocation$ &rarr; $location$ *',
showKey = '',
thickness = '3'):
+ '''Create a map
+
+ Parameters
+ ----------
+ doc : xml.minidom.Document
+ Parent document
+ tag : str
+ XML tag
+ node : xml.minidom.Node or None
+ Existing node or None
+ mapName : str
+ Name of map
+ allowMultiple : bool
+ Allow multiple boards
+ backgroundcolor : color
+ Bckground color
+ buttonName : str
+ Name on button to show map = '',
+ changeFormat :
+ Message format to show on changes
+ color : color
+ Color of selected pieces
+ createFormat : str
+ Message format when creating a piece
+ edgeHeight : int
+ Height of edge (margin)
+ edgeWidth : int
+ Width of edge (margin)
+ hideKey : Key
+ Hot-key or key-command to hide map
+ hotkey : Key
+ Hot-key or key-command to show map
+ icon : path
+ Icon image
+ launch : bool
+ Show on launch
+ markMoved : str
+ Show moved
+ markUnmovedHotkey : key
+ Remove moved markers
+ markUnmovedIcon : path
+ Icon for unmoved
+ markUnmovedReport : str
+ Message when marking as unmoved
+ markUnmovedText : str
+ Text on button
+ markUnmovedTooltip : str
+ Tooltip on button
+ moveKey : key
+ Key to set moved marker
+ moveToFormat : str
+ Message format when moving
+ moveWithinFormat : str
+ Message when moving within map
+ showKey : str,
+ Key to show map
+ thickness : int
+ Thickness of line around selected pieces
+ '''
super(BaseMap,self).__init__(doc,tag,node=node,
allowMultiple = allowMultiple,
backgroundcolor = backgroundcolor,
@@ -4632,6 +4819,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Picker
@@ -4646,6 +4834,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `BoardPicker` child, otherwise fail.
If `False` return all `BoardPicker` children in this element
+
Returns
-------
children : list
@@ -4660,6 +4849,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `BoardPicker` child, otherwise fail.
If `False` return all `BoardPicker` children in this element
+
Returns
-------
children : list
@@ -4674,6 +4864,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `StackMetric` child, otherwise fail.
If `False` return all `StackMetric` children in this element
+
Returns
-------
children : list
@@ -4688,6 +4879,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `ImageSaver` child, otherwise fail.
If `False` return all `ImageSaver` children in this element
+
Returns
-------
children : list
@@ -4702,6 +4894,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `TextSaver` child, otherwise fail.
If `False` return all `TextSaver` children in this element
+
Returns
-------
children : list
@@ -4716,6 +4909,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `ForwardToChatter` child, otherwise fail.
If `False` return all `ForwardToChatter` children in this element
+
Returns
-------
children : list
@@ -4730,6 +4924,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `MenuDi` child, otherwise fail.
If `False` return all `MenuDi` children in this element
+
Returns
-------
children : list
@@ -4744,6 +4939,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `MapCenterer` child, otherwise fail.
If `False` return all `MapCenterer` children in this element
+
Returns
-------
children : list
@@ -4758,6 +4954,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `StackExpander` child, otherwise fail.
If `False` return all `StackExpander` children in this element
+
Returns
-------
children : list
@@ -4772,6 +4969,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `PieceMover` child, otherwise fail.
If `False` return all `PieceMover` children in this element
+
Returns
-------
children : list
@@ -4786,6 +4984,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `SelectionHighlighter` child, otherwise fail.
If `False` return all `SelectionHighlighter` children in this element
+
Returns
-------
children : list
@@ -4802,6 +5001,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `HighlightLa` child, otherwise fail.
If `False` return all `HighlightLa` children in this element
+
Returns
-------
children : list
@@ -4816,6 +5016,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `CounterDetailViewer` child, otherwise fail.
If `False` return all `CounterDetailViewer` children in this element
+
Returns
-------
children : list
@@ -4830,6 +5031,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `GlobalMap` child, otherwise fail.
If `False` return all `GlobalMap` children in this element
+
Returns
-------
children : list
@@ -4844,6 +5046,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `Zoomer` child, otherwise fail.
If `False` return all `Zoomer` children in this element
+
Returns
-------
children : list
@@ -4858,6 +5061,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `HidePiece` child, otherwise fail.
If `False` return all `HidePiece` children in this element
+
Returns
-------
children : list
@@ -4871,6 +5075,7 @@ class BaseMap(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `MassKey` elements. If `False`, return a list of all MassKey` children.
+
Returns
-------
children : dict or list
@@ -4885,6 +5090,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `Flare` child, otherwise fail.
If `False` return all `Flare` children in this element
+
Returns
-------
children : list
@@ -4899,6 +5105,7 @@ class BaseMap(Element):
single : bool
If `True`, there can be only one `AtStart` child, otherwise fail.
If `False` return all `AtStart` children in this element
+
Returns
-------
children : list
@@ -4912,6 +5119,7 @@ class BaseMap(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `Board` elements. If `False`, return a list of all Board` children.
+
Returns
-------
children : dict or list
@@ -4947,6 +5155,7 @@ class BaseMap(Element):
elements. If `False`, return a list of all Board`
children.
+
Returns
-------
children : dict or list
@@ -4964,6 +5173,7 @@ class BaseMap(Element):
elements. If `False`, return a list of all Board`
children.
+
Returns
-------
children : dict or list
@@ -4978,6 +5188,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : BoardPicker
@@ -4991,6 +5202,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : StackMetrics
@@ -5004,6 +5216,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : ImageSaver
@@ -5017,6 +5230,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : TextSaver
@@ -5030,6 +5244,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : ForwardToChatter
@@ -5043,6 +5258,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : MenuDisplayer
@@ -5056,6 +5272,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : MapCenterer
@@ -5069,6 +5286,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : StackExpander
@@ -5082,6 +5300,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : PieceMover
@@ -5095,6 +5314,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : SelectionHighlighters
@@ -5108,6 +5328,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : KeyBufferer
@@ -5121,6 +5342,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : HighlightLastMoved
@@ -5134,6 +5356,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : CounterDetailViewer
@@ -5147,6 +5370,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : GlobalMap
@@ -5160,6 +5384,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Zoomer
@@ -5173,6 +5398,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : HidePiecesButton
@@ -5186,6 +5412,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : MassKey
@@ -5199,6 +5426,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : StartupMassKey
@@ -5212,6 +5440,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Flare
@@ -5225,6 +5454,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : AtStart
@@ -5240,6 +5470,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : PieceLayers
@@ -5253,6 +5484,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Menu
@@ -5266,6 +5498,7 @@ class BaseMap(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Menu
@@ -5377,6 +5610,7 @@ class ChartWindow(GameElement,WidgetElement):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Chart
@@ -5388,12 +5622,16 @@ class ChartWindow(GameElement,WidgetElement):
Parameters
----------
- asdict : bool
- If `True`, return a dictonary that maps key to `Chart` elements. If `False`, return a list of all Chart` children.
+ asdict : bool
+ If `True`, return a dictonary that maps key to `Chart`
+ elements. If `False`, return a list of all Chart`
+ children.
+
Returns
-------
children : dict or list
Dictionary or list of `Chart` children
+
'''
return self.getElementsById(Chart,'chartName',asdict=asdict)
@@ -5440,11 +5678,12 @@ class AddCommand(Command):
class Trait:
known_traits = []
def __init__(self):
- '''Base class for trait capture. Unlike the Element classes,
- this actually holds state that isn't reflected elsewhere in
- the DOM. This means that the data here is local to the
- object. So when we do
-
+ '''Base class for trait capture.
+
+ Unlike the Element classes, this actually holds state that
+ isn't reflected elsewhere in the DOM. This means that the
+ data here is local to the object. So when we do
+
piece = foo.getPieceSlots()[0]
traits = p.getTraits()
for trait in traits:
@@ -5467,6 +5706,9 @@ class Trait:
traits.append(MarkTrait('Hello','World;)
piece.setTraits(traits)
+ .. include:: ../../vassal/traits/README.md
+ :parser: myst_parser.sphinx_
+
'''
self._type = None
self._state = None
@@ -5479,6 +5721,7 @@ class Trait:
'''
self._type = list(kwargs.values())
self._tnames = list(kwargs.keys())
+
def setState(self,**kwargs):
'''Set states. Dictionary of names and values. Dictonary keys
defines how we access the fields, which is internal here.
@@ -5487,7 +5730,6 @@ class Trait:
self._state = list(kwargs.values())
self._snames = list(kwargs.keys())
-
def __getitem__(self,key):
'''Look up item in either type or state'''
try:
@@ -5574,39 +5816,78 @@ class Trait:
return [k.replace('\\'+f'{sep}',f'{sep}') for k in ks]
@classmethod
- def flatten(cls,traits,game=None,prototypes=None):
+ def flatten(cls,traits,game=None,prototypes=None,verbose=False):
if prototypes is None:
if game is None:
print(f'Warning: Game or prototypes not passed')
return None
prototypes = game.getPrototypes()[0].getPrototypes()
- ret = []
- return cls._flatten(traits,ret,prototypes,False)
+ if len(traits) < 1: return None
+
+ basic = None
+ if traits[-1].ID == BasicTrait.ID:
+ basic = traits.pop()
+
+ if verbose:
+ print(f'Piece {basic["name"]}')
+
+ ret = cls._flatten(traits,prototypes,' ',verbose)
+ ret.append(basic)
+
+ return ret
@classmethod
- def _flatten(cls,traits,ret,prototypes,nobasic=True):
+ def _flatten(cls,traits,prototypes,ind,verbose):
'''Expand all prototype traits in traits'''
+ ret = []
for trait in traits:
# Ignore recursive basic traits
- if nobasic and trait.ID == BasicTrait.ID:
+ if trait.ID == BasicTrait.ID:
continue
# Add normal traits
if trait.ID != PrototypeTrait.ID:
+ if verbose:
+ print(f'{ind}Adding trait "{trait.ID}"')
+
ret.append(trait)
continue
# Find prototype
- proto = prototypes.get(trait['name'],None)
+ name = trait['name']
+ proto = prototypes.get(name,None)
if proto is None:
- print(f'Warning, prototype {trait["name"]} not found')
+ if name != ' prototype':
+ print(f'{ind}Warning, prototype {name} not found')
continue
+ if verbose:
+ print(f'{ind}Expanding prototype "{name}"')
+
# Recursive call to add prototype traits (and possibly
# more recursive calls
- cls._flatten(proto.getTraits(), ret, prototypes,not nobasic)
+ ret.extend(cls._flatten(proto.getTraits(), prototypes,
+ ind+' ',verbose))
return ret
+
+ def print(self,file=None):
+ if file is None:
+ from sys import stdout
+ file = stdout
+
+ nt = max([len(i) for i in self._tnames])
+ ns = max([len(i) for i in self._snames])
+ nw = max(nt,ns)
+
+ print(f'Trait ID={self.ID}',file=file)
+ print(f' Type:', file=file)
+ for n,v in zip(self._tnames,self._type):
+ print(f' {n:<{nw}s}: {v}',file=file)
+ print(f' State:', file=file)
+ for n,v in zip(self._snames,self._state):
+ print(f' {n:<{nw}s}: {v}',file=file)
+
#
# EOF
#
@@ -5660,6 +5941,7 @@ class WithTraits(Element):
traits.append(trait)
self.setTraits(*traits)
+
def getTraits(self):
'''Get all element traits as objects. This decodes the trait
definitions. This is useful if we have read the element from
@@ -5680,9 +5962,109 @@ class WithTraits(Element):
The decoded traits
'''
+ code = self._node.childNodes[0].nodeValue
+ return self.decodeAdd(code)
+
+ def encodedStates(self):
+ from re import split
+
+ code = self._node.childNodes[0].nodeValue
+ cmd, iden, typ, sta = split(fr'(?<!\\)/',code) #code.split('/')
+
+ return sta
+
+ def decodeStates(self,code,verbose=False):
+ from re import split
+
+ newstates, oldstates = split(fr'(?<!\\)/',code)#code.split('/')
+
+ splitit = lambda l : \
+ [s.strip('\\').split(';') for s in l.split(r' ')]
+
+ newstates = splitit(newstates)
+ oldstates = splitit(oldstates)
+
+ traits = self.getTraits()
+
+ if len(traits) != len(newstates):
+ print(f'Piece has {len(traits)} traits but got '
+ f'{len(newstates)} states')
+
+ for trait, state in zip(traits,newstates):
+ trait._state = state;
+ # print(trait.ID)
+ # for n,s in zip(trait._snames,trait._state):
+ # print(f' {n:30s}: {s}')
+
+ self.setTraits(*traits)
+
+ def copyStates(self,other,verbose=False):
+ straits = other.getTraits()
+ dtraits = self.getTraits()
+
+ matches = 0
+ for strait in straits:
+ if len(strait._state) < 1:
+ continue
+
+ cand = []
+ ttrait = None
+ for dtrait in dtraits:
+ if dtrait.ID == strait.ID:
+ cand.append(dtrait)
+
+ if verbose and len(cand) < 1:
+ print(f'Could not find candidate for {strait.ID}')
+ continue
+
+ if len(cand) == 1:
+ ttrait = cand[0]
+
+ else:
+ # print(f'Got {len(cand)} candidiate targets {strait.ID}')
+
+ best = None
+ count = 0
+ types = strait._type
+ for c in cand:
+ cnt = sum([ct == t for ct,t in zip(c._type, types)])
+ if cnt > count:
+ best = c
+ count = cnt
+
+ if verbose and best is None:
+ print(f'No candidate for {strait.ID} {len(again)}')
+
+ if verbose and count+2 < len(types):
+ print(f'Ambigious candidate for {strait.ID} '
+ f'({count} match out of {len(types)})')
+ #print(best._type)
+ #print(types)
+
+ ttrait = best
+
+ if ttrait is None:
+ continue
+
+ ttrait._state = strait._state
+ matches += 1
+ # print(ttrait.ID)
+ # for n,s in zip(ttrait._snames,ttrait._state):
+ # print(f' {n:30s}: {s}')
+
+ if verbose:
+ print(f'Got {matches} matches out of {len(dtraits)}')
+
+ self.setTraits(*dtraits)
+
+
+ def decodeAdd(self,code,verbose=False):
+ '''Try to decode make a piece from a piece of state code'''
from re import split
- code = self._node.childNodes[0].nodeValue
+
cmd, iden, typ, sta = split(fr'(?<!\\)/',code) #code.split('/')
+ # print(cmd,iden,typ,sta)
+
types = typ.split(r' ')
states = sta.split(r' ')
types = [t.strip('\\').split(';') for t in types]
@@ -5705,19 +6087,11 @@ class WithTraits(Element):
print(f'Warning: Unknown trait {tid}')
return traits
-
- def setTraits(self,*traits,iden='null'):
- '''Set traits on this element. This encodes the traits into
- this object.
-
- Parameters
- ----------
- traits : tuple of Trait objects
- The traits to set on this object.
- iden : str
- Identifier
- '''
+ def encodeAdd(self,*traits,iden='null',verbose=False):
+ '''Encodes type and states'''
+ if len(traits) < 1: return ''
+
last = traits[-1]
# A little hackish to use the name of the class, but needed
# because of imports into patch scripts.
@@ -5740,9 +6114,30 @@ class WithTraits(Element):
tpe = WithTraits.encodeParts(*types)
state = WithTraits.encodeParts(*states)
add = AddCommand(str(iden),tpe,state)
+ return add.cmd
+
+
+ def setTraits(self,*traits,iden='null'):
+ '''Set traits on this element. This encodes the traits into
+ this object.
+
+ Parameters
+ ----------
+ traits : tuple of Trait objects
+ The traits to set on this object.
+ iden : str
+ Identifier
+
+ '''
+ add = self.encodeAdd(*traits,iden=iden)
+ if self._node is None:
+ from xml.dom.minidom import Element, Text
+ self._node = Element(self.TAG)
+ self._node.appendChild(Text())
+
if len(self._node.childNodes) < 1:
self.addText('')
- self._node.childNodes[0].nodeValue = add.cmd
+ self._node.childNodes[0].nodeValue = add
def removeTrait(self,ID,key=None,value=None,verbose=False):
'''Remove a trait from this object.
@@ -5896,6 +6291,7 @@ class PieceSlot(WithTraits):
width = width,
icon = icon)
+
def clone(self,parent):
'''Adds copy of self to parent, possibly with new GPID'''
game = self.getParentOfClass([Game])
@@ -5951,6 +6347,53 @@ registerElement(Prototype)
# EOF
#
# ====================================================================
+# From traits/area.py
+
+class AreaTrait(Trait):
+ ID = 'AreaOfEffect'
+ def __init__(self,
+ transparancyColor = rgb(0x77,0x77,0x77),
+ transparancyLevel = 30,
+ radius = 1,
+ alwaysActive = False,
+ activateCommand = 'Toggle area of effect',
+ activateKey = key('A'), # Ctrl-A
+ mapShaderName = '',
+ fixedRadius = True,
+ radiusMarker = '', # Property
+ description = 'Show area of effect',
+ name = 'EffectArea',
+ onMenuText = '', # Show area of effect
+ onKey = '', # key('A')
+ offMenuText = '', # Hide area of effect
+ offKey = '', # key(A,SHIFT)
+ globallyVisible = True):
+ super(AreaTrait,self).__init__()
+ self.setType(
+ transparancyColor = transparancyColor,
+ transparancyLevel = int(transparancyLevel),
+ radius = radius,
+ alwaysActive = alwaysActive,
+ activateCommand = activateCommand,
+ activateKey = activateKey,
+ mapShaderName = mapShaderName,
+ fixedRadius = fixedRadius,
+ radiusMarker = radiusMarker,
+ description = description,
+ name = name,
+ onMenuText = onMenuText,
+ onKey = onKey,
+ offMenuText = offMenuText,
+ offKey = offKey,
+ globallyVisible = globallyVisible
+ )
+ self.setState(active = alwaysActive or not globallyVisible)
+
+Trait.known_traits.append(AreaTrait)
+#
+# EOF
+#
+# ====================================================================
# From traits/dynamicproperty.py
# --------------------------------------------------------------------
@@ -5990,9 +6433,9 @@ class ChangePropertyTrait(Trait):
# print(cmd)
com = cmd[0] + ':' + cmd[1].replace(',',r'\,') + ':' + cmd[2]
if cmd[2] == self.DIRECT:
- com += f'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:')
+ com += r'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:')
elif cmd[2] == self.INCREMENT:
- com += f'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:')
+ com += r'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:')
cmds.append(com)
# print(cmds)
return ','.join(cmds)
@@ -6758,7 +7201,7 @@ class MaskTrait(Trait):
autoPeek = True,
dealKey = '',
dealExpr = ''):
- '''Create a mark trait (static property)'''
+ '''Create a masking trait'''
super(MaskTrait,self).__init__()
disp = displayStyle
if displayStyle == self.PEEK:
@@ -6822,25 +7265,32 @@ class TrailTrait(Trait):
inactiveOpacity = 50,
edgesBuffer = 20,
displayBuffer = 30,
- lineWidth = 1,
+ lineWidth = 5,
turnOn = '',
turnOff = '',
reset = '',
- description = ''):
+ description = 'Enable or disable movement trail'):
''' Create a movement trail trait ( VASSAL.counters.Footprint)'''
super(TrailTrait,self).__init__()
+ lw = (lineWidth
+ if isinstance(lineWidth,str) and lineWidth.startswith('{') else
+ int(lineWidth))
+ ra = (radius
+ if isinstance(radius,str) and radius.startswith('{') else
+ int(radius))
+
self.setType(key = key,# ENABLE KEY
name = name,# MENU
localVisible = localVisible,# LOCAL VISABLE
globalVisible = globalVisible,# GLOBAL VISABLE
- radius = radius,# RADIUS
+ radius = ra,# RADIUS
fillColor = fillColor,# FILL COLOR
lineColor = lineColor,# LINE COLOR
activeOpacity = activeOpacity,# ACTIVE OPACITY
inactiveOpacity = inactiveOpacity,# INACTIVE OPACITY
edgesBuffer = edgesBuffer,# EDGES BUFFER
displayBuffer = displayBuffer,# DISPLAY BUFFER
- lineWidth = int(lineWidth),# LINE WIDTH
+ lineWidth = lw,# LINE WIDTH
turnOn = turnOn,# TURN ON KEY
turnOff = turnOff,# TURN OFF KEY
reset = reset,# RESET KEY
@@ -7127,13 +7577,19 @@ class NonRectangleTrait(Trait):
self.setState()
@classmethod
- def getShape(cls,image):
- if image is None:
+ def getShape(cls,buffer):
+ if buffer is None:
return []
- from PIL import Image
from io import BytesIO
+ image = buffer
+ if image[:5] == b'<?xml':
+ from cairosvg import svg2png
+ image = svg2png(image)
+
+ from PIL import Image
+
code = []
with Image.open(BytesIO(image)) as img:
alp = img.getchannel('A') # Alpha channel
@@ -7277,6 +7733,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : BasicCommandEncoder
@@ -7290,6 +7747,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : GlobalTranslatableMessages
@@ -7303,6 +7761,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : PlayerRoster
@@ -7316,6 +7775,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : PlayerRoster
@@ -7329,6 +7789,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Language
@@ -7342,6 +7803,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Chatter
@@ -7355,6 +7817,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : KeyNamer
@@ -7368,6 +7831,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Notes
@@ -7381,6 +7845,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Language
@@ -7394,6 +7859,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Chatter
@@ -7407,6 +7873,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : KeyNamer
@@ -7420,6 +7887,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : GlobalProperties
@@ -7433,6 +7901,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : GlobalOptions
@@ -7446,6 +7915,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : TurnTrack
@@ -7459,6 +7929,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Documentation
@@ -7472,6 +7943,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Prototypes
@@ -7485,6 +7957,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : PieceWindow
@@ -7498,6 +7971,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : ChartWindow
@@ -7511,6 +7985,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Inventory
@@ -7524,6 +7999,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Map
@@ -7537,6 +8013,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : DiceButton
@@ -7550,6 +8027,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : PredefinedSetup
@@ -7563,6 +8041,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : GameMassKey
@@ -7576,6 +8055,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : StartupMassKey
@@ -7589,6 +8069,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Menu
@@ -7602,6 +8083,7 @@ class Game(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : SymbolicDice
@@ -7619,6 +8101,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `GlobalPropertie` child, otherwise fail.
If `False` return all `GlobalPropertie` children in this element
+
Returns
-------
children : list
@@ -7633,6 +8116,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `Ba` child, otherwise fail.
If `False` return all `Ba` children in this element
+
Returns
-------
children : list
@@ -7647,6 +8131,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `GlobalTranslatableMessage` child, otherwise fail.
If `False` return all `GlobalTranslatableMessage` children in this element
+
Returns
-------
children : list
@@ -7661,6 +8146,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `Language` child, otherwise fail.
If `False` return all `Language` children in this element
+
Returns
-------
children : list
@@ -7675,6 +8161,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `Language` child, otherwise fail.
If `False` return all `Language` children in this element
+
Returns
-------
children : list
@@ -7689,6 +8176,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `Chatter` child, otherwise fail.
If `False` return all `Chatter` children in this element
+
Returns
-------
children : list
@@ -7703,6 +8191,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `KeyNamer` child, otherwise fail.
If `False` return all `KeyNamer` children in this element
+
Returns
-------
children : list
@@ -7717,6 +8206,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `Documentation` child, otherwise fail.
If `False` return all `Documentation` children in this element
+
Returns
-------
children : list
@@ -7733,6 +8223,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `Prototypes` child, otherwise fail.
If `False` return all `Prototypes` children in this element
+
Returns
-------
children : list
@@ -7748,6 +8239,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `PlayerRo` child, otherwise fail.
If `False` return all `PlayerRo` children in this element
+
Returns
-------
children : list
@@ -7762,6 +8254,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `GlobalOption` child, otherwise fail.
If `False` return all `GlobalOption` children in this element
+
Returns
-------
children : list
@@ -7775,6 +8268,7 @@ class Game(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `Inventorie` elements. If `False`, return a list of all Inventorie` children.
+
Returns
-------
children : dict or list
@@ -7788,6 +8282,7 @@ class Game(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `PieceWindow` elements. If `False`, return a list of all PieceWindow` children.
+
Returns
-------
children : dict or list
@@ -7801,6 +8296,7 @@ class Game(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `ChartWindow` elements. If `False`, return a list of all ChartWindow` children.
+
Returns
-------
children : dict or list
@@ -7814,6 +8310,7 @@ class Game(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `DiceButton` elements. If `False`, return a list of all DiceButton` children.
+
Returns
-------
children : dict or list
@@ -7827,6 +8324,7 @@ class Game(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `PredefinedSetup` elements. If `False`, return a list of all PredefinedSetup` children.
+
Returns
-------
children : dict or list
@@ -7841,6 +8339,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `Note` child, otherwise fail.
If `False` return all `Note` children in this element
+
Returns
-------
children : list
@@ -7854,6 +8353,7 @@ class Game(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `TurnTrack` elements. If `False`, return a list of all TurnTrack` children.
+
Returns
-------
children : dict or list
@@ -7867,6 +8367,7 @@ class Game(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `Piece` elements. If `False`, return a list of all Piece` children.
+
Returns
-------
children : dict or list
@@ -7880,6 +8381,7 @@ class Game(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `SpecificPiece` elements. If `False`, return a list of all SpecificPiece` children.
+
Returns
-------
children : dict or list
@@ -7896,6 +8398,7 @@ class Game(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `WidgetMap` elements. If `False`, return a list of all WidgetMap` children.
+
Returns
-------
children : dict or list
@@ -7909,6 +8412,7 @@ class Game(Element):
----------
asdict : bool
If `True`, return a dictonary that maps key to `Map` elements. If `False`, return a list of all Map` children.
+
Returns
-------
children : dict or list
@@ -7931,6 +8435,7 @@ class Game(Element):
elements. If `False`, return a list of all Board`
children.
+
Returns
-------
children : dict or list
@@ -7948,6 +8453,7 @@ class Game(Element):
elements. If `False`, return a list of all Board`
children.
+
Returns
-------
children : dict or list
@@ -7965,6 +8471,7 @@ class Game(Element):
elements. If `False`, return a list of all Board`
children.
+
Returns
-------
children : dict or list
@@ -7982,6 +8489,7 @@ class Game(Element):
elements. If `False`, return a list of all Board`
children.
+
Returns
-------
children : dict or list
@@ -8014,6 +8522,7 @@ class Game(Element):
single : bool
If `True`, there can be only one `AtStart` child, otherwise fail.
If `False` return all `AtStart` children in this element
+
Returns
-------
children : list
@@ -8057,6 +8566,7 @@ class BuildFile(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Game
@@ -8096,6 +8606,7 @@ class Data(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Version
@@ -8109,6 +8620,7 @@ class Data(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : VASSALVersion
@@ -8122,6 +8634,7 @@ class Data(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Name
@@ -8135,6 +8648,7 @@ class Data(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Description
@@ -8148,6 +8662,7 @@ class Data(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : DateSaved
@@ -8162,6 +8677,7 @@ class Data(Element):
single : bool
If `True`, there can be only one `Version` child, otherwise fail.
If `False` return all `Version` children in this element
+
Returns
-------
children : list
@@ -8177,6 +8693,7 @@ class Data(Element):
If `True`, there can be only one `VASSALVersion` child,
otherwise fail. If `False` return all `VASSALVersion`
children in this element
+
Returns
-------
children : list
@@ -8195,6 +8712,7 @@ class Data(Element):
If `True`, there can be only one `Description` child,
otherwise fail. If `False` return all `De` children in
this element
+
Returns
-------
children : list
@@ -8210,6 +8728,7 @@ class Data(Element):
single : bool
If `True`, there can be only one `DateSaved` child, otherwise fail.
If `False` return all `DateSaved` children in this element
+
Returns
-------
children : list
@@ -8289,6 +8808,7 @@ class ModuleData(Element):
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Data
@@ -8928,6 +9448,18 @@ class VMod:
def fileName(self):
'''Get name of VMod file'''
return self._vmod.filename
+
+ def replaceFiles(self,**files):
+ '''Replace existing files with new files
+
+ Parameters
+ ----------
+ files : dict
+ Dictionary that maps file name to content
+ '''
+ self.removeFiles(*list(files.keys()))
+
+ self.addFiles(**files);
def addFiles(self,**files):
'''Add a set of files to this
@@ -8949,6 +9481,7 @@ class VMod:
File name in module
content : str
File content
+
Returns
-------
element : File
@@ -8963,6 +9496,7 @@ class VMod:
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : ExternalFile
@@ -8974,6 +9508,14 @@ class VMod:
def getFileNames(self):
'''Get all filenames in module'''
return self._vmod.namelist()
+
+ def getFileMapping(self):
+ '''Get mapping from short name to full archive name'''
+ from pathlib import Path
+
+ names = self.getFileNames()
+
+ return {Path(p).stem: str(p) for p in names}
def getFiles(self,*filenames):
'''Return named files as a dictionary.
@@ -8982,6 +9524,7 @@ class VMod:
----------
filenames : tuple
The files to get
+
Returns
-------
files : dict
@@ -9009,7 +9552,7 @@ class VMod:
r = self.getFiles(filename)
if filename not in r:
- raise RuntimeException(f'No {filename} found!')
+ raise RuntimeError(f'No {filename} found!')
return parseString(r[filename])
@@ -9031,6 +9574,7 @@ class VMod:
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : VSav
@@ -9043,6 +9587,187 @@ class VMod:
# EOF
#
# ====================================================================
+# From upgrade.py
+
+
+class VLogUpgrader:
+ def __init__(self,
+ vmodFileName,
+ vlogFileName,
+ verbose=False):
+ self._readVModFile(vmodFileName,verbose)
+ self._readVLogFile(vlogFileName,verbose)
+
+ def _readVModFile(self,vmodFileName,verbose=False):
+ with VMod(vmodFileName, 'r') as vmod:
+ self._build = BuildFile(vmod.getBuildFile())
+ self._game = self._build.getGame()
+
+ self._vmod_pieces = {}
+ for piece in self._game.getPieces():
+ name, piece = self._expandPiece(piece,verbose)
+ self._vmod_pieces[name] = piece
+
+ def _expandPiece(self,piece,verbose=False):
+ traits = piece.getTraits();
+ newTraits = Trait.flatten(traits, game=self._game,verbose=verbose)
+
+ piece.setTraits(*newTraits)
+
+ name = newTraits[-1]['name']
+
+ return name, piece
+
+ def _readVLogFile(self,vlogFileName,verbose=False):
+ key, lines, sdata, mdata = SaveIO.readSave(vlogFileName,
+ alsometa=True)
+
+ self._key = key
+ self._lines = lines
+ self._save_data = sdata
+ self._meta_data = mdata
+ self._vlog_pieces = {}
+
+ for line in self._lines:
+ iden, name, piece = self._vlogPiece(line,verbose)
+ if piece is None:
+ continue
+
+ vmod_piece = self._vmod_pieces.get(name,None)
+ if vmod_piece is None:
+ print(f'Did not find piece "{name}" in vmod')
+ vmod_piece = piece
+
+ vmod_piece.copyStates(piece)
+ self._vlog_pieces[iden] = {'name': name,
+ 'vlog': piece,
+ 'vmod': vmod_piece}
+
+
+ def _vlogPiece(self,line,verbose=False):
+ from re import match
+
+ m = match(r'^\+/([0-9]+)/.*;([a-z0-9_]+)\.png.*',line)
+ if m is None:
+ return None,None,None
+
+ iden = int(m.group(1))
+ piece = PieceSlot(None)
+ piece.setTraits(*piece.decodeAdd(line,verbose),iden=iden)
+ basic = piece.getTraits()[-1]
+
+ return iden,basic['name'],piece
+
+
+ def _newLine(self,line,verbose):
+ self._new_lines.append(line)
+ if verbose:
+ print(line)
+
+ def upgrade(self,shownew=False,verbose=False):
+ self._new_lines = []
+ for line in self._lines:
+ add_line = self.newDefine(line,verbose)
+ if add_line:
+ self._newLine(add_line,shownew)
+ continue
+
+ cmd_line = self.newCommand(line,verbose)
+ if cmd_line:
+ self._newLine(cmd_line,shownew)
+ continue
+
+ oth_line = self.other(line,verbose)
+ if oth_line:
+ self._newLine(oth_line,shownew)
+ continue
+
+ self._newLine(line,shownew)
+
+ def newCommand(self,line,verbose=False):
+ from re import match
+
+ m = match(r'LOG\s+([+MD])/([0-9]+)/([^/]+)(.*)',line)
+ if not m:
+ return None
+
+ cmd = m.group(1)
+ iden = int(m.group(2))
+ more = m.group(3)
+
+ if more == 'stack':
+ return None
+
+ vp = self._vlog_pieces.get(iden,None)
+ if vp is None:
+ print(f'Piece {iden} not found: "{line}"')
+ return None
+
+ if cmd == '+' or cmd == 'M':
+ return None
+
+ # Get the code
+ code = more + m.group(4)
+
+ # Decode the states from the code into the old piece
+ vp['vlog'].decodeStates(code,verbose)
+
+ # Get the previsous state from the new piece
+ old = vp['vmod'].encodedStates()
+
+ # Copy states from the old piece to the new piece
+ vp['vmod'].copyStates(vp['vlog'],verbose)
+
+ # Get the new state code from the new piece
+ new = vp['vmod'].encodedStates()
+
+ newline = 'LOG\t'+cmd+'/'+str(iden)+'/'+new+'/'+old+'\\\\'
+ # print('WAS',line)
+ # print('NOW',newline)
+ return newline
+
+ def newDefine(self,line,verbose):
+ from re import match
+
+ m = match(r'\+/([0-9]+)/([^/]+).*',line)
+
+ if not m:
+ return False
+
+ iden = int(m.group(1))
+ more = m.group(2)
+ if more == 'stack':
+ return False
+
+ vp = self._vlog_pieces.get(iden,None)
+ if vp is None:
+ print(f'Piece {iden} not known')
+
+ old = vp['vlog']
+ new = vp['vmod']
+
+ old_add = old._node.childNodes[0].nodeValue;
+ new_add = new.encodeAdd(*new.getTraits(),iden=iden,verbose=verbose);
+
+ return new_add
+
+ def other(self,line,verbose=False):
+ return None
+
+
+ def write(self,outFileName,verbose=False):
+ SaveIO.writeSave(outFileName,
+ key = 0xAA,
+ lines = self._new_lines,
+ savedata = self._save_data,
+ moduledata = self._meta_data)
+
+
+
+#
+# EOF
+#
+# ====================================================================
# From exporter.py
class Exporter:
@@ -9137,12 +9862,87 @@ class Exporter:
# Exporter class
#
class LaTeXExporter(Exporter):
+ class Specials:
+ BATTLE_MARK = 'wgBattleMarker'
+ BATTLE_CTRL = 'wgBattleCtrl'
+ BATTLE_CALC = 'wgBattleCalc'
+ BATTLE_UNIT = 'wgBattleUnit'
+ ODDS_MARK = 'wgOddsMarker'
+ HIDDEN_NAME = 'wg hidden unit'
+
+ class Keys:
+ MARK_BATTLE = key(NONE,0)+',wgMarkBattle'
+ CLEAR_BATTLE = key(NONE,0)+',wgClearBattle'
+ CLEAR_ALL_BATTLE = key(NONE,0)+',wgClearAllBattle'
+ ZERO_BATTLE = key(NONE,0)+',wgZeroBattle'
+ INCR_BATTLE = key(NONE,0)+',wgIncrBattle'
+ SET_BATTLE = key(NONE,0)+',wgSetBattle'
+ GET_BATTLE = key(NONE,0)+',wgGetBattle'
+ MARK_ODDS = key(NONE,0)+',wgMarkOdds'
+ MARK_RESULT = key(NONE,0)+',wgMarkResult'
+ CLEAR_MOVED = key(NONE,0)+',wgClearMoved'
+ ZERO_BATTLE_AF = key(NONE,0)+',wgZeroBattleAF'
+ ZERO_BATTLE_DF = key(NONE,0)+',wgZeroBattleDF'
+ ZERO_BATTLE_FRAC = key(NONE,0)+',wgZeroBattleFrac'
+ ZERO_BATTLE_ODDS = key(NONE,0)+',wgZeroBattleOdds'
+ ZERO_BATTLE_SHFT = key(NONE,0)+',wgZeroBattleShift'
+ ZERO_BATTLE_IDX = key(NONE,0)+',wgZeroBattleIdx'
+ CALC_BATTLE_AF = key(NONE,0)+',wgCalcBattleAF'
+ CALC_BATTLE_DF = key(NONE,0)+',wgCalcBattleDF'
+ CALC_BATTLE_FRAC = key(NONE,0)+',wgCalcBattleFrac'
+ CALC_BATTLE_ODDS = key(NONE,0)+',wgCalcBattleOdds'
+ CALC_BATTLE_SHFT = key(NONE,0)+',wgCalcBattleShift'
+ CALC_BATTLE_IDX = key(NONE,0)+',wgCalcBattleIdx'
+ CALC_BATTLE_RES = key(NONE,0)+',wgCalcBattleResult'
+ CLEAR_BATTLE_PHS = key(NONE,0)+',wgClearBattlePhs'
+ RESOLVE_BATTLE = key(NONE,0)+',wgResolveBattle'
+ ROLL_DICE = key(NONE,0)+',wgRollDice'
+ DICE_INIT_KEY = key(NONE,0)+',wgInitDice'
+ CLEAR_KEY = key('C')
+ CLEAR_ALL_KEY = key('C',CTRL_SHIFT)
+ DELETE_KEY = key('D')
+ ELIMINATE_KEY = key('E')
+ FLIP_KEY = key('F')
+ TRAIL_KEY = key('T')
+ RESTORE_KEY = key('R')
+ MARK_KEY = key('X')
+ RESOLVE_KEY = key('Y')
+ ROTATE_CCWKey = key('[')
+ ROTATE_CWKey = key(']')
+ CHARTS_KEY = key('A',ALT)
+ OOB_KEY = key('B',ALT)
+ COUNTERS_KEY = key('C',ALT)
+ DEAD_KEY = key('E',ALT)
+ DICE_KEY = key('6',ALT)
+ RECALC_ODDS = key('X',CTRL_SHIFT)
+
+ class Globals:
+ BATTLE_COUNTER = 'wgBattleCounter'
+ CURRENT_BATTLE = 'wgCurrentBattle'
+ CURRENT_ATTACKER = 'wgCurrentAttacker'
+ BATTLE_NO = 'wgBattleNo'
+ BATTLE_AF = 'wgBattleAF'
+ BATTLE_DF = 'wgBattleDF'
+ BATTLE_FRAC = 'wgBattleFrac'
+ BATTLE_IDX = 'wgBattleIdx'
+ BATTLE_ODDS = 'wgBattleOdds'
+ BATTLE_ODDSM = 'wgBattleOddsMarker'
+ BATTLE_SHIFT = 'wgBattleShift'
+ BATTLE_RESULT = 'wgBattleResult'
+ AUTO_ODDS = 'wgAutoOdds'
+ AUTO_RESULTS = 'wgAutoResults'
+ NO_CLEAR_MOVES = 'wgNoClearMoves'
+ NO_CLEAR_BATTLES = 'wgNoClearBattles'
+ DEBUG = 'wgDebug'
+ VERBOSE = 'wgVerbose'
+
def __init__(self,
vmodname = 'Draft.vmod',
pdfname = 'export.pdf',
infoname = 'export.json',
title = 'Draft',
version = 'draft',
+ imageFormat = 'png',
description = '',
rules = None,
tutorial = None,
@@ -9197,76 +9997,80 @@ class LaTeXExporter(Exporter):
self._nochit = nochit
self._resolution = resolution
self._counterScale = counterScale
- self._battleMark = 'wgBattleMarker'
+ self._img_format = imageFormat.lower()
+
+ self._battleMark = LaTeXExporter.Specials.BATTLE_MARK
+ self._oddsMark = LaTeXExporter.Specials.ODDS_MARK
+ self._battleCtrl = LaTeXExporter.Specials.BATTLE_CTRL
+ self._battleCalc = LaTeXExporter.Specials.BATTLE_CALC
+ self._battleUnit = LaTeXExporter.Specials.BATTLE_UNIT
+ self._hiddenName = LaTeXExporter.Specials.HIDDEN_NAME
+ self._markBattle = LaTeXExporter.Keys.MARK_BATTLE
+ self._clearBattle = LaTeXExporter.Keys.CLEAR_BATTLE
+ self._clearAllBattle = LaTeXExporter.Keys.CLEAR_ALL_BATTLE
+ self._zeroBattle = LaTeXExporter.Keys.ZERO_BATTLE
+ self._incrBattle = LaTeXExporter.Keys.INCR_BATTLE
+ self._setBattle = LaTeXExporter.Keys.SET_BATTLE
+ self._getBattle = LaTeXExporter.Keys.GET_BATTLE
+ self._markOdds = LaTeXExporter.Keys.MARK_ODDS
+ self._markResult = LaTeXExporter.Keys.MARK_RESULT
+ self._clearMoved = LaTeXExporter.Keys.CLEAR_MOVED
+ self._zeroBattleAF = LaTeXExporter.Keys.ZERO_BATTLE_AF
+ self._zeroBattleDF = LaTeXExporter.Keys.ZERO_BATTLE_DF
+ self._zeroBattleFrac = LaTeXExporter.Keys.ZERO_BATTLE_FRAC
+ self._zeroBattleOdds = LaTeXExporter.Keys.ZERO_BATTLE_ODDS
+ self._zeroBattleShft = LaTeXExporter.Keys.ZERO_BATTLE_SHFT
+ self._zeroBattleIdx = LaTeXExporter.Keys.ZERO_BATTLE_IDX
+ self._calcBattleAF = LaTeXExporter.Keys.CALC_BATTLE_AF
+ self._calcBattleDF = LaTeXExporter.Keys.CALC_BATTLE_DF
+ self._calcBattleFrac = LaTeXExporter.Keys.CALC_BATTLE_FRAC
+ self._calcBattleOdds = LaTeXExporter.Keys.CALC_BATTLE_ODDS
+ self._calcBattleShft = LaTeXExporter.Keys.CALC_BATTLE_SHFT
+ self._calcBattleIdx = LaTeXExporter.Keys.CALC_BATTLE_IDX
+ self._calcBattleRes = LaTeXExporter.Keys.CALC_BATTLE_RES
+ self._clearBattlePhs = LaTeXExporter.Keys.CLEAR_BATTLE_PHS
+ self._resolveBattle = LaTeXExporter.Keys.RESOLVE_BATTLE
+ self._rollDice = LaTeXExporter.Keys.ROLL_DICE
+ self._diceInitKey = LaTeXExporter.Keys.DICE_INIT_KEY
+ self._clearKey = LaTeXExporter.Keys.CLEAR_KEY
+ self._clearAllKey = LaTeXExporter.Keys.CLEAR_ALL_KEY
+ self._deleteKey = LaTeXExporter.Keys.DELETE_KEY
+ self._eliminateKey = LaTeXExporter.Keys.ELIMINATE_KEY
+ self._flipKey = LaTeXExporter.Keys.FLIP_KEY
+ self._trailKey = LaTeXExporter.Keys.TRAIL_KEY
+ self._restoreKey = LaTeXExporter.Keys.RESTORE_KEY
+ self._markKey = LaTeXExporter.Keys.MARK_KEY
+ self._resolveKey = LaTeXExporter.Keys.RESOLVE_KEY
+ self._rotateCCWKey = LaTeXExporter.Keys.ROTATE_CCWKey
+ self._rotateCWKey = LaTeXExporter.Keys.ROTATE_CWKey
+ self._chartsKey = LaTeXExporter.Keys.CHARTS_KEY
+ self._oobKey = LaTeXExporter.Keys.OOB_KEY
+ self._countersKey = LaTeXExporter.Keys.COUNTERS_KEY
+ self._deadKey = LaTeXExporter.Keys.DEAD_KEY
+ self._diceKey = LaTeXExporter.Keys.DICE_KEY
+ self._recalcOdds = LaTeXExporter.Keys.RECALC_ODDS
+ self._battleCounter = LaTeXExporter.Globals.BATTLE_COUNTER
+ self._currentBattle = LaTeXExporter.Globals.CURRENT_BATTLE
+ self._currentAttacker = LaTeXExporter.Globals.CURRENT_ATTACKER
+ self._battleNo = LaTeXExporter.Globals.BATTLE_NO
+ self._battleAF = LaTeXExporter.Globals.BATTLE_AF
+ self._battleDF = LaTeXExporter.Globals.BATTLE_DF
+ self._battleFrac = LaTeXExporter.Globals.BATTLE_FRAC
+ self._battleIdx = LaTeXExporter.Globals.BATTLE_IDX
+ self._battleOdds = LaTeXExporter.Globals.BATTLE_ODDS
+ self._battleOddsM = LaTeXExporter.Globals.BATTLE_ODDSM
+ self._battleShift = LaTeXExporter.Globals.BATTLE_SHIFT
+ self._battleResult = LaTeXExporter.Globals.BATTLE_RESULT
+ self._autoOdds = LaTeXExporter.Globals.AUTO_ODDS
+ self._autoResults = LaTeXExporter.Globals.AUTO_RESULTS
+ self._noClearMoves = LaTeXExporter.Globals.NO_CLEAR_MOVES
+ self._noClearBattles = LaTeXExporter.Globals.NO_CLEAR_BATTLES
+ self._debug = LaTeXExporter.Globals.DEBUG
+ self._verbose = LaTeXExporter.Globals.VERBOSE
self._battleMarks = []
self._oddsMarks = []
self._resultMarks = []
- self._markBattle = key(NONE,0)+',wgMarkBattle'
- self._clearBattle = key(NONE,0)+',wgClearBattle'
- self._clearAllBattle = key(NONE,0)+',wgClearAllBattle'
- self._zeroBattle = key(NONE,0)+',wgZeroBattle'
- self._incrBattle = key(NONE,0)+',wgIncrBattle'
- self._setBattle = key(NONE,0)+',wgSetBattle'
- self._getBattle = key(NONE,0)+',wgGetBattle'
- self._markOdds = key(NONE,0)+',wgMarkOdds'
- self._markResult = key(NONE,0)+',wgMarkResult'
- self._clearMoved = key(NONE,0)+',wgClearMoved'
- self._zeroBattleAF = key(NONE,0)+',wgZeroBattleAF'
- self._zeroBattleDF = key(NONE,0)+',wgZeroBattleDF'
- self._zeroBattleFrac = key(NONE,0)+',wgZeroBattleFrac'
- self._zeroBattleOdds = key(NONE,0)+',wgZeroBattleOdds'
- self._zeroBattleShft = key(NONE,0)+',wgZeroBattleShift'
- self._zeroBattleIdx = key(NONE,0)+',wgZeroBattleIdx'
- self._calcBattleAF = key(NONE,0)+',wgCalcBattleAF'
- self._calcBattleDF = key(NONE,0)+',wgCalcBattleDF'
- self._calcBattleFrac = key(NONE,0)+',wgCalcBattleFrac'
- self._calcBattleOdds = key(NONE,0)+',wgCalcBattleOdds'
- self._calcBattleShft = key(NONE,0)+',wgCalcBattleShift'
- self._calcBattleIdx = key(NONE,0)+',wgCalcBattleIdx'
- self._calcBattleRes = key(NONE,0)+',wgCalcBattleResult'
- self._clearBattlePhs = key(NONE,0)+',wgClearBattlePhs'
- self._resolveBattle = key(NONE,0)+',wgResolveBattle'
- self._rollDice = key(NONE,0)+',wgRollDice'
- self._diceInitKey = key(NONE,0)+',wgInitDice'
- self._clearKey = key('C')
- self._clearAllKey = key('C',CTRL_SHIFT)
- self._deleteKey = key('D')
- self._eliminateKey = key('E')
- self._flipKey = key('F')
- self._trailKey = key('M')
- self._restoreKey = key('R')
- self._markKey = key('X')
- self._resolveKey = key('Y')
- self._rotateCCWKey = key('[')
- self._rotateCWKey = key(']')
- self._chartsKey = key('A',ALT)
- self._oobKey = key('B',ALT)
- self._countersKey = key('C',ALT)
- self._deadKey = key('E',ALT)
- self._diceKey = key('6',ALT)
- self._battleCounter = 'wgBattleCounter'
- self._currentBattle = 'wgCurrentBattle'
- self._currentAttacker = 'wgCurrentAttacker'
- self._battleNo = 'wgBattleNo'
- self._battleAF = 'wgBattleAF'
- self._battleDF = 'wgBattleDF'
- self._battleFrac = 'wgBattleFrac'
- self._battleIdx = 'wgBattleIdx'
- self._battleOdds = 'wgBattleOdds'
- self._battleOddsM = 'wgBattleOddsMarker'
- self._battleShift = 'wgBattleShift'
- self._battleCtrl = 'wgBattleCtrl'
- self._battleCalc = 'wgBattleCalc'
- self._battleUnit = 'wgBattleUnit'
- self._battleResult = 'wgBattleResult'
- self._autoOdds = 'wgAutoOdds'
- self._autoResults = 'wgAutoResults'
- self._noClearMoves = 'wgNoClearMoves'
- self._noClearBattles = 'wgNoClearBattles'
- self._debug = 'wgDebug'
- self._verbose = 'wgVerbose'
self._hidden = None
- self._hiddenName = 'wg hidden unit'
self._dice = {}
self._diceInit = None
@@ -9283,6 +10087,8 @@ class LaTeXExporter(Exporter):
v(f'Visible grids: {self._visible}')
v(f'Resolution: {self._resolution}')
v(f'Scale of counters: {self._counterScale}')
+ v(f'Image format: {self._img_format}')
+
def setup(self):
# Start the processing
@@ -9306,6 +10112,7 @@ class LaTeXExporter(Exporter):
----------
args : list
List of process command line elements
+
Returns
-------
pipe : subprocess.Pipe
@@ -9320,16 +10127,18 @@ class LaTeXExporter(Exporter):
def addPws(self,opw=None,upw=None):
'''Add a `Pws` element to arguments
+ Add password options
+
Parameters
----------
kwargs : dict
Dictionary of attribute key-value pairs
+
Returns
-------
element : Pws
The added element
'''
- '''Add password options'''
args = []
if upw is not None: args.extend(['-upw',upw])
if opw is not None: args.extend(['-opw',opw])
@@ -9392,6 +10201,92 @@ class LaTeXExporter(Exporter):
return info
# ================================================================
+ @classmethod
+ def parseLength(cls,value,def_unit='px'):
+ from re import match
+
+ scales = {
+ 'px': 1,
+ 'pt': 1.25,
+ 'pc': 15,
+ 'in': 90,
+ 'mm': 3.543307,
+ 'cm': 35.43307,
+ '%': -1/100
+ }
+
+ if not value:
+ return 0
+
+ parts = match(r'^\s*(-?\d+(?:\.\d+)?)\s*(px|in|cm|mm|pt|pc|%)?', value)
+ if not parts:
+ raise RuntimeError(f'Unknown length format: "{value}"')
+
+ number = float(parts.group(1))
+ unit = parts.group(2) or def_unit
+ factor = scales.get(unit,None)
+
+ if not factor:
+ raise RuntimeError(f'Unknown unit: "{unit}"')
+
+ return factor * number
+
+ # ----------------------------------------------------------------
+ @classmethod
+ def scaleSVG(cls,buffer,factor):
+ '''Buffer is bytes'''
+ from xml.dom.minidom import parse
+ from re import split
+ from io import StringIO, BytesIO
+
+ if not LaTeXExporter.isSVG(buffer):
+ return buffer
+
+ with BytesIO(buffer) as stream:
+ doc = parse(stream)
+
+ if not doc:
+ raise RuntimeError('Failed to parse buffer as XML')
+
+ root = doc.childNodes[0]
+ getA = lambda e,n,d=None : \
+ e.getAttribute(n) if e.hasAttribute(n) else d
+ setA = lambda e,n,v : e.setAttribute(n,v)
+ leng = LaTeXExporter.parseLength
+
+ width = leng(getA(root,'width', '0'))
+ height = leng(getA(root,'height','0'))
+ vport = getA(root,'viewBox','0 0 0 0').strip()
+ vp = [leng(v) for v in split('[ \t,]',vport)]
+ # print(f'Input WxH: {width}x{height} ({vp})')
+
+ width *= factor
+ height *= factor
+ vp = [factor * v for v in vp]
+
+ # print(f'Scaled WxH: {width}x{height} ({vp})')
+
+ if width <= 0 and vp:
+ width = vp[2] - vp[0]
+
+ if height <= 0 and vp:
+ height = vp[3] - vp[1]
+
+ if not vp:
+ vp = [0, 0, width, height]
+
+ setA(root,'transform',f'scale({factor})')
+ setA(root,'width', f'{width}')
+ setA(root,'height',f'{height}')
+ setA(root,'viewBox',' '.join([f'{v}' for v in vp]))
+
+
+ with StringIO() as out:
+ doc.writexml(out)
+ return out.getvalue().encode()
+
+
+ # ================================================================
def convertPage(self,page,opw=None,upw=None,timeout=None):
'''Convert a page from PDF into an image (bytes)
@@ -9411,17 +10306,22 @@ class LaTeXExporter(Exporter):
info : dict
Image information
'''
- args = ['pdftocairo',
+ args = ['pdftocairo']
+ if self._img_format != 'svg':
+ args.extend([
'-transp',
- '-singlefile',
+ '-singlefile'])
+
+ args.extend([
'-r', str(self._resolution),
'-f', str(page),
'-l', str(page),
- '-png' ]
+ f'-{self._img_format}' ])
args.extend(self.addPws(opw=opw,upw=upw))
args.append(self._pdfname)
args.append('-')
-
+
+ # print(f'Conversion command',' '.join(args))
proc = self.createProcess(args)
try:
@@ -9432,7 +10332,16 @@ class LaTeXExporter(Exporter):
raise RuntimeError(f'Failed to convert page {page} of '
f'{self._pdfname}: {e}')
- # Just return the bytes
+ if len(out) <= 0:
+ raise RuntimeError(f'Failed to convert page {page} of '
+ f'{self._pdfname}: {err}')
+
+ # This does not seem to work - VASSAL (and Inkscape) does not
+ # apply the 'scale' transformation to the image!
+ #
+ # if self._img_format == 'svg':
+ # out = LaTeXExporter.scaleSVG(out,2)
+
return out
@@ -9501,6 +10410,11 @@ class LaTeXExporter(Exporter):
return imgsinfo
# ----------------------------------------------------------------
+ @classmethod
+ def isSVG(cls,buffer):
+ return buffer[:5] == b'<?xml'
+
+ # ----------------------------------------------------------------
def getBB(self,buffer):
'''Get bounding box of image
@@ -9514,11 +10428,26 @@ class LaTeXExporter(Exporter):
ulx, uly, lrx, lry : tuple
The coordinates of the bounding box
'''
- from PIL import Image
from io import BytesIO
+
+ with BytesIO(buffer) as inp:
+ if LaTeXExporter.isSVG(buffer):
+ from svgelements import SVG
+
+ svg = SVG.parse(inp)
+ # bb = svg.bbox()
+ # if bb is None:
+ # print(f'No bounding box!')
+ # bb = [0, 0, 1, 1]
+ # else:
+ # bb = [int(b) for b in bb]
+ x, y, w, h = svg.x, svg.y, svg.width, svg.height
+ bb = (x,y,x+w,y+h)
+ else:
+ from PIL import Image
- with Image.open(BytesIO(buffer)) as img:
- bb = img.getbbox()
+ with Image.open(inp) as img:
+ bb = img.getbbox()
return bb
@@ -9536,11 +10465,21 @@ class LaTeXExporter(Exporter):
ulx, uly, lrx, lry : tuple
The coordinates of the bounding box
'''
- from PIL import Image
from io import BytesIO
-
- with Image.open(BytesIO(buffer)) as img:
- w, h = img.width, img.height
+
+ with BytesIO(buffer) as inp:
+ if LaTeXExporter.isSVG(buffer):
+ from svgelements import SVG
+
+ svg = SVG.parse(inp)
+ w, h = svg.x, svg.y, svg.width, svg.height
+ # bb = svg.bbox()
+ # w, h = int(bb[2]-bb[0]),int(bb[3]-bb[1])
+ else:
+ from PIL import Image
+
+ with Image.open(inp) as img:
+ w, h = img.width, img.height
return w,h
@@ -9591,11 +10530,13 @@ class LaTeXExporter(Exporter):
typ = info.get('category','counter')
sub = info.get('subcategory','all')
-
- info['filename'] = info['name'].replace(' ','_') + '.png'
+ nam = info['name']
+ num = info['number']
+
+ info['filename'] = f'{nam.replace(" ","_")}.{self._img_format}'
imgfn = 'images/'+info['filename']
if imgfn not in self._vmod.getFileNames():
- if typ == 'counter':
+ if typ == 'counter' and self._img_format != 'svg':
# print(f'Possibly scale file {imgfn}')
info['img'] = self.scaleImage(info['img'],
counterScale)
@@ -9621,9 +10562,19 @@ class LaTeXExporter(Exporter):
cat[sub] = {}
tgt = cat[sub]
- v(f'[{info["name"]}]',end=' ',flush=True,noindent=True)
+ v(f'[{nam}]',end=' ',flush=True,noindent=True)
#self.message(f'Adding "{info["name"]}" to catalogue')
- tgt[info['name']] = info
+ #
+ # Here we could handle multiple info's with the same
+ # name by adding a unique postfix - e.g., for dices
+ # what have non-uniform PMFs.
+ #
+ # if info['name'] in tgt:
+ # n = len([i for k,i in tgt.items() if k.startswith(info['name'])])
+ # info['name'] += '_' + str(n)
+ # info['filename'] = info['name'].replace(' ','_') + '.png'
+ unam = f'{nam}'
+ tgt[unam] = info
if self._nonato: continue
@@ -9854,7 +10805,7 @@ class LaTeXExporter(Exporter):
v(f'We have symbolic dice')
self._diceInit = []
# from pprint import pprint
- # pprint(self._dice,depth=3)
+ # pprint(self._dice,depth=2)
for die, faces in self._dice.items():
ico = self.getIcon(die+'-die-icon','')
# print(f'Die {die} icon="{ico}"')
@@ -9866,7 +10817,9 @@ class LaTeXExporter(Exporter):
text = die if ico == '' else '',
icon = ico,
tooltip = f'{die} die roll',
- format = (f'{{"{die} die roll: "+result1'
+ format = (f'{{"<b>"+PlayerSide+"</b> "+'
+ f'"(<i>"+PlayerName+"</i>): "+'+
+ f'"{die} die roll: "+result1'
# f'+" <img src=\'{die}-"+result1'
# f'+".png\' width=24 height=24>"'
f'}}'),
@@ -9876,7 +10829,8 @@ class LaTeXExporter(Exporter):
sdie = symb.addDie(name = die);
for face, fdata in faces.items():
fn = fdata['filename']
- val = int(fn.replace('.png','').replace(die+'-',''))
+ val = int(fn.replace(f'.{self._img_format}','')
+ .replace(die+'-',''))
dmin = min(dmin,val)
dmax = min(dmax,val)
sdie.addFace(icon = fn,
@@ -9988,6 +10942,7 @@ class LaTeXExporter(Exporter):
[['Ctrl-C', 'Counter', 'Clear battle'],
['Ctrl-Shift-C','Board', 'Clear all battle'],
['Ctrl-X', 'Board,Counter','Mark battle'],
+ ['Ctrl-Shift-X','Board,Counter','Recalculate Odds'],
['Ctrl-Y', 'Board,Counter','Resolve battle'],
]):
ks = [k[0] for k in keys]
@@ -10092,6 +11047,7 @@ class LaTeXExporter(Exporter):
wrap = True,
description = 'Zero battle counter',
),
+ # Set global property combat # from this
GlobalPropertyTrait(
['',self._setBattle,GlobalPropertyTrait.DIRECT,
f'{{{self._battleCounter}}}'],
@@ -10411,6 +11367,8 @@ class LaTeXExporter(Exporter):
# for the current battle
#
traits = [
+ # getBattle retrieves the battle number from the global property.
+ # clearBattle sets piece battle to -1
DynamicPropertyTrait(['',self._getBattle,
DynamicPropertyTrait.DIRECT,
f'{{{self._currentBattle}}}'],
@@ -10421,7 +11379,9 @@ class LaTeXExporter(Exporter):
numeric = True,
value = f'{{-1}}',
description = 'Set battle number'),
- GlobalPropertyTrait(['',self._setBattle, GlobalPropertyTrait.DIRECT,
+ # This setBattle sets current attacker in global property
+ GlobalPropertyTrait(['',self._setBattle,
+ GlobalPropertyTrait.DIRECT,
'{IsAttacker}'],
name = self._currentAttacker,
numeric = True,
@@ -10457,6 +11417,9 @@ class LaTeXExporter(Exporter):
description = f'Add battle marker {i+1}',
placement = PlaceTrait.ABOVE,
above = False))
+ # Get current global battle number
+ # Set current battle
+ # Filtered on current global battle # is equal to
trig.append(
TriggerTrait(command = '',#Mark battle',
key = self._markBattle,
@@ -10758,7 +11721,9 @@ class LaTeXExporter(Exporter):
def oddsMarkerTraits(self,c=None):
'''Derives from the CurrentBattle prototype and adds a submenu
to replace odds counter with result marker'''
+ gpid = self._game.nextPieceSlotId()
traits = [PrototypeTrait(name=self._currentBattle),
+ MarkTrait(self._oddsMark,'true'),
NonRectangleTrait(filename = c['filename'],
image = c['img']),
DynamicPropertyTrait(
@@ -10773,13 +11738,53 @@ class LaTeXExporter(Exporter):
TriggerTrait(command = '',
key = self._getBattle+'Details',
actionKeys = [self._getBattle,
- self._getBattle+'More'])]
+ self._getBattle+'More']),
+ # DeleteTrait('',self._recalcOdds+'Delete'),
+ # ReplaceTrait(command = '',
+ # key = self._recalcOdds+'Replace',
+ # markerSpec = '',
+ # markerText = 'null',
+ # xOffset = 0,
+ # yOffset = 0,
+ # matchRotation = False,
+ # afterKey = '',
+ # gpid = gpid,
+ # description = f'Replace with nothing'),
+ GlobalHotkeyTrait(name = '',
+ key = self._calcBattleOdds+'Start',
+ globalHotkey = self._calcBattleOdds+'ReAuto',
+ description = 'Trampoline to global'),
+ # Recalculate odds
+ # First setBatle to make battle No global
+ # Then delete this
+ # Then send global key command
+ TriggerTrait(command = 'Recalculate',
+ key = self._recalcOdds,
+ actionKeys = [self._setBattle,
+ self._calcBattleOdds+'Start',
+ self._clearBattle,
+ ]),
+ ReportTrait(self._recalcOdds+'Delete',
+ report=(f'{{{self._debug}?'
+ f'("~ "+BasicName+'
+ f'": Deleting self"):""}}')),
+ ReportTrait(self._clearBattle,
+ report=(f'{{{self._debug}?'
+ f'("~ "+BasicName+'
+ f'": Remove"):""}}')),
+ ReportTrait(self._recalcOdds,
+ report=(f'{{{self._debug}?'
+ f'("! Recalculate Odds"):""}}')),
+ ReportTrait(self._calcBattleOdds+'Start',
+ report=(f'{{{self._debug}?'
+ f'("~ Start auto recalculate Odds"):""}}')),
+ ]
subs = []
place = []
trig = []
rept = []
- ukeys = []
+ ukeys = [self._recalcOdds]
first = ''
for i, result in enumerate(self._resultMarks):
r = result.replace('result marker','').strip()
@@ -10910,7 +11915,9 @@ class LaTeXExporter(Exporter):
traits = [#ReportTrait(self._eliminateKey,
# self._restoreKey,
# self._trailKey),
- TrailTrait(),
+ TrailTrait(lineWidth = 5,
+ radius = 10,
+ key = self._trailKey),
RotateTrait(),
MovedTrait(xoff = int(offX),yoff = int(offY)),
DeleteTrait(),
@@ -10921,6 +11928,8 @@ class LaTeXExporter(Exporter):
restoreName = 'Restore',
restoreKey = self._restoreKey,
description = 'Eliminate unit'),
+ # ReportTrait(self._trailKey,
+ # f'{{"Enabling trail on "+BasicName}}'),
PrototypeTrait(name=self._battleUnit),
MarkTrait(name='Faction',value=faction)]
@@ -10966,6 +11975,7 @@ class LaTeXExporter(Exporter):
bb = self.getBB(c['img'])
height = bb[3]-bb[1] if bb is not None else 1
width = bb[2]-bb[0] if bb is not None else 1
+
cf = subc.get(cn + ' flipped', None)
traits = [PrototypeTrait(name=f'{subn} prototype')]
@@ -10974,10 +11984,14 @@ class LaTeXExporter(Exporter):
if not self._nonato:
mains = c.get('mains','')
- m = set([clean(mains)] +
- [clean(m) for m in mains.split(',')])
- traits.extend([PrototypeTrait(name=f'{m.strip()} prototype')
- for m in set(m)])
+ mm = clean(mains).strip()
+ traits.append(PrototypeTrait(name=f'{mm} prototype'))
+ # Commented code adds all 'main' types as prototypes, which
+ # doesn't make so much sense
+ #
+ # m = set([clean(m) for m in mains.split(',')])
+ # traits.extend([PrototypeTrait(name=f'{m.strip()} prototype')
+ # for m in set(m)])
for p in ['echelon','command']:
val = c.get(p,None)
if val is not None:
@@ -11187,10 +12201,17 @@ class LaTeXExporter(Exporter):
True if any piece can be flipped
'''
with VerboseGuard(f'Adding board {name}') as v:
+ # from pprint import pprint
+ # pprint(info)
map = self._game.addMap(mapName=name,
markUnmovedHotkey=self._clearMoved)
map.addCounterDetailViewer(
- propertyFilter=f'{{{self._battleMark}!=true}}')
+ propertyFilter=f'{{{self._battleMark}!=true}}',
+ fontSize = 14,
+ summaryReportFormat = '<b>$LocationName$</b>',
+ hotkey = key('\n'),
+ stopAfterShowing = True
+ )
map.addHidePiecesButton()
map.addGlobalMap()
# Basics
@@ -11207,18 +12228,23 @@ class LaTeXExporter(Exporter):
map.addHighlightLastMoved()
map.addZoomer()
- map.addMassKey(name='Eliminate',
+ map.addMassKey(name = 'Eliminate',
buttonHotkey = self._eliminateKey,
hotkey = self._eliminateKey,
icon = self.getIcon('eliminate-icon',
'/icons/16x16/edit-undo.png'),
tooltip = 'Eliminate selected units')
- map.addMassKey(name='Delete',
+ map.addMassKey(name = 'Delete',
buttonHotkey = self._deleteKey,
hotkey = self._deleteKey,
icon = self.getIcon('delete-icon',
'/icons/16x16/no.png'),
tooltip = 'Delete selected units')
+ map.addMassKey(name = 'Trail',
+ buttonHotkey = self._trailKey,
+ hotkey = self._trailKey,
+ icon = '',
+ tooltip = '')
map.addMassKey(name='Rotate CW',
buttonHotkey = self._rotateCWKey,
hotkey = self._rotateCWKey,
@@ -11244,7 +12270,7 @@ class LaTeXExporter(Exporter):
f'{self._noClearMoves})'
f':""}}'))
if hasFlipped:
- map.addMassKey(name='Flip',
+ map.addMassKey(name = 'Flip',
buttonHotkey = self._flipKey,
hotkey = self._flipKey,
icon = self.getIcon('flip-icon',
@@ -11266,14 +12292,15 @@ class LaTeXExporter(Exporter):
curUnt = (f'{{{self._battleNo}=={self._currentBattle}&&'
f'{self._battleUnit}==true}}')
markSel = (f'{{{self._battleNo}=={self._currentBattle}&&'
- f'{self._battleMark}==true}}')
+ f'{self._battleMark}==true&&'
+ f'{self._oddsMark}!=true}}')
# ctrlSel = '{BasicName=="wg hidden unit"}'
map.addMassKey(name = 'User mark battle',
buttonHotkey = self._markKey,
buttonText = '',
hotkey = self._markBattle,
- icon = 'battle-marker-icon.png',
+ icon = f'battle-marker-icon.{self._img_format}',
tooltip = 'Mark battle',
target = '',
singleMap = False,
@@ -11336,7 +12363,7 @@ class LaTeXExporter(Exporter):
buttonText = '',
buttonHotkey = self._clearAllKey,
hotkey = self._clearAllBattle,
- icon = 'clear-battles-icon.png',
+ icon = f'clear-battles-icon.{self._img_format}',
tooltip = 'Clear all battles',
target = '',
singleMap = False,
@@ -11364,7 +12391,7 @@ class LaTeXExporter(Exporter):
map.addMassKey(name = 'Selected resolve battle',
buttonHotkey = self._resolveKey,
hotkey = self._resolveKey,
- icon = 'resolve-battles-icon.png',
+ icon = f'resolve-battles-icon.{self._img_format}',
tooltip = 'Resolve battle',
singleMap = False,
filter = oddsSel,
@@ -11433,15 +12460,45 @@ class LaTeXExporter(Exporter):
reportFormat = (f'{{{self._debug}?'
f'("~ {name}: '
f'Auto calculate odds"):""}}'))
+ map.addMassKey(name = 'User recalc',
+ buttonHotkey = self._recalcOdds,
+ buttonText = '',
+ hotkey = self._recalcOdds,
+ icon = '',
+ tooltip = 'Recalculate odds',
+ singleMap = False,
+ filter = '',
+ reportFormat = (f'{{{self._debug}?'
+ f'("~ {name}: '
+ f'Recalculate odds"):""}}'))
+ map.addMassKey(name = 'Auto recalc battle odds',
+ buttonText = '',
+ buttonHotkey = self._calcBattleOdds+'ReAuto',
+ hotkey = self._calcBattleOdds+'Start',
+ icon = '',
+ tooltip = '',
+ target = '',
+ singleMap = False,
+ filter = markSel,
+ reportFormat = (f'{{{self._debug}?'
+ f'("~ {name}: '
+ f'Auto re-calculate odds"):""}}'))
+ v(f'Getting the board dimensions')
ulx,uly,lrx,lry = self.getBB(info['img'])
- width = abs(ulx - lrx)
- height = abs(uly - lry)
- width, height = self.getWH(info['img'])
+ width = int(abs(ulx - lrx))
+ height = int(abs(uly - lry))
+ # Why is it we take the width and height like this?
+ # Do they every differ from the above?
+ # This is the only place that we actually use this
+ #
+ # width, height = self.getWH(info['img'])
height += 20
width += 5
-
+ # v(f'{ulx},{uly},{lrx},{lry}')
+
+ v(f'Board BB=({lrx},{lry})x({ulx},{uly}) {width}x{height}')
picker = map.addBoardPicker()
board = picker.addBoard(name = name,
image = info['filename'],
@@ -11451,13 +12508,14 @@ class LaTeXExporter(Exporter):
zoned.addHighlighter()
if not 'zones' in info:
- full = zoned.addZone(name = full,
+ color = rgb(255,0,0)
+ full = zoned.addZone(name = 'full',
useParentGrid = False,
path=(f'{ulx},{uly};' +
f'{lrx},{uly};' +
f'{lrx},{lry};' +
f'{ulx},{lry}'))
- grid = zone.addHexGrid(color = color,
+ grid = full.addHexGrid(color = color,
dx = HEX_WIDTH,
dy = HEX_HEIGHT,
visible = self._visible)
@@ -11489,7 +12547,7 @@ class LaTeXExporter(Exporter):
'''Add a "Dead Map" element to the module
'''
name = 'DeadMap'
- with VerboseGuard(f'Adding board {name}') as v:
+ with VerboseGuard(f'Adding deadmap {name}') as v:
map = self._game.addMap(mapName = name,
buttonName = '',
markMoved = 'Never',
@@ -12009,7 +13067,7 @@ class LaTeXExporter(Exporter):
# Do not add grids to pools
if ispool:
- v('Board {n} is pool with no points')
+ v(f'Board {n} is pool with no points')
continue
targs = {'color':rgb(255,0,0),'visible':self._visible}
@@ -12227,118 +13285,216 @@ class LaTeXExporter(Exporter):
self._game.addDiceButton(name = '1d6',
hotkey = self._diceKey)
+# ====================================================================
+def patchVmod(vmod_filename,patch_name,verbose):
+
+ with VMod(vmod_filename,'r') as vmod:
+ buildFile = BuildFile(vmod.getBuildFile())
+ moduleData = ModuleData(vmod.getModuleData())
+
+ from importlib.util import spec_from_file_location, module_from_spec
+ from pathlib import Path
+ from sys import modules
+
+ p = Path(patch_name)
+
+ spec = spec_from_file_location(p.stem, p.absolute())
+ module = module_from_spec(spec)
+ spec.loader.exec_module(module)
+
+ modules[p.stem] = module
+
+ with VMod(vmod_filename,'a') as vmod:
+ module.patch(buildFile,
+ moduleData,
+ vmod,
+ verbose)
+
+ vmod.replaceFiles(**{VMod.BUILD_FILE :
+ buildFile.encode(),
+ VMod.MODULE_DATA :
+ moduleData.encode()})
+
+
#
# EOF
#
# ====================================================================
# From main.py
+from argparse import ArgumentParser
+
+class DefaultSubcommandArgParse(ArgumentParser):
+ _default_subparser = None
+
+ def set_default_subparser(self, name):
+ self._default_subparser = name
+
+ def _parse_known_args(self, arg_strings, *args, **kwargs):
+ from argparse import _SubParsersAction
+ in_args = set(arg_strings)
+ d_sp = self._default_subparser
+ if d_sp is not None and not {'-h', '--help'}.intersection(in_args):
+ for x in self._subparsers._actions:
+ subparser_found = (
+ isinstance(x, _SubParsersAction) and
+ in_args.intersection(x._name_parser_map.keys())
+ )
+ if subparser_found:
+ break
+ else:
+ # insert default in first position, this implies no
+ # global options without a sub_parsers specified
+ arg_strings = [d_sp] + arg_strings
+ return super(DefaultSubcommandArgParse, self)._parse_known_args(
+ arg_strings, *args, **kwargs
+ )
+# ====================================================================
+def patchIt(args):
+ vmodname = args.output.name
+ patchname = args.patch.name
+ args.output.close()
+ args.patch .close()
+
+ patchVmod(vmodname, patchname, args.verbose)
+
+# ====================================================================
+def exportIt(args):
+
+ vmodname = args.output.name
+ patchname = args.patch.name if args.patch is not None else None
+
+ args.output.close()
+ if args.patch is not None:
+ args.patch.close()
+
+ Verbose().setVerbose(args.verbose)
+
+ try:
+ if args.version.lower() == 'draft':
+ args.visible_grids = True
+
+ rulesname = args.rules.name if args.rules is not None else None
+ tutname = args.tutorial.name if args.tutorial is not None else None
+
+ exporter = LaTeXExporter(vmodname = vmodname,
+ pdfname = args.pdffile.name,
+ infoname = args.infofile.name,
+ title = args.title,
+ version = args.version,
+ description = args.description,
+ rules = rulesname,
+ tutorial = tutname,
+ patch = patchname,
+ visible = args.visible_grids,
+ vassalVersion = args.vassal_version,
+ nonato = args.no_nato_prototypes,
+ nochit = args.no_chit_information,
+ resolution = args.resolution,
+ counterScale = args.counter_scale,
+ imageFormat = args.image_format)
+ exporter.run()
+ except Exception as e:
+ from sys import stderr
+ print(f'Failed to build {vmodname}: {e}',file=stderr)
+ from os import unlink
+ try:
+ unlink(vmodname)
+ except:
+ pass
+
+ raise e
+
+
# ====================================================================
if __name__ == '__main__':
from argparse import ArgumentParser, FileType
- ap = ArgumentParser(description='Create draft VASSAL module')
- ap.add_argument('pdffile',
+ ap = DefaultSubcommandArgParse(description='Create draft VASSAL module')
+ ap.set_default_subparser('export')
+ sp = ap.add_subparsers(dest='mode')
+
+ pp = sp.add_parser('patch',help='Patch VMod')
+ pp.add_argument('output',
+ help='Module to patch',
+ type=FileType('r'),
+ default='Draft.vmod')
+ pp.add_argument('patch',
+ help='A python script to patch generated module',
+ type=FileType('r'),
+ default='patch.py')
+ pp.add_argument('-V','--verbose',
+ help='Be verbose',
+ action='store_true')
+
+
+ ep = sp.add_parser('export',help='Export from PDF and JSON to VMod')
+ ep.add_argument('pdffile',
help='The PDF file to read images from',
type=FileType('r'),
default='export.pdf',
nargs='?')
- ap.add_argument('infofile',
+ ep.add_argument('infofile',
help='The JSON file to read image information from',
type=FileType('r'),
default='export.json',
nargs='?')
- ap.add_argument('-p','--patch',
- help='A python script to patch generated module',
- type=FileType('r'))
- ap.add_argument('-o','--output',
+ ep.add_argument('-o','--output',
help='Output file to write module to',
type=FileType('w'),
default='Draft.vmod')
- ap.add_argument('-t','--title',
+ ep.add_argument('-p','--patch',
+ help='A python script to patch generated module',
+ type=FileType('r'))
+ ep.add_argument('-V','--verbose',
+ help='Be verbose',
+ action='store_true')
+ ep.add_argument('-t','--title',
help='Module title', default='Draft',
type=str)
- ap.add_argument('-v','--version',
+ ep.add_argument('-v','--version',
help='Module version',
type=str,
default='draft')
- ap.add_argument('-r','--rules',
+ ep.add_argument('-r','--rules',
help='Rules PDF file',
type=FileType('r'))
- ap.add_argument('-T','--tutorial',
+ ep.add_argument('-T','--tutorial',
help='Tutorial (v)log file',
type=FileType('r'))
- ap.add_argument('-d','--description',
+ ep.add_argument('-d','--description',
help='Short description of module',
type=str,
default='draft of module')
- ap.add_argument('-W','--vassal-version',
+ ep.add_argument('-W','--vassal-version',
help='Vassal version number',
type=str,
default='3.6.7')
- ap.add_argument('-V','--verbose',
- help='Be verbose',
- action='store_true')
- ap.add_argument('-G','--visible-grids',
+ ep.add_argument('-G','--visible-grids',
action='store_true',
help='Make grids visible in the module')
- ap.add_argument('-N','--no-nato-prototypes',
+ ep.add_argument('-N','--no-nato-prototypes',
action='store_true',
help='Do not make prototypes for types,echelons,commands')
- ap.add_argument('-C','--no-chit-information',
+ ep.add_argument('-C','--no-chit-information',
action='store_true',
help='Do not make properties from chit information')
- ap.add_argument('-S','--counter-scale',
+ ep.add_argument('-S','--counter-scale',
type=float, default=1,
help='Scale counters by factor')
- ap.add_argument('-R','--resolution',
+ ep.add_argument('-R','--resolution',
type=int, default=150,
help='Resolution of images')
-
-
+ ep.add_argument('-I','--image-format',
+ choices = ['png','svg'], default='png',
+ help='Image format to use')
+
args = ap.parse_args()
- vmodname = args.output.name
- rulesname = args.rules.name if args.rules is not None else None
- tutname = args.tutorial.name if args.tutorial is not None else None
- args.output.close()
-
- patchname = args.patch.name if args.patch is not None else None
- if args.patch is not None:
- args.patch.close()
-
- if args.version.lower() == 'draft':
- args.visible_grids = True
-
- Verbose().setVerbose(args.verbose)
-
- try:
- exporter = LaTeXExporter(vmodname = vmodname,
- pdfname = args.pdffile.name,
- infoname = args.infofile.name,
- title = args.title,
- version = args.version,
- description = args.description,
- rules = rulesname,
- tutorial = tutname,
- patch = patchname,
- visible = args.visible_grids,
- vassalVersion = args.vassal_version,
- nonato = args.no_nato_prototypes,
- nochit = args.no_chit_information,
- resolution = args.resolution,
- counterScale = args.counter_scale)
- exporter.run()
- except Exception as e:
- from sys import stderr
- print(f'Failed to build {vmodname}: {e}',file=stderr)
- from os import unlink
- try:
- unlink(vmodname)
- except:
- pass
-
- raise e
+ if args.mode == 'patch':
+ patchIt(args)
+ else:
+ exportIt(args)
#
# EOF
diff --git a/Master/texmf-dist/tex/latex/wargame/wgmakenato.py b/Master/texmf-dist/tex/latex/wargame/wgmakenato.py
new file mode 100755
index 00000000000..65dcceb41f6
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/wargame/wgmakenato.py
@@ -0,0 +1,756 @@
+#!/usr/bin/env python
+
+# ====================================================================
+def ensure_list(what):
+ if not what:
+ return None
+
+ if isinstance(what,str):
+ return [what]
+
+ return what
+
+# --------------------------------------------------------------------
+def clean(base, suffixes):
+ from pathlib import Path
+
+ if not isinstance(base,Path):
+ base = Path(base)
+
+ for suffix in suffixes:
+ tgt = base.with_suffix(suffix)
+ tgt.unlink(missing_ok=True)
+
+# ====================================================================
+possible_commands = ['air',
+ 'land',
+ 'equipment',
+ 'installation',
+ 'sea surface',
+ 'sub surface',
+ 'space',
+ 'activity',
+ 'dismounted']
+possible_factions = ['friendly',
+ 'hostile',
+ 'neutral',
+ 'unknown']
+echelon_mapping = {'': 'team',
+ '*': 'squad',
+ '**': 'section',
+ '***': 'platoon',
+ '|': 'company',
+ '||': 'battalion',
+ '|||': 'regiment',
+ 'x': 'brigade',
+ 'xx': 'division',
+ 'xxx': 'corps',
+ 'xxxx': 'army',
+ 'xxxxx': 'army group',
+ 'xxxxxx': 'theater'}
+possible_echelons = list(echelon_mapping.values())+list(echelon_mapping.keys())
+
+# ====================================================================
+def make_picture(command,
+ faction,
+ echelon,
+ main,
+ top=None,
+ bottom=None,
+ left=None,
+ right=None,
+ below=None,
+ decoy=False,
+ line_width='1pt',
+ scale=.45,
+ more=None,
+ **kwargs):
+ '''Create latex code for the NATO App6 symbol - a single tikzpicture
+
+ Parameters
+ ----------
+ command : str
+ Command (base symbol)
+ faction : str
+ Faction (base symbol)
+ echelon : str or None
+ Echelon (top of base symbol
+ main : str or list of str
+ Main symbols
+ top : str or list of str
+ Top modifiers
+ bottom : str or list of str
+ Bottom modifiers
+ left : str or list of str
+ Left modifiers
+ right : str or list of str
+ Right modifiers
+ below : str or list of str
+ Below base frame
+ decoy : bool
+ True if it should be a decoy
+ line_width : str
+ Line width, including unit
+ scale : float
+ Scaling of image
+
+ Return
+ ------
+ out : str
+ LaTeX code to write to file
+ '''
+ ind = ' '
+ def add_line(out,key,what,ind=ind):
+ '''Adds a line with a key'''
+ lwhat = ensure_list(what)
+ if not lwhat:
+ return out
+
+ swhat = ",".join(lwhat)
+
+ return out+f'{ind} {key}={{{swhat}}},%'+'\n'
+
+
+ out = fr'''\begin{{tikzpicture}}%
+ \natoapp[%
+ scale={scale},%
+ scale line widths,%
+ line width={line_width},%
+ command={command},%
+ faction={faction},%'''+'\n'
+
+ out = add_line(out,'echelon',echelon)
+ out = add_line(out,'main', main)
+ out = add_line(out,'top', top)
+ out = add_line(out,'bottom', bottom)
+ out = add_line(out,'left', left)
+ out = add_line(out,'right', right)
+ out = add_line(out,'below', below)
+ if more:
+ out += f'{ind} {more}%'+'\n'
+
+ out += fr''' ];%
+ \end{{tikzpicture}}%
+ '''
+ lout = out.split('\n')
+ lout = [l[len(ind):] if l.startswith(ind) else l for l in lout]
+ return '\n'.join(lout)
+
+# --------------------------------------------------------------------
+def make_latex(db):
+ '''Create latex code for the all NATO App6 symbols -
+ a complete document
+
+ Parameters
+ ----------
+ db : list of dict
+ Configurations of each symbol
+
+ Return
+ ------
+ out : str
+ LaTeX code to write to file
+ '''
+
+ ind = ' '
+ out = r'''\documentclass[tikz,11pt]{standalone}
+ \usepackage{wargame}
+ \begin{document}%'''+'\n'
+
+ for entry in db:
+ out += make_picture(**entry)
+
+ out += r'\end{document}'
+
+ lout = out.split('\n')
+ lout = [l[len(ind):] if l.startswith(ind) else l for l in lout]
+ return '\n'.join(lout)
+
+
+# --------------------------------------------------------------------
+def make_name(command,
+ faction,
+ echelon,
+ main,
+ top=None,
+ bottom=None,
+ left=None,
+ right=None,
+ below=None,
+ decoy=False,
+ output=None,
+ **kwargs):
+ '''Create the file name
+
+ Parameters
+ ----------
+ command : str
+ Command (base symbol)
+ faction : str
+ Faction (base symbol)
+ echelon : str or None
+ Echelon (top of base symbol
+ main : str or list of str
+ Main symbols
+ top : str or list of str
+ Top modifiers
+ bottom : str or list of str
+ Bottom modifiers
+ left : str or list of str
+ Left modifiers
+ right : str or list of str
+ Right modifiers
+ decoy : bool
+ True if it should be a decoy
+
+ Return
+ ------
+ out : str
+ Output file name
+ '''
+ if output:
+ return output.format(command=command,
+ faction=faction,
+ echelon=echelon)\
+ .replace(' ','-')\
+ .replace('=','-')
+
+ def clean_sub(what):
+ from re import sub
+
+ res = what
+ while True:
+ old = res
+ res = sub(r'\[[^]]+\]','',res)
+ res = sub(r'\{[^}]+\}','',res)
+ if res == old:
+ break
+
+ return res
+
+ def add_component(out, what,sep='-'):
+
+ lwhat = ensure_list(what)
+
+ if not lwhat:
+ return out
+
+ return out+'_'+sep.join([clean_sub(l) for l in lwhat])
+
+ def add_front(out,what,sep='_'):
+ if not what:
+ return out
+
+ if len(out) > 0: out += sep
+ return out + what
+
+ out = ''
+ out = add_front(out,faction)
+ out = add_front(out,command.replace(' ','-'))
+ out = add_front(out,echelon.replace(' ','-'))
+ out = add_component(out,main)
+ out = add_component(out,top)
+ out = add_component(out,bottom)
+ out = add_component(out,left)
+ out = add_component(out,right)
+ out = add_component(out,below)
+
+ return out.replace(' ','-').replace('=','-')
+
+
+# ====================================================================
+default_latex_flags = ['-interaction=nonstopmode',
+ '-file-line-error',
+ '-synctex','15',
+ '-shell-escape']
+default_latex_command = 'pdflatex'
+
+# --------------------------------------------------------------------
+def create_process(args,verbose=False):
+ '''Create a subprocess with arguments
+
+ Returns
+ -------
+ proc : Popen
+ Process with stdout and stderr as pipes (fifos)
+ '''
+ from os import environ
+ from subprocess import Popen, PIPE
+
+ if verbose:
+ print(f'Will run: "{" ".join(args)}"')
+
+ return Popen(args,env=environ.copy(),stdout=PIPE,stderr=PIPE)
+
+# --------------------------------------------------------------------
+default_timeout = None
+default_keep = False
+# --------------------------------------------------------------------
+def run_latex(file,
+ content,
+ latex_cmd = default_latex_command,
+ latex_flags = default_latex_flags,
+ timeout = default_timeout,
+ keep = default_keep,
+ verbose = False):
+ '''Run latex on generated content
+
+ Parameters
+ ----------
+ filename : str
+ The file to write
+ content : str
+ Content to write to source file
+ latex_cmd : str
+ LaTeX command to run e.g., 'pdflatex'
+ latex_flags : list of str
+ Flags to pass to the LaTeX command line
+ timeout : int
+ Process timeout
+ keep : bool
+ If true, keep intermediate files
+
+ Returns
+ -------
+ None
+ '''
+ from pathlib import Path
+
+ fpath = Path(file.name).with_suffix('')
+ csuf = ['.aux','.log','.out','.synctex','.synctex.gz','.tex']
+
+ file.write(content)
+ file.close()
+
+ lflags = ensure_list(latex_flags)
+
+ args = [latex_cmd] + (lflags if lflags else + []) + \
+ [fpath.with_suffix('.tex').name]
+
+ proc = create_process(args,verbose=verbose)
+
+ try:
+ out, err = proc.communicate(timeout=timeout)
+
+ sout = out.decode()
+ if 'Error' in sout or \
+ 'Emergency stop' in sout or \
+ not Path(fpath).with_suffix('.pdf').is_file():
+ raise RuntimeError(sout)
+
+ except Exception as e:
+ proc.kill()
+ proc.communicate()
+ if not keep:
+ clean(base=fpath,suffixes=csuf+['.pdf'])
+
+ raise RuntimeError(f'Failed on "{" ".join(args)}" with:\n'+
+ str(e) + '\n--- Start LaTeX code -------\n'+
+ content+ '\n--- End LaTeX code ---------')
+
+ if not keep:
+ clean(base=fpath,suffixes=csuf)
+
+# --------------------------------------------------------------------
+possible_formats = ['png','svg','jpg','tiff']
+default_format = possible_formats[0]
+default_resolution = 150
+
+# --------------------------------------------------------------------
+def run_cairo(filename,
+ npages,
+ format = default_format,
+ resolution = default_resolution,
+ timeout = default_timeout,
+ keep = default_keep,
+ verbose = False):
+ '''Run 'pdftocairo' on generated PDF
+
+ Parameters
+ ----------
+ filename : str
+ The file to write
+ format : str
+ Image format to write
+ resolution : int
+ Pixels Per Inch (PPI)
+ timeout : int
+ Process timeout
+ keep : bool
+ If true, keep intermediate files
+
+ Returns
+ -------
+ None
+ '''
+ from pathlib import Path
+
+ fpath = Path(filename)
+ args = ['pdftocairo']
+ if format != 'svg':
+ args.extend(['-transp'])
+
+ args.extend(['-r',str(resolution),f'-{format}'])
+
+ inpdf = fpath.with_suffix('.pdf').name
+
+ def runit(args,pdf=inpdf,outimg=None):
+ args.append(inpdf)
+ if outimg: args.append(outimg)
+
+ proc = create_process(args,verbose)
+
+ try:
+ out, err = proc.communicate(timeout=timeout)
+
+ except Exception as e:
+ proc.kill()
+ proc.communicate()
+ if not keep:
+ clean(base=fpath,suffixes=[f'.{format}','.pdf'])
+
+ raise RuntimeError(f'Failed on "{" ".join(args)}" with:\n'+e)
+
+ if format != 'svg':
+ runit(args)
+ else:
+ from math import ceil, log10
+
+ base = fpath.stem
+ wn = ceil(log10(npages))
+ for no in range(1,npages+1):
+ no_args = args.copy()
+ no_args.extend(['-f',str(no),'-l',str(no)])
+
+ runit(no_args,outimg=base+f'-{no:0{wn}d}.{format}')
+
+ if not keep:
+ clean(base=fpath,suffixes=['.pdf'])
+
+# --------------------------------------------------------------------
+def make_images(db,
+ base_name,
+ format = default_format,
+ verbose = False):
+ from math import ceil, log10
+ from pathlib import Path
+
+ results = []
+ ndb = len(db)
+ wn = ceil(log10(ndb))
+ for no,entry in enumerate(db):
+ output = entry['output']+'.'+format
+ inpath = Path(f'{base_name}-{no+1:0{wn}d}.{format}')
+
+ inpath.rename(output)
+ results.append(output)
+ if verbose:
+ print(f'{no+1:0{wn}d}/{ndb}: {output}')
+
+ return results
+
+# --------------------------------------------------------------------
+default_xml = False
+
+# --------------------------------------------------------------------
+def write_xmls(db,
+ format = default_format,
+ verbose = False):
+ '''Build an XML snippet of a prototype'''
+
+ ndb = len(db)
+ wn = ceil(log10(ndb))
+ for no,entry in enumerate(db):
+ if verbose:
+ print(f'{no+1:0{wn}d}/{ndb} ...{entry["output"]}.xml')
+
+ write_xml(**entry,format=format)
+
+# --------------------------------------------------------------------
+def write_xml(command = None,
+ faction = None,
+ echelon = None,
+ main = None,
+ top = None,
+ bottom = None,
+ left = None,
+ right = None,
+ below = None,
+ decoy = False,
+ output = None,
+ format = default_format,
+ **kwargs):
+ '''Build an XML snippet of a prototype'''
+ from xml.dom.minidom import Document
+ from wgexport import LayerTrait, Prototype, MarkTrait, \
+ BasicTrait, BuildFile
+
+ doc = BuildFile()
+ hasEchelon = echelon and len(echelon) > 0
+
+ yoff = -8 if main else -10 if echelon else -8
+ traits = [
+ LayerTrait(
+ images = [f'{output}.{format}'],
+ newNames = [''],
+ activateName = '',
+ activateMask = '',
+ activateChar = '',
+ increaseName = '',
+ increaseMask = '',
+ increaseChar = '',
+ decreaseName = '',
+ decreaseMask = '',
+ decreaseChar = '',
+ resetName = '',
+ resetKey = '',
+ resetLevel = 1,
+ under = False,
+ underXoff = 0,
+ underYoff = yoff,
+ loop = False,
+ name = ('NATOAPP6_command_faction'
+ +('_main' if main else '')
+ +('_echelon' if hasEchelon else '')),
+ description = 'NATO App6 symbology',
+ randomKey = '',
+ randomName = '',
+ follow = False,
+ expression = '',
+ first = 1,
+ version = 1,
+ always = True,
+ activateKey = '',
+ increaseKey = '',
+ decreaseKey = '',
+ scale = 1.)]
+
+ if command:
+ traits.append(MarkTrait(name = 'NATOAPP6_command',
+ value = command))
+ if main:
+ traits.append(MarkTrait(name = 'NATOAPP6_type',
+ value = make_name(command = '',
+ faction = '',
+ echelon = '',
+ main = main,
+ top = top,
+ bottom = bottom,
+ left = left,
+ right = right,
+ below = below,
+ decoy = decoy)))
+ if echelon:
+ traits.append(MarkTrait(name = 'NATOAPP6_echelon',
+ value = echelon))
+
+ traits.append(BasicTrait())
+
+
+ proto = Prototype(doc,
+ name = output,
+ traits = traits,
+ description = 'NATO App6 symbol')
+
+ doc._node.insertBefore(
+ doc._root.createComment('Created via LaTeX wargame package, '
+ 'licensed under the CreativeCommons '
+ 'Share-Alike, '
+ '© 2024 Christian Holm Christensen'),
+ proto._node)
+ xml_out = doc.encode()
+
+ with open(output+'.xml','wb') as out:
+ out.write(xml_out)
+
+
+# ====================================================================
+def create_images(db,
+ latex_command = default_latex_command,
+ latex_flags = default_latex_flags,
+ timeout = default_timeout,
+ resolution = default_resolution,
+ format = default_format,
+ keep = default_keep,
+ verbose = False,
+ xml = default_xml):
+ from tempfile import NamedTemporaryFile
+ from pathlib import Path
+
+ result = []
+
+
+ with NamedTemporaryFile(mode='w',suffix='.tex',dir='.',
+ delete=not keep,
+ delete_on_close=False) as texfile:
+ if verbose:
+ print(f'Temporary file: {texfile.name}')
+
+ base_name = Path(texfile.name).stem
+ latex_code = make_latex(db)
+ try:
+ run_latex(texfile,
+ latex_code,
+ latex_cmd = latex_command,
+ latex_flags = latex_flags,
+ timeout = timeout,
+ keep = keep,
+ verbose = verbose)
+
+ run_cairo(base_name,
+ npages = len(db),
+ format = format,
+ resolution = resolution,
+ timeout = timeout,
+ keep = keep,
+ verbose = verbose)
+
+ result = make_images(db,
+ base_name,
+ format = format,
+ verbose = verbose)
+
+ if xml:
+ write_xmls(db)
+
+ except Exception as e:
+ import traceback
+ print(traceback.format_exc())
+ print(e)
+ return None
+
+ return result
+
+
+# ====================================================================
+#
+# Main program
+#
+if __name__ == '__main__':
+ from argparse import ArgumentParser, FileType
+ from pprint import pprint
+
+ ap = ArgumentParser(description='Create an image of NATO App6 symbol')
+ ap.add_argument('-c','--command',type=str,choices=possible_commands,
+ help='Select command',default=possible_commands[1])
+ ap.add_argument('-f','--faction',type=str,choices=possible_factions,
+ help='Select faction',default=possible_factions[0])
+ ap.add_argument('-e','--echelon',type=str,choices=possible_echelons,
+ help='Select echelon')
+ ap.add_argument('-m','--main',type=str,nargs='*',
+ help='Select main symbol(s)')
+ ap.add_argument('-t','--top',type=str,nargs='*',
+ help='Select top modifier(s)')
+ ap.add_argument('-b','--bottom',type=str,nargs='*',
+ help='Select bottom modifier(s)')
+ ap.add_argument('-l','--left',type=str,nargs='*',
+ help='Select left modifier(s)')
+ ap.add_argument('-r','--right',type=str,nargs='*',
+ help='Select left modifier(s)')
+ ap.add_argument('-B','--below',type=str,nargs='*',
+ help='Select below (mobility) modifier(s)')
+ ap.add_argument('-d','--decoy',action='store_true',
+ help='Mark as decoy')
+ ap.add_argument('-w','--line-width',default='1pt',type=str,
+ help='Line width, including unit')
+ ap.add_argument('-s','--scale',default=0.45,type=float,
+ help='Scaling of symbol (width in centimetre)')
+ ap.add_argument('-I','--format',default=default_format,
+ choices=possible_formats,type=str,
+ help='Output image format')
+ ap.add_argument('-L','--latex-command',default=default_latex_command,
+ help='Set the LaTeX command to use',type=str)
+ ap.add_argument('-F','--latex-flags',default=default_latex_flags,
+ help='Set the LaTeX command to use',type=str,nargs='*')
+ ap.add_argument('-T','--timeout',default=default_timeout,type=int,
+ help='Timeout of sub-processes')
+ ap.add_argument('-R','--resolution',default=default_resolution,type=int,
+ help='Resolution out output image (ppi)')
+ ap.add_argument('-k','--keep',action='store_true',
+ help='Leave intermediate files')
+ ap.add_argument('-o','--output',type=str,
+ help='Set output file name, default is autogenerated')
+ ap.add_argument('-j','--json',type=str,nargs='*',
+ help='Read symbols to create from JSON file')
+ ap.add_argument('-v','--verbose',action='store_true')
+ ap.add_argument('-X','--xml',action='store_true',
+ help='Also output XML snippets')
+
+ args = ap.parse_args()
+ vargs = vars(args)
+ oargs = {}
+ to_remove = ['latex_command',
+ 'latex_flags',
+ 'resolution',
+ 'format',
+ 'timeout',
+ 'keep',
+ 'json',
+ 'verbose',
+ 'xml']
+ for key in to_remove:
+ if key not in vargs:
+ continue
+
+ oargs[key] = vargs[key]
+ del vargs[key]
+
+ commons = ['infantry',
+ 'armoured',
+ 'armoured+infantry',
+ 'reconnaissance',
+ 'armoured+reconnaissance',
+ '[fill=pgfstrokecolor]artillery',
+ 'armoured+[fill=pgfstrokecolor]artillery',
+ 'text=SF']
+
+
+ db = None
+ main = vargs['main']
+ injson = oargs.pop('json',None)
+
+ #pprint(vargs)
+ #pprint(oargs)
+
+ if injson:
+ from json import load
+
+ db = []
+ for j in injson:
+ print(f'=== JSON input: {j}')
+ with open(j,'r') as jin:
+ db.extend(load(jin))
+
+ elif main and len(main) == 1 and main[0] == 'common':
+ db = [{'main': w.split('+')} for w in commons]
+ else:
+ db = [vargs]
+
+ if not db:
+ raise RuntimeError('Noting to do')
+
+ from math import log10, ceil
+
+ def ensure(d, key, default):
+ if key not in d and default:
+ d[key] = default[key]
+
+ results = []
+ ndb = len(db)
+ wn = ceil(log10(ndb))
+ for no,entry in enumerate(db):
+ print(f'{no:{wn}d} of {ndb} ...',end='')
+ if not isinstance(entry,dict):
+ print(' skipped')
+ continue
+
+ for key in vargs.keys():
+ ensure(entry,key,vargs)
+ entry['output'] = make_name(**entry)
+ print(entry['output'])
+
+
+ results = create_images(db,**oargs)
+#
+#
+#