web-dev-qa-db-fra.com

Pacman: comment les yeux retrouvent-ils le chemin du monstre?

J'ai trouvé beaucoup de références à l'intelligence artificielle des fantômes dans Pacman, mais aucune d'elles n'a mentionné comment les yeux retrouvent leur chemin vers le trou central des fantômes après qu'un fantôme a été dévoré par Pacman.

Dans mon implémentation, j'ai implémenté une solution simple mais affreuse. Je viens de coder en dur à chaque coin, quelle direction devrait être prise.

Existe-t-il une meilleure/ou la meilleure solution? Peut-être un générique qui fonctionne avec des conceptions de niveaux différents?

321
RoflcoptrException

En fait, je dirais que votre approche est une solution assez impressionnante, avec un coût en temps d'exécution quasi nul par rapport à n'importe quel type de recherche exploratoire.

Si vous en avez besoin pour généraliser à des cartes arbitraires, vous pouvez utiliser n'importe quel algorithme de recherche de chemin - la recherche en largeur d'abord est simple à mettre en œuvre, par exemple - et l'utiliser pour calculer les directions à encoder à chacun des coins avant l'exécution du jeu.

EDIT (11 août 2010): On vient de me référer à une page très détaillée sur le système Pacman: The Pac-Man Dossier , et comme j'ai la réponse acceptée ici, je pense que je devrais la mettre à jour. L'article ne semble pas couvrir l'acte de retourner explicitement dans la maison du monstre, mais il indique que le parcours direct dans Pac-Man est le cas suivant:

  • continuer à avancer vers l'intersection suivante (bien qu'il s'agisse essentiellement d'un cas particulier de "quand on vous laisse un choix, choisissez la direction qui n'implique pas l'inversion de votre direction, comme indiqué dans l'étape suivante);
  • à l'intersection, regardez les cases de sortie adjacentes, à l'exception de celle dont vous venez de sortir;
  • en choisir un qui est le plus proche du but. Si plusieurs sont également à proximité du but, choisissez la première direction valide dans cet ordre: haut, gauche, bas, droite.
151
Kylotan

J'ai résolu ce problème pour les niveaux génériques de cette façon: Avant le début du niveau, je fais une sorte de "remplissage d'inondation" à partir du trou du monstre; chaque tuile du labyrinthe qui n'est pas un mur porte un nombre indiquant à quelle distance il se trouve du trou. Ainsi, lorsque les yeux sont sur une tuile avec une distance de 68, ils regardent laquelle des tuiles voisines a une distance de 67; c'est la voie à suivre alors.

85
Erich Kitzmueller

Pour une alternative aux algorithmes de recherche de chemins plus traditionnels, vous pouvez jeter un oeil au modèle (nommé de manière appropriée!) modèle anti-objet Pac-Man Scent .

Vous pouvez diffuser l'odeur du monstre-trou autour du labyrinthe au démarrage et laisser les yeux le suivre à la maison.

Une fois que l'odeur est configurée, le coût d'exécution est très faible.


Edit: malheureusement l'article de Wikipédia a été supprimé, donc WayBack Machine à la rescousse ...

42
Dan Vinton

Vous devriez jeter un oeil sur un algorithme de recherche de chemin, comme algorithme de Dijkstra ou algorithme A * . Voici quel est votre problème: un problème de graphique/chemin.

18
Clement Herreman

Toute solution simple qui fonctionne est maintenable, fiable et performante est une bonne solution. Il me semble que vous avez déjà trouvé une bonne solution ...

Une solution de recherche de chemin sera probablement plus compliquée que votre solution actuelle et, par conséquent, nécessitera probablement un débogage. Ce sera probablement aussi plus lent.

IMO, si ce n'est pas cassé, ne le répare pas.

EDIT

IMO, si le labyrinthe est corrigé alors votre solution actuelle est bon/code élégant. Ne faites pas l'erreur d'associer "bon" ou "élégant" à "intelligent". Un code simple peut aussi être "bon" et "élégant".

Si vous avez des niveaux de labyrinthe configurables, alors vous devriez peut-être simplement faire le cheminement lors de la configuration initiale des labyrinthes. Le plus simple serait de demander au concepteur de labyrinthe de le faire à la main. Je ne prendrais la peine d'automatiser cela que si vous avez des labyrinthes incroyables ... ou si les utilisateurs peuvent les concevoir.

(De plus, si les itinéraires sont configurés manuellement, le concepteur de labyrinthe pourrait rendre un niveau plus intéressant en utilisant des itinéraires non optimaux ...)

18
Stephen C

Dans le Pacman original, le fantôme a trouvé le mangeur de pilule jaune grâce à son "odeur", il laissait une trace sur la carte. le joueur. Chaque fois que Pacman se déplaçait, les "valeurs des odeurs" étaient diminuées de 1.

Maintenant, un moyen simple d’inverser le processus consiste à créer une "pyramide d’odeur de fantôme", dont le point le plus élevé se trouve au centre de la carte. Le fantôme se déplace alors dans la direction de cette odeur.

