Algorithme de chemin le plus long pour la génération de labyrinthes roguelike

10

J'ai une simple carte basée sur une grille composée de pièces, comme ceci (A = entrée, B = sortie):

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

Et je suis coincé à essayer de créer un algorithme approprié pour créer un chemin de portes entre les pièces, de telle sorte que le joueur doive explorer la majeure partie de la carte avant de trouver la sortie.

En d' autres termes, je suis en train de trouver le chemin le plus long possible de A à B .

(Je sais que ce problème peut être résolu pour les graphiques acycliques; cependant, dans ce cas, il peut y avoir des cycles.)

EDIT: Un autre exemple où les pièces sont connectées à l'aide d'un remblai et la sortie est choisie comme la pièce la plus éloignée de l'entrée:

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

Notez que le chemin d'accès à la sortie n'est pas le plus long possible.

Utilisateur non trouvé
la source
Si vous forcez le joueur à emprunter le chemin le plus long possible, vous construisez en fait un chemin droit qui prétend être complexe. C'est mauvais.
o0 '.
Ce n'est pas mal (c'est la base du genre de tireur de rail, par exemple), mais vous devez être conscient que vous le faites et concevoir le reste de votre jeu pour bien fonctionner avec.
Il est également plus facile de contrôler le rythme du jeu lorsque les niveaux sont principalement linéaires. Il permet par exemple d'ajouter une salle de réveil après une salle monstre particulièrement difficile. S'il n'y avait pas de chemin principal, la répartition des défis et des récompenses serait aléatoire.
Utilisateur non trouvé

Réponses:

11

Je pense que vous vous y trompez. Le chemin maximal dans un graphique avec des cycles est techniquement indéfini car il est infini si le cycle se situe entre le début et la fin. Il existe probablement des moyens intelligents pour étendre / restreindre la définition du chemin maximal, mais je ne pense pas que ce soit la meilleure approche ici.

Vous n'essayez pas de modéliser un long chemin réel (par exemple, un robot essayant d'explorer autant de zone que possible sur une carte). Vous essayez simplement d'amener le joueur à explorer de nombreuses pièces.

Alors, faites en sorte que le joueur trouve la sortie proportionnelle au pourcentage de la carte explorée jusqu'à présent . Supposons qu'il y ait X pièces à un niveau et que le personnage joueur ait exploré Y. La prochaine fois que le personnage entre dans une pièce, placez-y la sortie avec une probabilité f (Y, X). Un exemple trivial de f pourrait être (Y * Y) / (X * X) - par exemple, pour 10 chambres, il y a 100% de chances que la sortie dans la dernière salle, 81% de chances qu'elle se trouve dans l'avant-dernière salle - et seulement un 1% de chance que ce soit dans la première salle.

Vous pouvez modifier l'équation comme vous le souhaitez pour que le jeu se sente bien, et peut-être même donner au joueur certaines capacités pour le rendre plus susceptible de générer. L'essentiel est de ne pas générer la sortie tant que le personnage n'est pas réellement entré dans la pièce. Cette méthode est également à l'abri des connaissances des joueurs sur l'algorithme de génération de donjon; même si le joueur a d'étranges schémas de mouvement comme le saut du chevalier dans NetHack ou la téléportation, il devra explorer plus de pièces pour trouver la sortie.

Si vous devez générer statiquement l'exit, vous pouvez utiliser la même idée avec un personnage virtuel. Imaginez un remplissage à partir de la position du personnage, se déplaçant une fois à chaque itération. La dernière pièce à remplir est la pièce à laquelle appartient la sortie (en fait, la dernière cellule à remplir est la cellule où elle est la plus éloignée du joueur). Cependant, dans ce cas, le joueur a plus d'informations sur la sortie - s'il est à gauche, c'est probablement à droite - et s'il peut se téléporter, il pourra peut-être y arriver plus rapidement qu'une marche aléatoire normale.

Enfin, je viens de terminer un roguelike où la sortie est apparue de l'autre côté de la carte du personnage du joueur, puis j'ai erré au hasard. Certains objets du donjon le rendaient visible sur la carte, au détriment de la faim plus rapide. Je n'ai fait aucune analyse, mais j'avais vraiment l'impression que je devais explorer davantage la carte pour la trouver, et cela donnait aux niveaux une sensation unique.


