Algorithmus mit dem längsten Pfad für die Erzeugung eines schurkenhaften Labyrinths


10

Ich habe eine einfache gitterbasierte Karte, die aus solchen Räumen besteht (A = Eingang, B = Ausgang):

   0 1 2 3
  #########
0 # B # #####
  #########
1 # ### #
  #########
2 # # #
  # # #
3 # # #
  #########
4 # ### #
  #########
5 ### A #
  ### #
6 ### #
  #########

Und ich bin festgefahren, einen geeigneten Algorithmus zu entwickeln, um einen Türweg zwischen den Räumen zu erstellen, so dass der Spieler den größten Teil der Karte erkunden muss, bevor er den Ausgang findet.

Mit anderen Worten, ich versuche den längsten Weg von A nach B zu finden .

(Mir ist bewusst, dass dieses Problem für azyklische Graphen gelöst werden kann. In diesem Fall kann es jedoch zu Zyklen kommen.)

BEARBEITEN: Ein weiteres Beispiel, bei dem Räume mithilfe von Floodfill verbunden werden und der Ausgang als der am weitesten vom Eingang entfernte Raum ausgewählt wird:

   0 1 2 3
  #########
0 # B # #
  # # - #####
1 # | # #
  ### # #
2 ### # #
  ### - # - ###
3 # | ###
  # - #######
4 #A | #
  # # #
5 # # #
  # # #
6 # # #
  #########

Beachten Sie, dass der Pfad zum Ausgang überhaupt nicht der längste ist.


Wenn Sie den Spieler zwingen, den längsten möglichen Weg zu gehen, bauen Sie tatsächlich einen geraden Weg, der vorgibt, komplex zu sein. Das ist schlecht.
o0 '.

Es ist nicht schlecht (es ist zum Beispiel die Grundlage des Rail-Shooter-Genres), aber Sie müssen sich bewusst sein, dass Sie es tun, und den Rest Ihres Spiels so gestalten, dass es gut damit funktioniert.

Es ist auch einfacher, das Tempo des Spiels zu steuern, wenn die Levels meist linear sind. Es ist beispielsweise möglich, nach einem besonders schwierigen Monsterraum einen Aufwachraum hinzuzufügen. Wenn es keinen Hauptweg gäbe, wäre die Verteilung der Herausforderungen und Belohnungen zufällig.
Benutzer nicht gefunden

Antworten:


11

Ich denke, du machst das falsch. Der maximale Pfad in einem Diagramm mit Zyklen ist technisch undefiniert, da er unendlich ist, wenn der Zyklus zwischen Anfang und Ende liegt. Es gibt wahrscheinlich clevere Möglichkeiten, die Definition des maximalen Pfades zu erweitern / einzuschränken, aber ich denke nicht, dass dies hier der beste Ansatz ist.

Sie versuchen nicht, einen tatsächlichen langen Pfad zu modellieren (z. B. einen Roboter, der versucht, so viel Gebiet wie möglich auf einer Karte zu erkunden). Sie versuchen nur, den Spieler dazu zu bringen, viele Räume zu erkunden.

Also, machen Sie die Chance der Spieler findet der Ausgang proportional zum Prozentsatz der Karte so weit erforscht . Angenommen, es gibt X Räume auf einer Ebene, und der Spielercharakter hat Y erkundet. Wenn der Charakter das nächste Mal einen Raum betritt, platzieren Sie den Ausgang dort mit der Wahrscheinlichkeit f (Y, X). Ein triviales Beispiel für f könnte (Y * Y) / (X * X) sein - z. B. besteht für 10 Räume eine 100% ige Chance, dass der Ausgang im letzten Raum liegt, eine 81% ige Chance, dass er sich im vorletzten Raum befindet - und nur a 1% Chance, dass es im ersten Raum ist.