14
Ivo Wetzel

En supposant que vous ayez déjà la logique nécessaire pour poursuivre pacman, pourquoi ne pas le réutiliser? Il suffit de changer de cible. On dirait que ce serait beaucoup moins de travail que d'essayer de créer une toute nouvelle routine en utilisant exactement la même logique.

5
John Gardeniers

Ce fut la meilleure source que j'ai pu trouver sur la façon dont cela fonctionnait réellement.

http://gameai.com/wiki/index.php?title=Pac-Man#Respawn Lorsque les fantômes sont tués, leurs yeux désincarnés reviennent à leur emplacement de départ. Ceci est simplement accompli en plaçant la tuile cible du fantôme à cet endroit. La navigation utilise les mêmes règles.

Cela a du sens. Peut-être pas la plus efficace au monde, mais une belle façon de ne pas avoir à vous soucier d’un autre État ou de quoi que ce soit du genre, si vous changez d’objectif.

Note latérale: Je ne savais pas à quel point ces programmeurs de pac-man étaient géniaux: ils ont en fait créé un système de messagerie complet dans un espace très restreint avec une mémoire très limitée ... c'est incroyable.

3
Midpipps

Que diriez-vous de chaque carré ayant une valeur de distance au centre? De cette façon, pour chaque carré donné, vous pouvez obtenir les valeurs des carrés voisins immédiats dans toutes les directions possibles. Vous choisissez la case avec la valeur la plus basse et vous vous déplacez vers cette case.

Les valeurs seraient pré-calculées à l'aide de tout algorithme disponible.

3
mvbl fst

C'est un problème de découverte. Pour un algorithme populaire, voir http://wiki.gamedev.net/index.php/A* .

3
Marijn

la suggestion de dtb23 consistant à choisir une direction aléatoire à chaque coin et vous finirez par découvrir que le monstre-trou semble horriblement inefficace.

Cependant, vous pouvez utiliser son algorithme de retour à la maison inefficace pour rendre le jeu plus amusant en introduisant plus de variation dans la difficulté du jeu. Pour ce faire, appliquez l'une des approches ci-dessus, telles que vos points de cheminement ou le remplissage de la source d'inondation, sans le faire de manière déterministe. Donc, à chaque coin, vous pouvez générer un nombre aléatoire pour décider de prendre la meilleure façon ou une direction aléatoire.

Au fur et à mesure que le joueur progresse, vous réduisez le risque qu'une direction aléatoire soit prise. Cela ajouterait un autre levier sur le niveau de difficulté général en plus du niveau de vitesse, de la vitesse fantôme, de la pause pour manger la pilule (etc.). Vous avez plus de temps pour vous détendre alors que les fantômes ne sont que des yeux inoffensifs, mais ce temps devient de plus en plus court à mesure que vous progressez.

2
imoatama

Réponse courte, pas très bien. :) Si vous modifiez le labyrinthe Pac-Man, les yeux ne reviendront pas nécessairement. Certains des hacks qui circulent ont ce problème. Donc, cela dépend d'un labyrinthe coopératif.

2
dwidel

Je pense que votre solution est bonne pour le problème, plus simple que cela, est de rendre une nouvelle version plus "réaliste" où les yeux fantômes peuvent traverser les murs =)

2
Hernán Eche

Voici un analogue et un pseudo-code de l'idée d'inondation d'ammoQ.

queue q
enqueue q, ghost_Origin
set visited

while q has squares
   p <= dequeue q
   for each square s adjacent to p
      if ( s not in visited ) then
         add s to visited
         s.returndirection <= direction from s to p
         enqueue q, s
      end if
   next
 next

L’idée est qu’il s’agit d’une recherche en profondeur, de sorte que chaque fois que vous rencontrez un nouveau carré adjacent, le meilleur chemin à suivre est p. C'est O(N) je crois.

2
Mark Peters

