|
Künstliche Intelligenz - Teil3 |
Top Previous Next |
|
In diesem Monat werden wir den KI Code weiter verbessen und so unserem Bot ein wenig mehr menschenähnliches Verhalten beibringen. Als erstes richten wir unser Augenmerk auf das Sichtfeld, den sichtbaren Bereich oder wie auch immer Sie es nennen wollen. Ackbot wird dadurch menschlicher, dass er ignoriert, was er nicht direkt “sehen” kann. Das heißt, wir sollten in der Lage sein, uns von hinten an ihn anzuschleichen ohne entdeckt zu werden; glücklicherweise kann man dies sehr einfach mit c_scan erreichen.
Falls Sie vergessen haben sollten wie diese Anweisung funktioniert, es gibt einen eigenen c_scan Workshop in AUM 54. Aber Sie als mein treuer Schüler können natürlich sofort weiterlesen ohne diesen Workshop erneut konsultieren zu müssen.
Hier ist der Code aus der vorigen KI-Version.
Beachten Sie die grün gefärbte Zeile; diese sagt dem Bot, dass er den Spieler angriefen soll, sobald dieser näher als 1000 Quants ist. Sehen wir uns an, was sich geändert hat.
Wir haben eine Codezeile hinzugefügt, die überprüft ob c_scan einen Wert größer als 0 zurückliefert oder nicht. Das Handbuch verrät uns, dass c_scan genau dann einen Wert größer als 0 liefert, wenn die Anweisung eine Entity entdeckt hat. Falls diese Entity der Spieler ist (you == player), dann wird Ackbot angreifen.
Durch welche Werte wird das Sichtfeld festgelegt? Modifizieren Sie den Vektor (120, 60, 1000) bis Sie mit dem Ergebnis zufrieden sind; Sie kennen solche Bilder schon, aber ich habe noch eines gemacht, damit Sie schneller loslegen können.
Das war doch nicht allzu kompliziert oder? Kommen wir nun zu etwas noch Interessanterem: Vermeidung von Hindernissen. Wie Sie wissen habe ich dem Level einige Blocks hinzugefügt, weil ich Ackbots Fähigkeiten, diese zu vermeiden demonstrieren wollte. Wenn wir dafür keinen Code schreiben, können wir kaum davon ausgehen, dass unser Bot auf zauberhafte Weise die Fähigkeit erhält, diesen Hindernissen von selbst auszuweichen. Die einzigen “zauberhaften” Effekte beim Programmieren sind Bugs, die unerklärlicherweise aus dem Nichts kommen, aber das ist eine andere Geschichte...
Wir werden keine komplexen Path-Finding Algorithmen implementieren, aber der fertige Code sollte es Ackbot ermöglichen, diverse Hindernisse zu umgehen; hier ist die Draufsicht des Testlevels, den ich für die Demo verwende.
Zunächst sollte der Bot die Umgebung wahrnehmen können; er braucht Sensoren, die es ihm erlauben zu “sehen”, was vor ihm liegt. Ich habe zwei lokale Variablen namens “content_right” und “content_left” definiert, die genau das leisten.
Schauen wir uns nochmal den Angriffs-Code aus dem Workshop vom letzten Mal an:
Der Code ist recht simpel: wenn der Status auf “Angriff” steht, dreht sich der Bot die ganze Zeit in Richtung Spieler. Das heißt aber auch, dass der Bot einem Block, der zwischen ihn und den Spieler gerät nicht ausweichen kann, wenn er nicht daran entlang gleitet. Der neue Code läßt den Bot etwas schlauer agieren.
Sehen Sie? Der Bot ist viel intelligenter geworden und das mit ungefähr zehn Codezeilen.
if (my.status == attacking) // shooting at the player? { // the road is clear? then rotate the enemy towards the player if (c_content (content_right.x, 0) + c_content (content_left.x, 0) == 2) { vec_set(temp, player.x); vec_sub(temp,my.x); vec_to_angle(my.pan, temp); // turn the enemy towards the player }
Zunächst sollten wir klären, was c_content leistet, eine Anweisung, die den Inhalt (empty, passable oder solid) einer bestimmten Position im Level testet. Die Definition ist simpel:
c_content (position, mode);
- “position” ist der Vektor, an dessen Position geprüft werden soll; - “mode” ist der Modus für c_content; nehmen Sie dort einfach 0.
Die Anweisung wird den Wert 1 zurückliefern, wenn “position” im leeren Raum liegt, eine “2”, wenn der Ort in einem passierbaren Block ist und 3, wenn “position” in einem festen Block ist.
Ackbot bekommt seine “content_right” und “content_left” Sensoren wir im unteren Bild gezeigt.
Jeder Sensor ist 50 Quants vor dem Bot und 20 Quants zur Seite (links und rechts), sowie 15 Quants unter seinem Origin plaziert. Wir haben vec_rotate bereits in AUM 54 kennengelernt, hier ist eine kurze Erklärung.
vec_set(content_right, vector(50, -20, -15)); vec_rotate(content_right, my.pan); vec_add(content_right.x, my.x);
Die erste Codezeile bestimmt den korrekten Offset für content_right und die folgenden Zeilen richten die Position je nach Ackbots Pan und Position aus, damit die richtige Position relativ zum Bot ermittelt wird. Schauen wir uns den Code für den Bot nochmal an.
Wenn der Bot angreift und der Inhalt der Sensoren 1 + 1 = 2 ergibt (an beiden Position leerer Raum), dann dreht sich Ackbot in Richtung des Spielers, wie zuvor auch. Falls mindestens einer der Sensoren einen Block ermittelt (Level Block oder eine WMB Entity), dann dreht sich der Bot mit einer Geschwindigkeit von 5 * time, um dem Hindernis auszuweichen. Sehen Sie sich das folgende Bild an.
Ob Sie es glauben oder nicht, die KI-Serie ist beendet. Wir haben nun eine anständige und erweiterbare KI, aber vor allem haben wir etwas über endliche Automaten gelernt und werden diese Information in zukünftigen Projekten anwenden können. Bis nächsten Monat dann!
|