Any package for typesetting polyominos/tetris-like shapes?
Code 1
\documentclass[tikz,border=2pt]{standalone}
\usetikzlibrary{matrix}
\makeatletter
\newcounter{qrr@tikz@omino}
\newcounter{qrr@tikz@omino@up}
\newcounter{qrr@tikz@omino@right}
\tikzset{
omino/.style={/tikz/omino/.cd,#1},
omino/distance/.initial=1,
omino/radius/.initial=.5,
omino/at/.style={/tikz/shift={(#1)}},
omino/rotate/.style={/tikz/rotate=#1},
omino/s/.code=
\setcounter{qrr@tikz@omino}{0}%
\setcounter{qrr@tikz@omino@up}{0}%
\setcounter{qrr@tikz@omino@right}{0}%
\pgfkeysalso{/tikz/insert path={(0,0) node[/tikz/omino/nodes/.try,/tikz/omino/node normal/.try,/tikz/omino/node start/.try] {\qrr@tikz@omino@text@start}}},
omino/u/.code=%
\stepcounter{qrr@tikz@omino}%
\stepcounter{qrr@tikz@omino@up}%
\pgfkeysalso{/tikz/insert path={
to[/tikz/omino/how] ++(up:#1)
node[/tikz/omino/nodes/.try,/tikz/omino/node normal/.try,/tikz/omino/node up/.try]{\qrr@tikz@omino@text@up}}},
omino/d/.code=%
\stepcounter{qrr@tikz@omino}%
\addtocounter{qrr@tikz@omino@up}{-1}%
\pgfkeysalso{/tikz/insert path={
to[/tikz/omino/how] ++(down:#1)
node[/tikz/omino/nodes/.try,/tikz/omino/node normal/.try,/tikz/omino/node down/.try]{\qrr@tikz@omino@text@down}}},
omino/l/.code=%
\stepcounter{qrr@tikz@omino}%
\addtocounter{qrr@tikz@omino@right}{-1}%
\pgfkeysalso{/tikz/insert path={
to[/tikz/omino/how] ++(left:#1)
node[/tikz/omino/nodes/.try,/tikz/omino/node normal/.try,/tikz/omino/node left/.try]{\qrr@tikz@omino@text@left}}},
omino/r/.code=%
\stepcounter{qrr@tikz@omino}%
\stepcounter{qrr@tikz@omino@right}%
\pgfkeysalso{/tikz/insert path={
to[/tikz/omino/how] ++(right:#1)
node[/tikz/omino/nodes/.try,/tikz/omino/node normal/.try,/tikz/omino/node right/.try] {\qrr@tikz@omino@text@right}}},
omino/u/.default=\pgfkeysvalueof{/tikz/omino/distance},
omino/d/.default=\pgfkeysvalueof{/tikz/omino/distance},
omino/l/.default=\pgfkeysvalueof{/tikz/omino/distance},
omino/r/.default=\pgfkeysvalueof{/tikz/omino/distance},
omino/how/.style=,
omino/reset/.code=
\pgfutil@in@_{#1}%
\ifpgfutil@in@
\qrr@tikz@omino@split#1\relax
\else
\edef\pgf@tempa{\csname qrr@tikz@omino@coords@#1\endcsname}%
\expandafter\qrr@tikz@omino@split\pgf@tempa\relax
\fi
\pgfkeysalso{/tikz/insert path={(omino-n-#1.center) node[/tikz/omino/nodes/.try, /tikz/omino/node reset/.try] {\qrr@tikz@omino@text@reset}}},
omino/do/.code={\@tfor\@next:=#1\do{\pgfkeysalso{/tikz/omino/\@next}}},
omino/node reset/.style={draw=none,fill=none},
omino/node normal/.style={
name=omino-n-\number\c@qrr@tikz@omino,
alias=omino-n-\number\c@qrr@tikz@omino@right_\number\c@qrr@tikz@omino@up,
omino/@store coords
},
omino/@store coords/.code=
\expandafter\xdef\csname qrr@tikz@omino@coords@\arabic{qrr@tikz@omino}\endcsname
{\number\c@qrr@tikz@omino@right_\number\c@qrr@tikz@omino@up},
omino/Text/.code 2 args=\expandafter\edef\csname qrr@tikz@omino@text@#1\endcsname{#2},
omino/Text={up}{},omino/Text={down}{},omino/Text={left}{},omino/Text={right}{},omino/Text={start}{},omino/Text={reset}{}
}
\def\qrr@tikz@omino@split#1_#2\relax{\setcounter{qrr@tikz@omino@right}{#1}\setcounter{qrr@tikz@omino@up}{#2}}
\tikzset{
omino/x mirror/.style={/tikz/cm={-1,0,0,1,(0,0)}},
omino/y mirror/.style={/tikz/cm={1,0,0,-1,(0,0)}}
}
\tikzset{fun/.code={\pgfmathtruncatemacro\@fun{\number\c@qrr@tikz@omino/4*100}\pgfkeysalso{fill=blue!\@fun!red}}}
\makeatother
\tikzset{
tetris/.style={/tikz/tetris/.cd,#1},
tetris/1/.style={/tikz/omino={do=suuu}},
tetris/2/.style={/tikz/omino={do=suur}},
tetris/2'/.style={/tikz/omino/x mirror, 2},
tetris/3/.style={/tikz/omino={do=suru}},
tetris/3'/.style={/tikz/omino/x mirror, 3},
tetris/4/.style={/tikz/omino={do=surd}},
tetris/5/.style={/tikz/omino={s,u,u,reset=1,r}}
}
\makeatletter
\makeatother
\newcommand*{\thesamepictureeverywhere}{\matrix[column sep=.5cm, row sep=.5cm, ampersand replacement=\&] {
\path [tetris=1]; \&
\path [tetris=2']; \& \path [tetris=2]; \\
\path [tetris=3]; \& \path [tetris=3']; \&
\path [tetris=4]; \&
\path [tetris=5];\\};}
\begin{document}
\begin{tikzpicture}[
every path/.style=draw,
omino/how/.style={bend left},
omino/nodes/.style={circle, inner sep=+0pt, minimum size=+4pt, fill=black, outer sep=+0pt}]
\thesamepictureeverywhere
\end{tikzpicture}
\begin{tikzpicture}[omino/nodes/.style={rectangle, inner sep=+0pt, minimum size=+1cm, draw}]
\thesamepictureeverywhere
\end{tikzpicture}
\begin{tikzpicture}[omino={
nodes/.style={circle, inner sep=+0pt, minimum size=+1cm, draw},
Text={left}l,Text={right}r,Text={up}u,Text={down}d,Text={start}s
}]
\thesamepictureeverywhere
\end{tikzpicture}
\begin{tikzpicture}[omino/nodes/.style={shape=circle, inner sep=+0pt, minimum size=+1cm, fun}]
\thesamepictureeverywhere
\end{tikzpicture}
\tikzset{
tetris/1/.prefix style={/tikz/omino/nodes/.append style={fill=black,text=white}},
tetris/2/.prefix style={/tikz/omino/nodes/.append style={fill=blue}},
tetris/3/.prefix style={/tikz/omino/nodes/.append style={fill=green!70!blue}},
tetris/4/.prefix style={/tikz/omino/nodes/.append style={fill=yellow!80!black}},
tetris/5/.prefix style={/tikz/omino/nodes/.append style={fill=red!70!black}},
omino/Text={start}{.}
}
\begin{tikzpicture}[omino/nodes/.style={shape=rectangle, rounded corners, inner sep=+0pt, minimum size=1cm-2\pgflinewidth}]
\path [tetris=1];
\path [omino/at=0:1] [tetris=2];
\path [omino/at=0:2] [tetris=3];
\path [omino={at=0:3, rotate=-90, x mirror}][tetris=5];
\path [omino={at={5,1}, rotate=-90}][tetris=3];
\path [omino={at={5,2}, rotate=-90}][tetris=2];
\path [omino={at={4,2}, x mirror}][tetris=5];
\path [omino={at={1,3}}][tetris=4];
\end{tikzpicture}
\end{document}
Output 1
Code 2
\documentclass[tikz,border=2pt,convert=false]{standalone}
\usetikzlibrary{matrix}
\makeatletter
\tikzset{
omino/.style={/tikz/omino.cd,#1},
omino/row sep/.initial=1cm,
omino/column sep/.initial=1cm}
\newcounter{qrr@tikz@omino@y}
\newcounter{qrr@tikz@omino@x}
\def\qrr@tikz@omino@empty{\stepcounter{qrr@tikz@omino@x}}
\def\qrr@tikz@omino@full{%
\stepcounter{qrr@tikz@omino@x}
\node[
every omino node/.try,
every omino row \number\c@qrr@tikz@omino@y/.try,
every omino column \number\c@qrr@tikz@omino@x/.try,
every omino cell \number\c@qrr@tikz@omino@x-\number\c@qrr@tikz@omino@y/.try,
at={(\c@qrr@tikz@omino@x*\pgfkeysvalueof{/tikz/omino/column sep},\c@qrr@tikz@omino@y*\pgfkeysvalueof{/tikz/omino/row sep})}
]{};}
\def\qrr@tikz@omino@nextrow{\setcounter{qrr@tikz@omino@x}{0}\stepcounter{qrr@tikz@omino@y}}
\def\qrr@tikz@omino@final{\endgroup\@gobble}
\def\qrr@omino{%
\afterassignment\qrr@@omino\let\qrr@next@token=}
\def\qrr@@omino{%
\let\qrr@next\relax
\ifx\qrr@next@token.%
\let\qrr@next\qrr@tikz@omino@empty
\else
\ifx\qrr@next@token*%
\let\qrr@next\qrr@tikz@omino@full
\else
\ifx\qrr@next@token:
\let\qrr@next\qrr@tikz@omino@nextrow
\else
\ifx\qrr@next@token;
\let\qrr@next\qrr@tikz@omino@final
\fi
\fi
\fi
\fi
\qrr@next\qrr@omino
}
\newcommand*{\omino}[1][]{\begingroup\tikzset{#1}\setcounter{qrr@tikz@omino@x}{0}\setcounter{qrr@tikz@omino@y}{0}\qrr@omino}
\makeatother
\tikzset{every omino node/.style={circle, inner sep=+0pt, minimum size=+1cm}}
\begin{document}
\begin{tikzpicture}[every omino node/.append style={rectangle, fill,draw}]
\matrix[column sep=.5cm]{
\omino *:*:*:*; & \omino **:*:*; & \omino *:**:*; & \omino .*:**:*; \\};
\end{tikzpicture}
\begin{tikzpicture}[
every omino row 0/.style={fill=blue},
every omino row 1/.style={fill=blue!33!red},
every omino row 2/.style={fill=blue!67!red},
every omino row 3/.style={fill=red}]
\matrix[column sep=.5cm]{
\omino *:*:*:*; & \omino **:*:*; & \omino *:**:*; & \omino .*:**:*; \\};
\end{tikzpicture}
\end{document}
Output 2
\documentclass{article}
\makeatletter
\def\omino#1{{%
\unitlength10\p@
\@tempcnta\z@
\@tempcntb\@ne
\count@\z@
\xomino#1\relax
\fbox{\begin{picture}(\@tempcnta,\@tempcntb)(0,-\@tempcntb)%
\@tempcnta\z@
\@tempcntb\@ne
\count@\z@
\xxomino#1\relax
\end{picture}}%
}%
}
\def\xomino#1{%
\ifx\relax#1%
\else
\ifx\\#1%
\ifnum\count@>\@tempcnta \@tempcnta\count@\fi
\advance\@tempcntb\@ne
\count@\z@
\else
\advance\count@\@ne
\fi
\expandafter\xomino
\fi}
\def\xxomino#1{%
\ifx\relax#1%
\else
\ifx\\#1%
\advance\@tempcntb\@ne
\count@\z@
\else
\advance\count@\@ne
\ifx*#1%
\put(\count@,-\@tempcntb){\kern-10pt\rule{10pt}{10pt}}%
\fi
\fi
\expandafter\xxomino
\fi}
\makeatother
\begin{document}
\omino{
*\\
*\\
*\\
*\\
*}
\omino{
**\\
.*\\
.*\\
.*}
\omino{
**\\
*\\
*\\
**}
\end{document}
David's solution converts ascii art into graphics. Here is a derived version that does a similar trick.
\documentclass{article}
\usepackage{color}
\newdimen\omsq \omsq=20pt
\newdimen\omrule \omrule=2pt
\newdimen\omint
\newif\ifvth \newif\ifhth \newif\ifomblank
\def\OMINO#1{%
\vthtrue \hthtrue
\vbox{ \offinterlineskip\parindent=0pt \OM#1\relax\vskip1pt}}
\def\OM#1{%
\omint=\omsq \advance\omint-\omrule
\ifx\relax#1%
\else
\ifx\\#1 \newline\null \hthtrue \ifvth\vthfalse\else\vskip-\omrule\vthtrue\fi
\else%
\ifx .#1\hskip\ifhth \omrule\else \omint\fi
\else%
\ifx +#1\def\colour{black}\fi%
\ifx -#1\def\colour{black}\fi%
\ifx |#1\def\colour{black}\fi%
\ifx @#1\def\colour{black}\fi%
\ifx r#1\def\colour{red}\fi%
\ifx g#1\def\colour{green}\fi%
\ifx b#1\def\colour{blue}\fi%
\ifx y#1\def\colour{yellow}\fi%
\ifx m#1\def\colour{magenta}\fi%
\ifx c#1\def\colour{cyan}\fi%
\textcolor{\colour}{\rule{\ifhth\omrule\else\omsq\fi}{\ifvth\omrule\else\omsq\fi}}%
\ifhth\else\hskip -\omrule\fi%
\fi%
\ifhth\hthfalse\else\hthtrue\fi%
\fi%
\expandafter\OM%
\fi}
\makeatother
\begin{document}
\OMINO{
+-+-----+\\
|g|@|r.r|\\
|.+-+.+-+\\
|g.g|r|.|\\
+-+.|.|.|\\
|c|g|r|.|\\
|.+-+-+.|\\
|c.c.c|.|\\
+-----+-+
}
\OMINO{
+-+.......+-----+\\
|.|.......|r.r.r|\\
|.+-+-----+---+.|\\
|...|y.y.y.y.y|r|\\
+-+.+-+-----+-+.|\\
..|...|.....|r.r|\\
..+---+.....+---+
}
\end{document}