Je ne sais pas trop comment vous avez implémenté votre jeu, mais vous pouvez faire ce qui suit:

  1. Déterminez l'emplacement relatif des yeux par rapport à la porte. c'est-à-dire est-il laissé en haut? Juste en dessous?
  2. Puis déplacez les yeux en face de l’une des deux directions (par exemple, déplacez-la vers la gauche si elle se trouve à droite de la porte et sous la porte) et vérifiez s’il ya des murs qui vous en empêchent.
  3. Si des murs vous en empêchent, faites-le bouger dans le sens opposé (par exemple, si les coordonnées des yeux par rapport à la broche sont tout à fait au nord et si elle se déplaçait actuellement à gauche, il y a un mur dans le sens déplacez-vous vers le sud.
  4. N'oubliez pas de vérifier chaque fois que vous vous déplacez pour vérifier la position des yeux par rapport à la porte et pour vérifier s'il n'y a pas de coordonnées latitudinales. c'est-à-dire qu'il est seulement au-dessus de la porte.
  5. Dans le cas où il n'y a qu'un mur au-dessus de la porte, descendez s'il y a un mur, déplacez-vous vers la gauche ou la droite et continuez à faire ce numéro 1 - 4 jusqu'à ce que les yeux soient dans la tanière.
  6. Je n'ai jamais vu d'impasse dans Pacman, ce code ne rendra pas compte de l'impasse.
  7. De plus, j’ai inclus une solution indiquant quand les yeux "vacilleraient" entre un mur qui traverse l’Origine dans mon pseudocode.

Quelques pseudocodes:

   x = getRelativeOppositeLatitudinalCoord()
   y
   origX = x
    while(eyesNotInPen())
       x = getRelativeOppositeLatitudinalCoordofGate()
       y = getRelativeOppositeLongitudinalCoordofGate()
       if (getRelativeOppositeLatitudinalCoordofGate() == 0 && move(y) == false/*assume zero is neither left or right of the the gate and false means wall is in the way */)
            while (move(y) == false)
                 move(origX)
                 x = getRelativeOppositeLatitudinalCoordofGate()
        else if (move(x) == false) {
            move(y)
    endWhile
2
thyrgle

Je proposerais que le fantôme enregistre le chemin qu'il a emprunté du trou au Pacman. Donc, dès que le fantôme meurt, il peut suivre ce chemin mémorisé en sens inverse.

2
Fischer Ludrian
  1. Avant que le jeu ne commence, enregistrez les nœuds (intersections) de la carte.
  2. Quand le monstre meurt, prenez le point (coordonnées) et trouvez le nœud le plus proche dans votre liste de nœuds
  3. Calculer tous les chemins partant de ce nœud vers le trou
  4. Prendre le plus court chemin en longueur
  5. Ajouter la longueur de l'espace entre le point et le nœud le plus proche
  6. Dessine et avance sur le chemin

Prendre plaisir!

1
GingerHead

Mon approche nécessite un peu de mémoire (du point de vue de l’ère Pacman), mais vous n’avez besoin que de calculer une fois et cela fonctionne pour n’importe quel niveau de conception (y compris les sauts).

Étiqueter les nœuds une fois

Lorsque vous chargez un niveau pour la première fois, étiquetez tous les nœuds du repaire du monstre 0 (représentant la distance du repaire). Étiquetez ensuite les nœuds connectés 1, les nœuds qui leur sont connectés 2, etc., jusqu'à ce que tous les nœuds soient étiquetés. (note: cela fonctionne même si le repaire a plusieurs entrées)

Je suppose que vous avez déjà des objets représentant chaque nœud et des connexions à leurs voisins. Le pseudo-code pourrait ressembler à ceci:

public void fillMap(List<Node> nodes) { // call passing lairNodes
    int i = 0;

    while(nodes.count > 0) {
        // Label with distance from lair
        nodes.labelAll(i++);

        // Find connected unlabelled nodes
        nodes = nodes
            .flatMap(n -> n.neighbours)
            .filter(!n.isDistanceAssigned());
    }
}

Flood-fill out from lair

Les yeux se déplacent vers le voisin avec l'étiquette de distance minimale

Une fois que tous les nœuds sont étiquetés, le routage des yeux est trivial ... il suffit de choisir le nœud voisin avec l'étiquette de distance la plus basse (remarque: si plusieurs nœuds ont la même distance, peu importe laquelle est choisie). Pseudo code:

public Node moveEyes(final Node current) {
    return current.neighbours.min((n1, n2) -> n1.distance - n2.distance);
}

Exemple entièrement étiqueté

Complete map

1
AjahnCharles

Sachant que les chemins de pacman ne sont pas aléatoires (chaque niveau spécifique compris entre 0 et 255, inky, blinky, pinky et clyde fonctionnera exactement de la même manière pour ce niveau).

Je prendrais ceci et devinerais alors qu'il y a quelques chemins principaux qui enveloppent tout le labyrinthe comme un "chemin de retour" qu'un objet de globe oculaire prend en attente où il se trouve quand l'homme de poche a mangé le fantôme.

1
Incognito

Les fantômes de pacman suivent des schémas plus ou moins prévisibles s’agissant d’essayer de faire correspondre X ou Y en premier jusqu’à ce que l’objectif soit atteint. J'ai toujours supposé que c'était exactement la même chose pour les yeux retrouvant leur chemin.

1
plinth

Pour mon jeu PacMan, j’ai créé un algorithme un peu " shortest multiple path home " qui fonctionne pour tous les labyrinthes que je lui ai fournis (dans mon ensemble de règles). Cela fonctionne également à travers ces tunnels.

Lorsque le niveau est chargé, tous les path home data in every crossroad Sont vides (valeur par défaut) et une fois que les fantômes commencent à explorer le labyrinthe, ils crossroad path home information Continuent à être mis à jour chaque fois qu'ils rencontrent un "nouveau" carrefour ou par un chemin différent, trébuchez à nouveau sur leur carrefour connu.

0
iNyuu