
Die Realisierung der suchenden Monstern (wenn ein Monster den Spieler aus den Augen verliert, soll es anfangen nach ihm zu suchen - und zwar nicht mit den absoluten Koordinaten - das wäre einfach -, sondern mit den zuletzt bekannten) war ein einziger Alptraum!
Ich hab's mir einfacher vorgestellt.

Jetzt läuft es aber!


Gegeben sei:
Sobald ein Monster den Spieler sieht, speichert es seine Koordinaten in actor()\xSearch und actor()\ySearch. Diese Koordinaten vergisst es erst wieder, wenn es in den IDLE-Modus wechselt. Wenn jetzt der Spieler im Fog of War verschwindet, also canSee() ein #False zurückgibt, triggert der Suchmodus. Das Monster sucht so lange, bis es das gemerkte Feld erreicht. Oder halt, wenn das Monster auf seiner Suche den Spieler wieder sieht.
So sollte es ursprünglich laufen:
Im Such-Modus benutzen die Monster keine Dijkstra-Maps, sondern die aStar-Suche. Das brachte allerhand Probleme mit sich ... aStar ist super-fix, aber auch sehr streng ... man muß Situationen voraussehen und gewappnet sein ... was, wenn der Spieler auf seinem Weg eine Tür zuschlägt? Dann existiert kein Pfad mehr. Mit Dijkstra ist das kein Problem, dann wird automatisch der nächstliegende erreichbare Punkt angesteuert. Und wenn das Monster den Spieler durch eine Tür gesehen hat, und kurz darauf der Spieler diese Tür zuschlägt, dann hilft auch die Suche nach umliegenden Feldern nicht, weil diese ebenfalls hinter der Tür sind. Und im Nu hat man schönen modularen Code mit Hardcoding verunstaltet.
Ich habe verschiedene Lösungs-Ansätze probiert - der irrsinnigste beinhaltete, daß für jedes Monster, welches in den Suchmodus wechselt, eine eigene Dijkstra-Map angelegt wird. Dazu brauchte es aber einen internen Counter und eine Funktion, bzw. LinkedList, die immer die Übersicht behält, wieviele Monster gerade im Suchmodus sind, um dementsprechend das Array zu re-dimensionieren. Das war inaktzeptabel, da Dijkstra-Pfadsuche zwar extrem coole Möglichkeiten bietet, aber auch EXTREM die CPU belastet. 2,3 oder 4 Maps jeden Zug zu updaten fällt nicht ins Gewicht, darüber wird es langsam kritisch. Bzw. es wäre noch spielbar, aber die schnelle Punkt-zu-Punkt-Bewegung, auf die ich sehr stolz bin, würde wegfallen. Das wäre dann tatsächlich Schritt ... für Schritt ... für Schritt. "Zu schnell" ist mir lieber; stattdessen halte ich mir die Option offen, hinterher die Schrittgeschwindigkeit per Timer zu regulieren.
Die Lösung:
Ein guter Kompromiss: Es gibt nur eine einzige searchDijkstra()-Map! Das besondere an der searchDijkstra()-Map ist, daß diese mit Werten initialisiert wird, welche actor()-Elemente mit Kollision gänzlich ignorieren! Das hat den Effekt, daß die Dijkstra-Hotspots durch blockierende Elemente hindurch berechnet werden, also ein Monster auch bei versperrten Weg in der Lage ist, sich zumindest in der Nähe aufzuhalten (die Hotspots "leuchten" durch Wände).
Die searchDijkstra() wird NUR geupdatet, sobald ein Monster in den SEARCH-Modus wechselt oder diesen aktiv beendet (Zielpunkt/Spieler gesichtet)! Jedesmal wenn ein Monster auf die searchMap() zugreift, wird initialisiert, dann einmal durch alle Monster-actors() gecyclet (ich habe mir zu diesem Zweck ein *pointer-Array angelegt, mit dem ich schnell bestimmte actor()-Typen filtern kann), und jedes Monster, welches aktuelle xSearch,ySearch-Koordinaten hat, setzt seinen Hotspot auf die Map. Dann einmal durchrechnen, und das Ergebnis ist eine Map mit allen Hotspots, wo der Spieler kürzlich gesehen wurde; ein Monster im SEARCH-Modus wird sich automatisch den nächsten herauspicken und dort im Umkreis "gefangen" bleiben, bzw. patroullieren.