diff --git a/slides/content/ai.tex b/slides/content/ai.tex index 42ea641ed93ba54ccfaf64dc064da28b0d6e95b9..23413c06eab3828c0f5ec18c1c3aa42e48055242 100644 --- a/slides/content/ai.tex +++ b/slides/content/ai.tex @@ -23,7 +23,7 @@ \end{frame} \begin{frame}{Artificial Intelligence} - \begin{itemize} + \begin{itemize}[<+->] \item Production Rule Agents \item Monte-Carlo Tree Search \item Genetic Algorithms @@ -31,21 +31,18 @@ \end{itemize} \end{frame} -\begin{frame}[fragile]{Production Rule Agents} +\section{Production Rule Agents} + +\begin{frame}[fragile]{Basic} \begin{minted}[breaklines,tabsize=2,fontsize=\footnotesize]{Java} @FunctionalInterface -public interface Rule -{ - -default boolean canFire(int playerID, GameState state) -{ -return execute(playerID, state) != null; -} -Action execute(int playerID, GameState state); +public interface Rule { + boolean couldFire(int playerID, GameState state); + Action execute(int playerID, GameState state); } \end{minted} \end{frame} -\begin{frame}{Production Rule Agents} +\begin{frame}{Diagram} \begin{tikzpicture}[] \node[state,initial] (0) {\tiny Pop next rule}; \node[state] (1) [above right=of 0] {\tiny Check if fires}; @@ -60,7 +57,7 @@ Action execute(int playerID, GameState state); (2) edge [bend left] node [ below] {\tiny No} (3); \end{tikzpicture} \end{frame} -\begin{frame}{Production Rule Agents} +\begin{frame}{Hanabi} \begin{center} \includegraphics[scale=0.175]{hanabiBuilder} \end{center} @@ -87,8 +84,331 @@ Action execute(int playerID, GameState state); } \end{block} \end{frame} +\begin{frame}[fragile]{Basic-TBS} +\begin{minted}[breaklines,tabsize=2,fontsize=\footnotesize]{Java} + +public interface ProductionRule { + +Map<UUID, Order> perform( +int playerId, +GameState state, +List<UUID> entities +); + +} +\end{minted} +\end{frame} + +\begin{frame}{Basic-TBS} + \begin{itemize}[<+->] + \item Rules now apply to \textbf{0} or more Entities + \item \textbf{Remaining} entities considered by lower rules + \item Orders generated by rules are \textbf{executed} by the rule + \begin{itemize} + \item \textbf{Simulating} their effects for other rules + \item Allows \textbf{lower} rules to make \textbf{informed} decisions + \item Is why \textbf{non-determinism} is ill-advised + \end{itemize} + \end{itemize} +\end{frame} + +\begin{frame}{Built-Ins} + \begin{itemize}[<+->] + \item Many rules are provided + \item Some complications: + \begin{itemize} + \item Rules deal with \textbf{EntityTypes} and \textbf{Actions} + \item When I write the rules, you haven't \textbf{written} them yet + \item Luckily they are \textbf{dynamically} built at \textbf{runtime} + \end{itemize} + \item I suppose we should list the included rules + \item And how to \textbf{use} them + \end{itemize} +\end{frame} + +\begin{frame}{Built-Ins} + \begin{tabularx}{\textwidth}{X X} + AttackMeleeRule & AttackRangedClosestRule \\ + AttackRangedMostDamagedRule & EnsureEntityRule \\ + Module & NoopProductionRule \\ + RandomRule & Filter\\ + & RunAwayRule \\ + RunTowardsRule & RunTowardsResource \\ + UseActionOnEntity & UseActionOnResource\\ + \end{tabularx} + Some rules are similar - Will cover them together +\end{frame} + +\begin{frame}{Rule Types} +\begin{itemize}[<+->] + \item Two main types + \begin{itemize} + \item ProductionRule + \item PerEntityRule \textit{implements} ProductionRule + \end{itemize} + \item Depends what you need to do in the rule + \item PerEntityRule is simpler + \begin{itemize} + \item Executes the orders \textbf{automatically} + \item What a \textbf{single} Entity does + \item Removes Entity from consideration for you + \end{itemize} + \note{Not all rules can be done this way - What about EnsureEntity?} +\end{itemize} +\end{frame} + +\begin{frame}{Attack Rules} + \begin{itemize}[<+->] + \item PerEntityRule + \item AttackMeleeRule, AttackRangedClosestRule,AttackRangedMostDamagedRule + \item Melee rule will also \textbf{move} unit towards target + \item Be careful: + \begin{itemize} + \item These rules do \textbf{not} check + \item They can issue an \textbf{invalid} order + \end{itemize} + \end{itemize} +\end{frame} +\begin{frame}{EnsureEntity} + \begin{block}{Example} + EnsureEntity[blue\_town:blue\_civilian:3] + \end{block} + \begin{itemize}[<+->] + \item Producer, Product, Quantity + \item Simple: + \begin{itemize} + \item Counts how many Product we have + \item Finds Producer for each missing Product + \item Issues order for Producer to build Product + \end{itemize} + \item Supports abstract types: + \item EnsureEntity[abstract\_civilian:abstract\_town:1] + \item Uses BuildOrder. + \end{itemize} +\end{frame} +\begin{frame}{Run Rules} + \begin{block}{Example} + RunTowards[0.0] \\ + RunAway[0.5] \\ + RunTowardsResource[gold] + \end{block} + \begin{itemize}[<+->] + \item Causes Entity to travel + \item \textbf{To} or \textbf{from} something + \end{itemize} +\end{frame} +\begin{frame}{Use Rules} + \begin{block}{Example} + UseActionOnResource[BuildOnResource[gold\_mine:gold]:gold] + \end{block} + \begin{itemize}[<+->] + \item Causes Entity to use an Action on either: + \begin{itemize} + \item Another Entity + \item A resource + \end{itemize} + \item Great for building mines + \item Great for supporting custom actions. + \item Attack actions could have been written with this + \item But they predate this + \end{itemize} +\end{frame} + +\begin{frame}{Filter Rules} + \begin{block}{Example} + Filter[AttackMelee:abstract\_knight] + \end{block} + \begin{itemize}[<+->] + \item PerEntityRule + \item PerEntityRule usually consults \textbf{every} Entity + \item This doesn't \textbf{usually} make sense + \item Rather than write \textbf{conditions} on other rules + \item \textbf{Wrap} rules with this condition + \item Takes 1 or more type as an array + \end{itemize} +\end{frame} + +\begin{frame}{Custom Rules} + \begin{itemize}[<+->] + \item These are largely designed for civ style games + \item Great news if you have made one + \item Less than great news if your game is radically different + \item You'll need to \textbf{provide} new rules + \begin{itemize} + \item Same way you did for Actions + \item Dynamically scanned at runtime + \end{itemize} + \end{itemize} +\end{frame} + +\begin{frame}{Production Rule Agents} +"RangedRush":"PRA[EnsureBase,EnsureWorker,EnsureArchery,BuildGoldMine,BuildWoodMine,EnsureEntity[abstract\_civilian:farm:3],TravelToGold,TravelToWood,EnsureArcher,ArcherAttack,ArcherChase,WorkerEvade]", +\end{frame} + +\begin{frame}{Production Rule Agents} + \begin{itemize}[<+->] + \item That was a lot in one line + \item \textbf{Sorry}, but that is how it is + \item These do tend to be quite in-flexible. + \item More on that later + \end{itemize} +\end{frame} + +\section{Genetic Algorithms} + +\begin{frame}{Genetic Algorithms} + \begin{itemize}[<+->] + \item Powerful algorithms for variety of uses + \item Can even \textbf{play} games + \item Apologies to those that have encountered GA's + \item Even more apologies to those that have encountered RHEA's + \end{itemize} +\end{frame} + +\begin{frame}{Genetic Algorithms} + +\begin{tikzpicture} +\node[box](init) at (-1, 0){Initial \\ Population}; +\node[box](decode) at (2, 0){Decode \\ Population}; +\node[box](fitness) at (5, 0){Calculate \\ Fitness}; +\node[box](selection) at (8, 0){Selection}; +\node[box](cross) at (8, -2.5){Crossover}; +\node[box](mutate) at (8, -5){Mutation}; +\node[box](newPop) at (2, -5){New Population}; + +\path[->] +(init) edge [] node [] {} (decode) +(decode) edge [] node [] {} (fitness) +(fitness) edge [] node [] {} (selection) +(selection) edge [] node [] {} (cross) +(cross) edge [] node [] {} (mutate) +(mutate) edge [] node [] {} (newPop) +(newPop) edge [] node [] {} (decode) +; +\end{tikzpicture} +\end{frame} + +\begin{frame}{Genetic Algorithms} + \begin{itemize}[<+->] + \item You \textbf{all} have some experience using these + \item Asteroids assignment had one built in + \item But how to play a game with a GA? + \end{itemize} +\end{frame} + +\begin{frame}{Simpler Games} + \begin{columns} + \begin{column}{0.4\textwidth} + \begin{itemize}[<+->] + \item Consider this game + \item More like a maze + \item Get each Agent to the goal + \item 5 possible moves + \item Controller returns a single move per turn + \end{itemize} + \end{column} + \begin{column}{0.6\textwidth} + \begin{center} + \includegraphics[scale=0.45]{level1e} + \end{center} + \end{column} + \end{columns} +\end{frame} + +\begin{frame}{GA for Simple Game} + \begin{itemize}[<+->] + \item Given a time budget + \item Spend it evolving ``plans'' + \item Plan is a sequence of possible actions + \item Simulate the plan and evaluate resultant state for score + \item Sound like a possible GA? + \item This is called a Rolling Horizon Evolutionary Algorithm + \end{itemize} +\end{frame} + +\begin{frame}{Boosting the horizon} + \begin{itemize}[<+->] + \item RHEA is quite jerky in games + \item Macro Actions can solve this + \item Locking the agent to consider each move $N$ times + \item Means you can think for $N$ turns + \item Works great in real-time engines like PTSP + \item Getting $N$ wrong means poor performance + \end{itemize} +\end{frame} + +\begin{frame}{Problem with Macro Actions} + \begin{columns} + \begin{column}{0.4\textwidth} + \begin{itemize}[<+->] + \item What if $N$ is 2? + \item Can we reach the Goal? + \item MacroActionGA is poor at discrete boards + \end{itemize} + \end{column} + \begin{column}{0.6\textwidth} + \begin{center} + \includegraphics[scale=0.45]{level1e} + \end{center} + \end{column} + \end{columns} +\end{frame} + +\begin{frame}{Solution} + \begin{itemize}[<+->] + \item What if $N$ wasn't fixed? + \item What if $N$ wasn't the same for each action? + \item Learn the values for $N$ as well as the actions + \item Include them in the GA + \end{itemize} + + \begin{center} + \includegraphics[height=0.5\textheight]{level1E-txt-pairs-ticks} + \end{center} +\end{frame} + +\begin{frame}{More complex games} + \begin{itemize}[<+->] + \item This is great for simple games + \item More complex games are too large + \item Action space in our game is huge! + \item Macro actions don't make sense either! + \item Need something \textbf{higher} level + \end{itemize} +\end{frame} + +\begin{frame}{Strategy Search} + \begin{itemize}[<+->] + \item Instead of choosing actions + \item Choose between \textbf{strategies} + \item But where will we get those? + \end{itemize} +\end{frame} + +\begin{frame}[fragile]{Strategy Search} +\begin{minted}[breaklines,tabsize=2,fontsize=\footnotesize]{Java} + Map<EntityType, List<ProductionRuleAgent>> rules; +\end{minted} + +\begin{itemize}[<+->] + \item Choose between PRA's for each \textbf{EntityType} + \item Why not per Entity? +\end{itemize} +\end{frame} + +\begin{frame}{Variable Length Macro Action GA} +"MedievalGA":"VLMAGA[1000:10:EandM:abstract\_civilian,abstract\_town,abstract\_knightery,abstract\_archery,abstract\_knight,abstract\_archer:noopRule/ResourceBuilder/BuildBase/BuildMilitary,noopRule/BuildWorker,noopRule/BuildKnights,noopRule/BuildArchers,KnightAttack,ArcherAttack:noop:RangedRush]" + \begin{itemize}[<+->] + \item Will do automatic single actions first + \item Then will follow its learned policy + \item Then will use the fallback agent for the rest + \end{itemize} +\end{frame} + +\begin{comment} +\section{Monte-Carlo Tree Search} \begin{frame}[fragile]{Monte-Carlo Tree Search} \begin{center} \begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 5cm/#1, @@ -125,27 +445,5 @@ Action execute(int playerID, GameState state); \end{itemize} \end{frame} -\begin{frame}{Genetic Algorithms} - - \begin{tikzpicture} - \node[box](init) at (-1, 0){Initial \\ Population}; - \node[box](decode) at (2, 0){Decode \\ Population}; - \node[box](fitness) at (5, 0){Calculate \\ Fitness}; - \node[box](selection) at (8, 0){Selection}; - \node[box](cross) at (8, -2.5){Crossover}; - \node[box](mutate) at (8, -5){Mutation}; - \node[box](newPop) at (2, -5){New Population}; - - \path[->] - (init) edge [] node [] {} (decode) - (decode) edge [] node [] {} (fitness) - (fitness) edge [] node [] {} (selection) - (selection) edge [] node [] {} (cross) - (cross) edge [] node [] {} (mutate) - (mutate) edge [] node [] {} (newPop) - (newPop) edge [] node [] {} (decode) - ; - \end{tikzpicture} -\end{frame} - +\end{comment} \end{document} diff --git a/slides/images/level1E-txt-pairs-ticks.png b/slides/images/level1E-txt-pairs-ticks.png new file mode 100644 index 0000000000000000000000000000000000000000..9ecab62ad9d580b3d84ff634c8db927f9ad64d1f Binary files /dev/null and b/slides/images/level1E-txt-pairs-ticks.png differ diff --git a/slides/images/level1e.png b/slides/images/level1e.png new file mode 100644 index 0000000000000000000000000000000000000000..1b34f40490e77bd9d522b646fa4bc4d2881384d2 Binary files /dev/null and b/slides/images/level1e.png differ