-
Notifications
You must be signed in to change notification settings - Fork 0
/
ttt.sty
116 lines (113 loc) · 5.06 KB
/
ttt.sty
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
\ProvidesPackage{ttt}[2022/02/04 v1.0 Ticle-Die-Tacle-Die-Toe]
\RequirePackage{tikz}
\makeatletter
\newcount\c@ttt@rs
\protected\def\ttt#1{\c@ttt@rs0\leavevmode\bgroup\vb@xt@\z@\bgroup\@iterttt#1\relax}
\def\@iterttt{\afterassignment\@@iterttt\let\tmp= }
\def\@@iterttt{%
\ifx\tmp\@sptoken\egroup\ \vb@xt@\z@\bgroup\let\next\@iterttt
\else\ifx\tmp\relax\egroup\egroup\let\next\relax
\else\@curttt{\tmp}\let\next\@iterttt\fi\fi
\next}
\def\@curttt#1{%
\global\advance\c@ttt@rs1\relax
\expandafter\expandafter\expandafter\global\expandafter\let\csname ttt@\number\c@ttt@rs\endcsname=#1\relax
}
{\def\:{\global\let\tttvoid=-} \: }
{\def\:{\global\let\pOne=X} \: }
{\def\:{\global\let\pTwo=O} \: }
\def\IsWinCell#1->#2#3{\edef\tmpa{#1}\ifx\tmpa\win@a#2\else\ifx\tmpa\win@b#2\else\ifx\tmpa\win@c#2\else#3\fi\fi\fi}
\def\@tttcell@#1#2#3{\IsWinCell{#1}->{\node[@=palette#2,text=white] {#3}}{\node[@=shade#2] {#3}}}
\def\tttcell#1{\xdef\@tmp{\csname ttt@#1\endcsname}\expandafter\ifx\@tmp\tttvoid \node[@]{\color{gray}#1}\else\expandafter\ifx\@tmp\pOne\@tttcell@{#1}{B}{\pOne}\else\@tttcell@{#1}{D}{\pTwo}\fi\fi;}
\def\printscale{1}
\def\currenttttlabel{}
\def\printtt{\getwinner\@ifstar\@printtt\n@printtt}
\newcommand\n@printtt[1][]{\scalebox{\printscale}{\begin{tikzpicture}[ampersand replacement=\&,align-half-base]\@printtt[#1]\end{tikzpicture}}}
% get winner:
\newcommand\@printtt[1][]{%
\matrix[#1,@/.style={rounded corners=1pt,fill=##1,minimum size=2em},@/.default=gray!20!white,column sep=1ex,row sep=1ex] (m) {
\tttcell1 \& \tttcell2 \& \tttcell3 \\
\tttcell4 \& \tttcell5 \& \tttcell6 \\
\tttcell7 \& \tttcell8 \& \tttcell9 \\
};
\pgfinterruptboundingbox
\expandafter\ifx\win\tttvoid\ifx\currenttttlabel\@empty
\else\node[below left] at(m.south east) {\color{gray}\itshape\footnotesize\currenttttlabel};\fi
\else
\node[below left] at(m.south east) {Winner: \win};
\fi\endpgfinterruptboundingbox
}
% tokens \win
\def\getwinner{%
\global\let\win\tttvoid
\global\let\win@a\relax \global\let\win@b\relax \global\let\win@c\relax
\foreach\a/\b/\c in {1/2/3,4/5/6,7/8/9,1/4/7,2/5/8,3/6/9,1/5/9,3/5/7}{\@winsame\a\b->{\@winsame\b\c->{\xdef\win{\csname ttt@\a\endcsname}\global\let\win@a\a\global\let\win@b\b\global\let\win@c\c}}}}%
\def\@winsame#1#2->#3{\edef\@tmpa{\csname ttt@#1\endcsname}\edef\@tmpb{\csname ttt@#2\endcsname}\expandafter\expandafter\expandafter\ifx\expandafter\@tmpa\@tmpb#3\fi}%
% set #1 to #2
\newcount\c@score
\newcount\c@move
\newcount\c@curscore
\newcount\c@curmove
\def\@setc#1#2{\csname c@#1\endcsname#2\relax}
\def\step#1<-#2;{\expandafter\let\csname ttt@#1\endcsname=#2\relax}
\def\gstep#1<-#2;{\expandafter\global\expandafter\let\csname ttt@#1\endcsname=#2\relax}
% X | O
\def\tttdumpcell#1{\expandafter\ifx\csname ttt@#1\endcsname\pOne1\else\expandafter\ifx\csname ttt@#1\endcsname\pTwo2\else-\fi\fi}
\def\doBestMoveFor#1{\nextmovefor{#1}\step{\number\c@move}<-#1;}
\def\nextmovefor{\c@move0\c@score-2\relax\@nextmovefor}
\def\@nextmovefor#1{\let\@cur=#1\relax%
\getwinner% min max:
\@setc{curmove}{0}\relax
\@setc{curscore}{-2}\relax
\expandafter\ifx\win\tttvoid% no winner so far
\foreach\trymove in {1,2,3,4,5,6,7,8,9} {%
\edef\@tmp{\csname ttt@\trymove\endcsname}%
\expandafter\ifx\@tmp\tttvoid% valid move
\typeout{\tttdumpcell1 \tttdumpcell2 \tttdumpcell3^^J\tttdumpcell4 \tttdumpcell5 \tttdumpcell6^^J\tttdumpcell7 \tttdumpcell8 \tttdumpcell9}%
\typeout{trying: \trymove>}%
\begingroup
% try; is local will be erased by group
\step\trymove<-\@cur;%
\edef\@tmp{\noexpand\@nextmovefor{\ifx\@cur\pOne\pTwo\else\pOne\fi}}\@tmp
\ifnum\c@curscore>-2
\setcounter{curscore}{-\number\c@curscore}%invert on raise
\fi
% now we do have updates in \@move and \@score; score is interpreted negative
\ifnum\c@score>\c@curscore\relax
\typeout{\ifx\@cur\pOne2\else1\fi-Besting: \trymove|\number\c@curscore|\number\c@curmove|by: \number\c@score}%
\setcounter{curscore}{\number\c@score}%
\setcounter{curmove}{\trymove}%
\else
\typeout{\ifx\@cur\pOne2\else1\fi-Loosing: \trymove|\number\c@curscore|\number\c@curmove|by: \number\c@score}%
\fi
\endgroup
\fi
}%
\@setc{move}{\number\c@curmove}%
\ifnum\c@curmove=0% no move found
\@setc{score}{0}%
\else
\@setc{score}{\number\c@curscore}%
\fi
\typeout{Set: \number\c@move|with: \number\c@score || from: \number\c@curmove|\number\c@curscore}%
\else
\@setc{move}{\number\c@curmove}%
\expandafter\ifx\win\@cur % good for player
\@setc{score}{1}\relax
\else % bad for player
\@setc{score}{-1}\relax
\fi\fi
% TODO: return move
}
% #2 User with X
% #1 initial field
% \ifx\@cur\pOne\pTwo\else\pOne\fi
\newcommand\SimulateTTTPlay[3][--- --- ---]{%
\let\@cur\pOne
\ttt{#1}\printtt\foreach[count=\i]\playerDoes in {#2} {%
\edef\from{\the\numexpr#3+\i-1\relax}\relax
\onslide<\from->{\def\currenttttlabel{Player \say{\@cur}: \playerDoes}\gstep\playerDoes<-\@cur;\relax$~~\to~~$\printtt
\ifx\@cur\pOne\global\let\@cur\pTwo\else\global\let\@cur\pOne\fi}
}}
\makeatother
\endinput