la source
La génération dynamique semble être une assez bonne idée, tant que le joueur ne le remarque pas. Sinon, je pense qu'ils se sentiraient assez trompés. J'adore cependant l'idée du remblayage.
Utilisateur non trouvé
2
Eh bien, toute votre proposition trompe en quelque sorte le joueur. Ne me blâmez pas d'avoir affiné les mathématiques pour ne pas avoir besoin d'un modèle mondial. ;) Mais vous pouvez utiliser des astuces de conception pour le rendre plus agréable au goût - par exemple, la sortie est placée a priori, mais une clé requise pour l'utiliser est générée dans la méthode que j'ai décrite, ou placée sur un monstre qui n'apparaît qu'après avoir exploré X chambres / tuer X monstres, ou ouvrir la porte nécessite de basculer X interrupteurs, un dans chaque chambre, etc ...
J'ai essayé une approche de remplissage. Il fait un bon travail de connexion de chaque pièce et produit des branches courtes, mais il ne produit pas réellement le chemin le plus long possible vers la sortie même si la sortie est le dernier nœud visité (ou, dans mon implémentation, le plus éloigné). (exemple ajouté à ma question)
Utilisateur non trouvé
Je suis tout de même pour les labyrinthes basés sur des touches / commutateurs. Il semble simplement plus facile d'implémenter ce genre de chose avec des arbres, car si vous avez deux branches, vous pouvez détecter quelle branche mène à la sortie, la bloquer et mettre la clé dans l'autre branche.
Utilisateur non trouvé
Mais j'admets que j'avais tort de penser que c'était un problème de repérage "A to B". Je me rends compte qu'il est plus logique de trouver la sortie à la suite de l'algorithme plutôt que comme un objectif.
Utilisateur non trouvé
6

Une alternative possible serait de créer un arbre couvrant (maximum?) En utilisant Prim / Kruskal (afin d'éliminer les cycles) et d'appliquer un algorithme traditionnel du plus long chemin sur l'arbre couvrant.

Cependant, je crains que l'algorithme de Spanning Tree ait tendance à créer des branches sans issue, forçant le joueur à revenir en arrière constamment.

EDIT: Résultat de l'utilisation d'un algorithme basé sur Kruskal et de placer la sortie à la fin de la branche la plus longue:

   0 1 2 3
  #########
0 #A | #
  # ##### - #
1 # # #
  ### #
2 ### #
  ### #
3 ### #
  ### - #####
4 # | #
  # - ##### - #
5 # ### #
  # - #######
6 # # B #
  # # - #
7 # | #
  #########
Utilisateur non trouvé
la source
1
J'allais aussi suggérer Primm :-), +1, je pense que le retour en arrière est une partie importante de beaucoup de jeux aussi ... consultez diablo 2.
Mr.Gando
2

Voici quelque chose à jouer:

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
}

Je supprimerais les portes au hasard le long du chemin, sinon vous vous retrouvez avec 1 porte à la sortie et des tonnes de portes au début.

Je pense que ce n'est O(n^2)pas génial pour les grandes cartes.

Stephen Furlani
la source
Une solution très élégante en principe. La prochaine fois, je devrais essayer de penser à quelque chose comme ça avant d'aller pour des techniques alambiquées.
Utilisateur non trouvé
Eh bien, élégant peut-être, mais ça va être un porc de processeur. O (n ^ 2) ne s'adaptera pas bien avec de grandes cartes.
Stephen Furlani
1

Je crois que vous avez déjà d'excellentes réponses, mais voici mes 0,02 $ de solution théorique au problème.

Ce que vous voulez n'est PAS le chemin le plus long, mais le chemin le plus long le plus court. Vous voulez la pièce la plus éloignée, étant donné que vous envisagez le chemin le plus court vers la pièce. Cela semble probablement déroutant, mais il est très facile à calculer.

  1. Commencez à votre salle de départ. Marquez chacun de ses voisins 1. Ils sont éloignés de 1 de la salle de départ.
  2. Pour chaque pièce marquée 1, visitez chacun de ses voisins NON MARQUÉS et marquez-les 2. Ils sont à 2 distances du départ.
  3. Continuez jusqu'à ce que vous ayez couvert toutes les pièces. La salle avec le nombre maximum est la plus éloignée du départ.

Le calcul d'un véritable chemin le plus long (ne prendra pas trop de temps pour disons 10 pièces) ne fonctionnera pas car vous ne pouvez pas obliger le joueur à emprunter ce chemin le plus long. Il est donc préférable de placer l'entrée et la sortie dans deux pièces les plus éloignées l'une de l'autre. Pour le trouver, calculez la pièce la plus éloignée d'une pièce aléatoire. Ensuite, à partir de cette pièce, trouvez la pièce la plus éloignée. Cela s'appelle trouver le diamètre d'un graphique, veuillez le rechercher sur Google.

Sid Datta
la source