Sie können die Gleichung anpassen, wie Sie möchten, damit sich das Spiel richtig anfühlt, und dem Spieler möglicherweise sogar einige Fähigkeiten geben, um die Wahrscheinlichkeit zu erhöhen, dass es generiert wird. Der Schlüssel ist, erst den Ausgang zu generieren, wenn der Charakter tatsächlich den Raum betritt. Diese Methode ist auch immun gegen das Wissen der Spieler über den Dungeon-Generierungsalgorithmus. Selbst wenn der Spieler seltsame Bewegungsmuster wie den Sprung des Ritters in NetHack oder die Teleportation hat, muss er mehr Räume erkunden, um den Ausgang zu finden.

Wenn Sie den Exit statisch generieren müssen , können Sie dieselbe Idee mit einem virtuellen Charakter verwenden. Stellen Sie sich eine Flutfüllung vor, die von der Position des Charakters ausgeht und sich bei jeder Iteration einmal in einer Zelle bewegt. Der letzte Raum, der gefüllt wird, ist der Raum, in den der Ausgang gehört (tatsächlich ist die letzte Zelle, die gefüllt wird, die Zelle, in der sie am weitesten vom Spieler entfernt ist). In diesem Fall hat der Spieler jedoch mehr Informationen über den Ausgang - wenn er sich links befindet, ist es höchstwahrscheinlich rechts - und wenn er sich teleportieren kann, kann er möglicherweise tatsächlich schneller als ein normaler zufälliger Spaziergang dorthin gelangen.

Schließlich habe ich gerade ein Roguelike beendet, bei dem der Ausgang auf der anderen Seite der Karte vom Spielercharakter erzeugt wurde, und bin dann zufällig gewandert. Einige Gegenstände im Dungeon machten es auf der Karte sichtbar, auf Kosten des schnelleren Hungers. Ich habe keine Analyse durchgeführt, aber es fühlte sich definitiv so an, als müsste ich mehr von der Karte erkunden, um sie zu finden, und es gab den Levels ein einzigartiges Gefühl.


Die dynamische Erzeugung scheint eine ziemlich gute Idee zu sein, solange der Spieler es nicht bemerkt. Sonst würden sie sich ziemlich betrogen fühlen. Ich liebe die Idee der Flutfüllung.
Benutzer nicht gefunden

2
Nun, Ihr gesamter Vorschlag betrügt in gewisser Weise den Spieler. Beschuldigen Sie mich nicht, dass ich die Mathematik so verfeinert habe, dass kein Weltmodell erforderlich ist. ;) Aber du kannst Design-Tricks verwenden, um es schmackhafter zu machen - zum Beispiel wird der Ausgang a priori platziert, aber ein Schlüssel, der für die Verwendung erforderlich ist, wird in der von mir beschriebenen Methode generiert oder auf ein Monster gelegt, das erst nach Erkundung von X erscheint Räume / X-Monster töten oder die Tür öffnen erfordert das Umlegen von X-Schaltern, einen in jedem Raum usw.

Ich habe einen Floodfill-Ansatz versucht. Es verbindet jeden Raum gut und erzeugt kurze Zweige, aber es erzeugt nicht den längsten möglichen Weg zum Ausgang, selbst wenn der Ausgang der zuletzt besuchte Knoten ist (oder in meiner Implementierung der am weitesten entfernte). (Beispiel zu meiner Frage hinzugefügt)
Benutzer nicht gefunden

Ich bin jedoch alles für Labyrinthe auf Schlüssel- / Schalterbasis. Es scheint einfach einfacher zu sein, so etwas mit Bäumen zu implementieren, denn wenn Sie zwei Zweige haben, können Sie erkennen, welcher Zweig zum Ausgang führt, ihn blockieren und den Schlüssel in den anderen Zweig stecken.
Benutzer nicht gefunden

Aber ich gebe zu, dass ich falsch gedacht habe, dass es sich um ein "A to B" -Pfadfindungsproblem handelt. Mir ist klar, dass es sinnvoller ist, den Ausgang als Ergebnis des Algorithmus zu finden, als als Ziel.
Benutzer nicht gefunden

