Improved AI with documentation

This commit is contained in:
Jonas Suess 2019-03-26 17:14:09 +01:00
parent bf13680e78
commit 99f5e8d59d

View file

@ -284,7 +284,55 @@ $$\Theta(n^3)$$
\section{Weitergestaltung des Spiels} \section{Weitergestaltung des Spiels}
\subsection{Computergegner} \subsection{Computergegner}
\subsubsection{Funktionsweise}
Die hier verwendete Implementation ist eine \textit{Utility Based AI}. Die Funktionalität beruht hauptsächlich auf mehreren \textit{Utility-Funktionen}, welche die Nützlichkeit einer bestimmten Aktion bewerten.
Der Computer prüft verschiedene verfügbare Züge, bestimmt jeweils deren \textit{utility} und wählt den besten aus, wobei darauf geachtet wird, dass der Zug dem Computer den größtmöglichen Vorteil und dem Gegner den größtmöglichen Nachteil verschafft.
In der ersten Runde nutzt der Computer die \texttt{evaluateState} Funktion (siehe 2.1.2), um immer die beste verfügbare Burg, in Abhängigkeit der bereits gewählten Burgen zu bestimmen.
Ab der zweiten Runde werden, falls sinnvoll, zunächst Joker gespielt und anschließend die neuen Truppen auf die Burgen verteilt, wobei mit der Funktion \texttt{utilityReinforce} bestimmt wird, welche Burgen am nötigsten Truppen brauchen.
Danach beginnt die Eroberungsphase der Runde: mithilfe der \texttt{utilityCastle}-Funktion wird die wertvollste gegnerische Burg bestimmt und angegriffen, sofern der Angriff für den Computer sinnvoll ist.
Nach jedem Angriff werden die Truppen zu den Burgen am Rand umverteilt, wobei wieder nach \textit{utility} vorgegangen wird. Die Angriffsphase geht solange, wie es noch Burgen gibt, die sinnvoll angegriffen werden können.
\subsubsection{Utility-Funktionen}
Es werden drei verschiedene Utility-Funktionen verwendet, um die Nützlichkeit einer bestimmten Aktion zu bewerten: \texttt{utilityCastle}, \texttt{utilityReinforce} und \texttt{utilityAttack}, sowie eine vierte Funktion \texttt{evaluateState}, die den gesamten Spielzustand bewertet.
Bei den ersten drei Funktionen handelt es sich um lineare Polynome der Form
\begin{center}
\begin{large}
$\sum \limits_{k=1}^{n} \alpha_k f_k$
\end{large}
\end{center}
wobei $f_k$ wiederum Funktionen sind, welche jeweils einen Aspekt der Bewertung betrachten, mehr dazu unten.
Bei den Koeffizienten $\alpha_k$ handelt es sich um um \texttt{double}-Zahlen, welche die einzelnen Funktionen gewichten. Die drei Utility-Funktionen unterscheiden sich in den jeweils betrachteten Aspekten.
Die Funktion \texttt{evaluateState} berechnet den kumulierten Wert aller Burgen für den Computer und subtrahiert einen gewichteten Wert der Burgen für den Gegner. Sie bietet also eine Möglichkeit, den gesamten Wert eines Spielzustandes zu bestimmen.
\\\\
\textbf{utilityCastle}\\\\
Diese Funktion bestimmt den "Wert" einer Burg für einen bestimmten Spieler. Hierbei fließen die Anzahl der angrenzenden eigenen und gegnerischen Burgen, die Zahl der abgehenden Kanten, die Größe des Blocks von zusammenhängenden eigenen Burgen, in dem sich die Burg befindet und weitere Parameter ein. Diese werden gewichtet und addiert, um einen heuristischen \textit{utility}-Wert zu erzeugen.
Eine Burg wird als "wertvoll" betrachtet, wenn sie an einer strategisch günstigen Position ist, und durch andere Burgen unterstützt werden kann. Dies soll dann durch einen hohen Ausgabewert ausgedrückt werden.
\\\\
\textbf{utilityReinforce}\\\\
Diese Funktion gibt an, wie sinnvoll es ist, eine bestimmte Burg mit Truppen zu versorgen. Hierbei spielen die Zahl der angrenzenden gegnerischen Burgen, die Zahl der Truppen in der Burg, der Wert der Burg und weitere Parameter eine Rolle.
Generell sollen Burgen unterstützt werden, die entweder durch viele starke gegnerische Burgen gefährdet sind, oder für einen taktischen Angriff verwendet werden können.
\\\\
\textbf{utilityAttack}\\\\
Diese Funktion gibt an, wie sinnvoll es ist, eine bestimmte gegnerische Burg anzugreifen. Hier fließen der Wert der Burg für den Computer und für den Gegner und das Truppenverhältnis von Angreifer- zu Zielburg ein.
Burgen sollten dann angegriffen werden, wenn ihre Eroberung den Gesamtspielzustand zugunsten des Computers verändert und der Angriff eine große Erfolgschance hat.
\subsubsection{Motivation und Anmerkung}
Die \textit{Utility Based AI} ist ein häufig verwendeter und erfolgreicher Ansatz zur Entwicklung von Computergegnern für Strategiespiele. Die Umsetzung ist inspiriert von Artikeln wie "\textit{An Introduction to Utility Theory}" von David Graham und "\textit{Designing AI Algorithms For Turn-Based Strategy Games}" von Ed Welch, wurde aber vollständig selbst durch Trial-And-Error implementiert und optimiert. Sie ist der \textit{Basic AI} überlegen, hat aber noch Raum für Verbesserung.
Ein möglicher Verbesserungsvorschlag wäre, den Computer mehrere Züge in die Zukunft zu planen zu lassen und somit intelligenteres, strategisches Vorgehen zu ermöglichen (beispielsweise durch Minimax und co.).
\subsection{Missionen} \subsection{Missionen}
\subsubsection{Begrenzte Rundenanzahl} \subsubsection{Begrenzte Rundenanzahl}