Ich entwickle einen Klon des Bomberman-Spiels und experimentiere mit verschiedenen Arten von KI. Zuerst habe ich mit A * den Zustandsraum durchsucht und jetzt möchte ich einen anderen Ansatz mit dem Minimax-Algorithmus ausprobieren. Mein Problem ist, dass jeder Minimax-Artikel, den ich gefunden habe, Spieler abwechselt. Aber in Bomberman macht jeder Spieler gleichzeitig eine Aktion. Ich denke, ich könnte alle möglichen Zustände für einen Spiel-Tick generieren, aber mit vier Spielern und 5 Grundaktionen (4 Züge und Bombenplatz) gibt es 5 ^ 4 Zustände auf der ersten Ebene des Spielbaums. Dieser Wert steigt mit jedem nächsten Level exponentiell an. Vermisse ich etwas Gibt es Möglichkeiten, es zu implementieren, oder sollte ich einen völlig anderen Algorithmus verwenden? Vielen Dank für alle Vorschläge
11
Antworten:
Echtzeit-Strategiespiele wie Bomber Man haben es schwer mit KI. Sie möchten, dass es intelligent ist, aber gleichzeitig kann es nicht perfekt sein.
Wenn die KI perfekt ist, werden Ihre Spieler frustriert sein. Entweder weil sie immer verlieren oder Sie erhalten 0,3 Bilder pro Sekunde.
Wenn es nicht intelligent genug ist, werden sich Ihre Spieler langweilen.
Meine Empfehlung ist, zwei KI-Funktionen zu haben, eine, die bestimmt, wohin die KI geht, die andere, die bestimmt, wann eine Bombe am besten abgeworfen werden kann. Mithilfe von Bewegungsvorhersagen können Sie feststellen, ob sich ein Feind auf einen Punkt zubewegt, der gefährlich ist, wenn eine Bombe am aktuellen Standort abgeworfen wird.
Je nach Schwierigkeitsgrad können Sie diese Funktionen ändern, um den Schwierigkeitsgrad zu verbessern oder zu verringern.
quelle
Wie Sie bemerkt haben, ist Bomberman viel zu komplex, um als rundenbasiertes Spiel simuliert zu werden. Eine mögliche eigene Entscheidung und jede mögliche Entscheidung eines anderen Spielers zu extrapolieren, funktioniert einfach nicht.
Stattdessen sollten Sie eher einen strategischeren Ansatz wählen.
Sie sollten sich fragen: Wie trifft ein menschlicher Spieler Entscheidungen, während er Bomberman spielt? Normalerweise sollte ein Spieler vier grundlegende Prioritäten befolgen:
Die erste Priorität kann durch die Erstellung einer "Gefahrenkarte" erfüllt werden. Wenn eine Bombe platziert wird, sollten alle von ihr bedeckten Kacheln als "gefährlich" gekennzeichnet werden. Je früher die Bombe explodiert (Kettenreaktionen im Auge behalten!), Je höher die Gefahr. Immer wenn die KI bemerkt, dass sie sich auf einem Feld mit hoher Gefahr befindet, sollte sie sich entfernen. Wenn ein Pfad (aus welchem Grund auch immer) gezeichnet wird, sollten Felder mit einer hohen Gefährdungsstufe vermieden werden (kann implementiert werden, indem ihnen künstlich höhere Pfadkosten hinzugefügt werden).
Die Berechnung der Gefahrenkarte kann weiter verbessert werden, um die KI vor dummen Entscheidungen zu schützen (z. B. beim Betreten von Bereichen, denen man nur schwer entkommen kann, wenn sich ein anderer Spieler in der Nähe befindet).
Dies sollte bereits eine vernünftige defensive KI schaffen. Was ist also mit Beleidigung?
Wenn die KI erkennt, dass sie momentan einigermaßen sicher ist, sollte sie offensive Manöver planen: Sie sollte überlegen, wie sie die Gefahrenkarte um die anderen Spieler erhöhen kann, indem sie selbst Bomben platziert. Bei der Auswahl eines Ortes, an dem eine Bombe gepflanzt werden soll, sollten nahe gelegene Orte bevorzugt werden, damit sie sich nicht so weit bewegen müssen. Bombenstandorte sollten ebenfalls ignoriert werden, wenn die resultierende Gefahrenkarte keinen angemessenen Fluchtweg zulässt.
quelle
Richtig! Sie müssen alle 5 ^ 4 (oder sogar 6 ^ 4, da Sie in 4 Richtungen gehen, anhalten und "eine Bombe legen"?) Aktionen für jeden Spieltick suchen. ABER wenn sich ein Spieler bereits für einen Zug entschieden hat, dauert es einige Zeit, bis der Zug ausgeführt wird (z. B. 10 Spiel-Ticks). Während dieser Zeit verringert sich die Anzahl der Möglichkeiten.
Sie können eine Hash-Tabelle verwenden, um denselben Spielstatus "Teilbaum" nur einmal zu berechnen. Stellen Sie sich vor, Spieler A geht auf und ab, während alle anderen Spieler "warten", landen Sie im selben Spielzustand. Es ist das gleiche wie für "links-rechts" oder "rechts-links". Auch das Verschieben von "nach oben, dann nach links" und "nach links, dann nach oben" führt zum gleichen Zustand. Mit einer Hash-Tabelle können Sie die berechnete Punktzahl für einen bereits ausgewerteten Spielstatus "wiederverwenden". Dies reduziert die Wachstumsgeschwindigkeit erheblich. Mathematisch reduziert es die Basis Ihrer exponentiellen Wachstumsfunktion. Um eine Vorstellung davon zu bekommen, um wie viel sich die Komplexität verringert, betrachten wir die Bewegungen, die nur für einen Spieler möglich sind, im Vergleich zu erreichbaren Positionen auf der Karte (= verschiedene Spielzustände), wenn sich der Spieler nur nach oben / unten / links / rechts / anhalten bewegt .
Tiefe 1: 5 Züge, 5 verschiedene Zustände, 5 zusätzliche Zustände für diese Rekursion
Tiefe 2: 25 Züge, 13 verschiedene Zustände, 8 zusätzliche Zustände für diese Rekursion
Tiefe 3: 6125 Züge, 25 verschiedene Zustände, 12 zusätzliche Zustände für diese Rekursion
Um dies zu visualisieren, antworten Sie sich selbst: Welche Felder auf der Karte können mit einem Zug, zwei Zügen, drei Zügen erreicht werden. Die Antwort lautet: Alle Felder mit einem maximalen Abstand = 1, 2 oder 3 von der Startposition.
Wenn Sie eine HashTable verwenden, müssen Sie jeden erreichbaren Spielstatus (in unserem Beispiel 25 in Tiefe 3) nur einmal auswerten. Ohne eine HashTable müssen Sie sie mehrmals auswerten, was 6125 Auswertungen anstelle von 25 in Tiefenstufe 3 bedeuten würde. Das Beste: Sobald Sie einen HashTable-Eintrag berechnet haben, können Sie ihn in späteren Zeitschritten wiederverwenden ...
Sie können auch inkrementelle Vertiefungs- und Alpha-Beta-Bereinigungs-Teilbäume verwenden, die es nicht wert sind, genauer untersucht zu werden. Beim Schach reduziert dies die Anzahl der gesuchten Knoten auf etwa 1%. Eine kurze Einführung in das Alpha-Beta-Bereinigen finden Sie hier als Video: http://www.teachingtree.co/cs/watch?concept_name=Alpha-beta+Pruning
Ein guter Anfang für weitere Studien ist http://chessprogramming.wikispaces.com/Search . Die Seite bezieht sich auf Schach, aber die Such- und Optimierungsalgorithmen sind ziemlich gleich.
Ein anderer (aber komplexer) KI-Algorithmus - der für das Spiel besser geeignet wäre - ist "Temporal Difference Learning".
Grüße
Stefan
PS: Wenn Sie die Anzahl der möglichen Spielzustände reduzieren (z. B. sehr kleine Kartengröße, nur eine Bombe pro Spieler, sonst nichts), besteht die Möglichkeit, eine Bewertung für alle Spielzustände vorab zu berechnen.
--bearbeiten--
Sie können auch offline berechnete Ergebnisse der Minimax-Berechnungen verwenden, um ein neuronales Netzwerk zu trainieren. Oder Sie können sie verwenden, um handimplementierte Strategien zu bewerten / vergleichen. Zum Beispiel könnten Sie einige der vorgeschlagenen "Persönlichkeiten" und einige Heuristiken implementieren, die erkennen, in welchen Situationen welche Strategie gut ist. Daher sollten Sie Situationen (z. B. Spielzustände) "klassifizieren". Dies könnte auch von einem neuronalen Netzwerk erledigt werden: Trainieren Sie ein neuronales Netzwerk, um vorherzusagen, welche der handcodierten Strategien in der aktuellen Situation am besten funktioniert, und führen Sie sie aus. Dies sollte zu extrem guten Echtzeitentscheidungen für ein echtes Spiel führen. Viel besser als eine Suche mit niedrigem Tiefenlimit, die sonst durchgeführt werden kann, da es nicht so wichtig ist, wie lange die Offline-Berechnungen dauern (sie sind vor dem Spiel).
- bearbeiten # 2 -
Wenn Sie Ihre besten Züge nur alle 1 Sekunde neu berechnen, können Sie auch versuchen, eine höhere Ebene zu planen. Was meine ich damit? Sie wissen, wie viele Züge Sie in 1 Sekunde ausführen können. Sie können also eine Liste der erreichbaren Positionen erstellen (z. B. wenn dies 3 Züge in 1 Sekunde wären, hätten Sie 25 erreichbare Positionen). Dann könnten Sie wie folgt planen: Gehen Sie zu "Position x und platzieren Sie eine Bombe". Wie einige andere vorgeschlagen haben, können Sie eine "Gefahren" -Karte erstellen, die für den Routing-Algorithmus verwendet wird (wie geht man zu Position x? Welcher Pfad sollte bevorzugt werden [in den meisten Fällen sind einige Variationen möglich]). Dies ist im Vergleich zu einer großen HashTable weniger speicherintensiv, führt jedoch zu weniger optimalen Ergebnissen. Da jedoch weniger Speicher benötigt wird, kann dies aufgrund von Caching-Effekten schneller sein (bessere Verwendung Ihrer L1 / L2-Speicher-Caches).
ZUSÄTZLICH: Sie können Vorsuchen durchführen, die nur Züge für jeweils einen Spieler enthalten, um Variationen zu sortieren, die zum Verlust führen. Nehmen Sie deshalb alle anderen Spieler aus dem Spiel ... Speichern Sie, welche Kombinationen jeder Spieler wählen kann, ohne zu verlieren. Wenn nur Züge verloren gehen, suchen Sie nach den Zugkombinationen, bei denen der Spieler am längsten am Leben bleibt. Um diese Art von Baumstrukturen zu speichern / verarbeiten, sollten Sie ein Array mit folgenden Indexzeigern verwenden:
Jeder Zustand hat einen Bewertungswert und wird beim Bewegen (0 = Stopp, 1 = Aufwärts, 2 = Rechts, 3 = Abwärts, 4 = Links) mit den nächsten Spielzuständen verknüpft, indem der Array-Index in "Baum" in Zügen [0 "gespeichert wird ] zu bewegen [4]. Um Ihren Baum rekursiv zu erstellen, könnte dies folgendermaßen aussehen:
Diese Art der Baumstruktur ist viel schneller, da die dynamische Zuweisung von Speicher sehr langsam ist! Das Speichern des Suchbaums ist jedoch auch ziemlich langsam ... Dies ist also eher eine Inspiration.
quelle
Würde es helfen, sich vorzustellen, dass sich jeder abwechselt?
Technisch gesehen tun sie dies im zugrunde liegenden System tatsächlich, aber da die Dinge verschachtelt und überlappt sind, scheinen sie gleichzeitig zu laufen.
Denken Sie auch daran, dass Sie AI nicht nach jedem Animationsframe ausführen müssen . Viele erfolgreiche Casual Games führen den KI-Algorithmus nur etwa einmal pro Sekunde aus und geben den KI-gesteuerten Charakteren Informationen darüber, wohin sie gehen sollen oder was sie tun sollen. Diese Informationen werden dann zur Steuerung der KI-Charaktere verwendet auf den anderen Frames.
quelle