6

Eine mögliche Alternative wäre, mit Prim / Kruskal einen (maximalen?) Spanning Tree zu erstellen (um Zyklen zu eliminieren) und einen traditionellen Algorithmus für den längsten Pfad auf den Spanning Tree anzuwenden.

Ich mache mir jedoch Sorgen, dass der Spanning Tree-Algorithmus dazu neigt, Sackgassenverzweigungen zu erzeugen, die den Spieler dazu zwingen, sich ständig zurückzuziehen.

BEARBEITEN: Ergebnis der Verwendung eines Kruskal-basierten Algorithmus und Platzieren des Ausgangs am Ende des längsten Zweigs:

   0 1 2 3
  #########
0 #A | #
  # ##### - #
1 # # #
  ### #
2 ### #
  ### #
3 ### #
  ### - #####
4 # | #
  # - ##### - #
5 # ### #
  # - #######
6 # # B #
  # # - #
7 # | #
  #########

1
Ich wollte auch Primm vorschlagen :-), +1, ich denke, Backtrack ist auch ein wichtiger Teil vieler Spiele ...
siehe

2

Hier ist etwas zum Spielen:

Connect each room with a door to another room.
N = 0.75*TotalNumberOfRooms
Until (pathSize > N) {
  Use A* pathing to get a path from A to B. (G being size of room, or # of monsters)
  if (pathSize < N) remove a connection/door
  if (noPath) choose a different door/connection
  if (room.doors < 1) choose a different door/connection
}

Ich würde zufällig Türen entlang des Pfades entfernen, sonst erhalten Sie 1 Tür am Ausgang und Tonnen von Türen am Anfang.

Ich denke, das ist O(n^2)für große Karten nicht so toll.


Eine sehr elegante Lösung im Prinzip. Das nächste Mal sollte ich versuchen, mir so etwas auszudenken, bevor ich mich für verschlungene Techniken entscheide.
Benutzer nicht gefunden

Na ja, vielleicht elegant, aber es wird ein Prozessorfresser. O (n ^ 2) lässt sich mit großen Karten nicht gut skalieren.
Stephen Furlani


1

Ich glaube, Sie haben bereits gute Antworten, aber hier ist meine theoretische Lösung für das Problem in Höhe von 0,02 USD.

Was Sie wollen, ist NICHT der längste Weg, sondern der längste kürzeste Weg. Sie möchten den Raum, der am weitesten entfernt ist, vorausgesetzt, Sie erwägen den kürzesten Weg zum Raum. Das klingt wahrscheinlich verwirrend, ist aber sehr einfach zu berechnen.

  1. Beginnen Sie in Ihrem Startraum. Markieren Sie jeden seiner Nachbarn 1. Sie sind Abstand 1 vom Startraum entfernt.
  2. Besuchen Sie für jeden mit 1 gekennzeichneten Raum jeden seiner UNMARKED-Nachbarn und markieren Sie ihn mit 2. Sie sind 2 Abstände vom Start entfernt.
  3. Fahren Sie fort, bis Sie alle Räume abgedeckt haben. Der Raum mit der maximalen Anzahl ist vom Start am weitesten entfernt.

Das Berechnen eines tatsächlich längsten Pfades (dauert nicht zu lange für beispielsweise 10 Räume) funktioniert nicht, da Sie den Spieler nicht dazu bringen können, diesen längsten Pfad zu nehmen. Daher ist es am besten, den Ein- und Ausgang in zwei Räumen zu platzieren, die am weitesten voneinander entfernt sind. Um dies zu finden, berechnen Sie den am weitesten entfernten Raum aus einem zufälligen Raum. Dann finden Sie von diesem Raum aus den am weitesten entfernten Raum. Dies wird als Ermitteln des Durchmessers eines Diagramms bezeichnet. Bitte googeln Sie es.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.