Pacman: come fanno gli occhi a tornare alla buca dei mostri?


321

Ho trovato molti riferimenti all'intelligenza artificiale dei fantasmi in Pacman, ma nessuno di loro ha menzionato il modo in cui gli occhi tornano al buco fantasma centrale dopo che un fantasma è stato mangiato da Pacman.

Nella mia implementazione ho implementato una soluzione semplice ma terribile. Ho appena programmato su ogni angolo quale direzione dovrebbe essere presa.

Esistono soluzioni migliori / migliori? Forse uno generico che funziona con disegni di livello diverso?


11
Sei sicuro che l'hardcoding all'angolo sia abbastanza buono? Questo non garantisce il percorso migliore. Immagina che il fantasma si trovi di fronte a un passaggio lungo e stretto. Con il tuo algoritmo avrebbe dovuto percorrere l'intero passaggio, raggiungere un angolo e quindi prendere il percorso più veloce. Se hai codificato su ogni quadrato in quale direzione andare, potrebbe sapere di voltarsi per primo.
Mark Peters,

3
@Mark, dipende dalla tua definizione in un angolo. Se si tratta di una connessione a T anche se vai dritto nella riga superiore, va bene.
Thorbjørn Ravn Andersen,

1
@ Thorbjørn: non sto nemmeno parlando di incroci. Dai un'occhiata a questo forum: en.wikipedia.org/wiki/File:Pac-man.png . Se il fantasma si muoveva a destra e si posizionava sul secondo punto in basso a sinistra, non avrebbe incontrato alcun incrocio per un po '. Ciò causerà un ulteriore spostamento di 10 quadrati rispetto a se avesse girato all'indietro (a sinistra) e intrapreso il percorso più breve.
Mark Peters,

6
la tua soluzione utilizza waypoint (o briciole di pane) e penso che sia una tecnica usata comunemente per accelerare gli algoritmi di ricerca del percorso.
Nick Dandoulakis,

1
grazie per tutte le risposte! Ho semplicemente seguito la mia soluzione precedente e ho indicato le indicazioni stradali in ogni angolo. Per farlo in modo generico, è necessario che il file leveldesigner / a level definisca anche queste informazioni nella definizione del livello.
RoflcoptrException,

Risposte:


152

In realtà, direi che il tuo approccio è una soluzione davvero fantastica, con un costo a tempo quasi zero rispetto a qualsiasi tipo di pathfinding.

Se ne hai bisogno per generalizzare su mappe arbitrarie, puoi usare qualsiasi algoritmo di rilevamento dei percorsi - ad esempio la ricerca della larghezza di campo è semplice da implementare - e usarlo per calcolare quali direzioni codificare in ciascuno degli angoli, prima che il gioco sia avviato.

EDIT (11 agosto 2010): Mi è appena stata riferita una pagina molto dettagliata sul sistema Pacman: The Pac-Man Dossier , e dato che ho la risposta accettata qui, ho sentito di doverlo aggiornare. L'articolo non sembra riguardare l'atto di tornare alla casa dei mostri in modo esplicito, ma afferma che il pathfinding diretto in Pac-Man è un caso del seguente:

  • continua a spostarti verso l'incrocio successivo (anche se questo è essenzialmente un caso speciale di "quando ti viene data una scelta, scegli la direzione che non comporta l'inversione della tua direzione, come visto nel passaggio successivo);
  • all'incrocio, guarda i quadrati di uscita adiacenti, tranne quello da cui sei appena arrivato;
  • sceglierne uno più vicino all'obiettivo. Se più di uno è ugualmente vicino all'obiettivo, scegli la prima direzione valida in questo ordine: su, sinistra, giù, destra.

16
Penso che significhi che potresti calcolarlo in fase di esecuzione (quando il livello è caricato ma prima di iniziare a giocarlo) ma solo una volta. Non è difficile da mantenere.
Mark Peters,

3
Sì, o se c'è uno strumento per creare le mappe, come parte di quello.
Kylotan,

6
Non c'è nulla di sbagliato nel precomputare i percorsi di ritorno. Stai scambiando spazio di archiviazione (percorsi) per le prestazioni di runtime.
Steve Kuo,

6
Grazie. Penso che rimarrò fedele a questa soluzione. Qualcuno sa come è stato fatto nel Pacman originale?
RoflcoptrException il

4
No, non lo so. La domanda originale usava quel termine ma non è esattamente giuridicamente vincolante.
Kylotan,

85

Ho risolto questo problema per i livelli generici in quel modo: prima che inizi il livello, faccio una sorta di "riempimento" dal buco del mostro; ogni tessera del labirinto che non è un muro riceve un numero che indica quanto è lontano dal buco. Quindi quando gli occhi sono su una piastrella con una distanza di 68, guardano quale delle tessere vicine ha una distanza di 67; questa è la strada da percorrere allora.


15
Sì. Il diluvio è ottimo per l'individuazione di percorsi in qualsiasi situazione in cui il mondo non è troppo grande per renderlo praticabile. Penserei che potrebbe essere utilizzato anche in grandi mondi imponendo una griglia più grossolana la cui connettività è stata precalcolata. Farebbe andare le cose un po 'fuori mano, ma sarebbe meglio degli ingorghi che ho visto in questi giochi.
Loren Pechtel,

1
Per risparmiare spazio (per mondi più grandi o sistemi vincolati), è possibile salvare la direzione per viaggiare ad ogni incrocio, anziché salvare un valore per ogni piastrella. Questo è essenzialmente ciò che OP stava suggerendo.
BlueRaja - Danny Pflughoeft il

BlueRaja: Certo, ma è più complesso farlo e il risultato non è ottimale - il fantasma viene mangiato tra due incroci, quindi potrebbe correre nella direzione sbagliata per qualche tempo. La mia soluzione ha funzionato bene su un en.wikipedia.org/wiki/HP_200LX, quindi quanto più vincolato potrebbe ottenere?
Erich Kitzmueller,

5
(Sono in ritardo ...) Sì, il riempimento dell'inondazione è buono, tuttavia in realtà non è necessario un numero intero, ma solo una direzione (due bit) in ciascun quadrato per indicare il quadrato successivo da utilizzare.
Matthieu M.

Matthieu: Sì, sarebbe una possibile ottimizzazione.
Erich Kitzmueller, il

42

Per un'alternativa agli algoritmi di pathfinding più tradizionali, puoi dare uno sguardo al modello di antiobject di profumo Pac-Man (opportunamente chiamato!) .

All'avvio potresti diffondere odore di buco mostro attorno al labirinto e far sì che gli occhi lo seguano a casa.

Una volta impostato l'odore, il costo di runtime è molto basso.


Modifica: purtroppo l'articolo di Wikipedia è stato cancellato, quindi WayBack Machine in soccorso ...


2
questa sarebbe stata la mia risposta. È essenzialmente lo stesso di ammoQ, ma ricordo sempre l'odore di pacman :)
Luke Schafer,

Sembra che l'articolo di Wikipedia sia morto / cancellato. Il risultato principale di Google è questa discussione, ma penso che questo si avvicini.
David,

2
Mi sono confuso per un secondo, ma poi ho capito immediatamente cosa si intende per "profumo". È un ottimo modo per descrivere queste cose di campo scalare!
Steven Lu,


18

Qualsiasi soluzione semplice che funzioni sia mantenibile, affidabile e che funzioni abbastanza bene è una buona soluzione. Mi sembra che tu abbia già trovato una buona soluzione ...

È probabile che una soluzione di individuazione del percorso sia più complicata della soluzione corrente e quindi richieda un debug. Probabilmente sarà anche più lento.

IMO, se non è rotto, non aggiustarlo.

MODIFICARE

IMO, se il labirinto è risolto, la tua soluzione attuale è un codice buono / elegante. Non commettere l'errore di equiparare "buono" o "elegante" a "intelligente". Il codice semplice può anche essere "buono" ed "elegante".

Se hai livelli di labirinto configurabili, forse dovresti semplicemente fare il pathfinding quando configuri inizialmente i labirinti. La cosa più semplice sarebbe convincere il progettista del labirinto a farlo a mano. Mi preoccuperei solo di automatizzare questo se hai un labirinto di labirinti ... o gli utenti possono progettarli.

(A parte: se i percorsi sono configurati a mano, il progettista del labirinto potrebbe rendere un livello più interessante usando percorsi non ottimali ...)


Sì, funziona. Tuttavia, vorrei scrivere un buon codice e non solo un codice. Inoltre ho aggiunto l'ultima frase alla mia domanda, quindi se possibile l'algoritmo dovrebbe essere non solo per un labirinto ma per diversi.
RoflcoptrException il

si possono anche generare labirinti (ho un algoritmo che genera pacifici labirinti di pacman), quindi un po 'di automazione è la strada da percorrere
Erich Kitzmueller,

"... o gli utenti possono progettarli." Nel qual caso, hai un labirinto di labirinti.
phuzion

@phuzion - Ne sono consapevole. Tuttavia, esiste una distinzione tra i due casi. Se è l'OP a creare un labirinto bazzilion, è un inconveniente dover creare il routing a mano. Se è un utente finale ... significa che l'OP deve scrivere la documentazione, fare una risoluzione infinita dei labirinti degli utenti finali, presentare infinite lamentele su quanto sia ostile, eccetera. In altre parole, i motivi per implementare la generazione automatica del percorso sono diversi .
Stephen C,

14

Nell'originale Pacman lo Spettro trovò il mangiatore di pillole giallo con il suo "odore" che avrebbe lasciato una traccia sulla mappa, il fantasma avrebbe vagato in modo casuale fino a quando non avessero trovato l'odore, quindi avrebbero semplicemente seguito il percorso dell'olfatto che li conduce direttamente a il giocatore. Ogni volta che Pacman si muoveva, i "valori dell'olfatto" venivano ridotti di 1.

Ora, un modo semplice per invertire l'intero processo sarebbe quello di avere una "piramide di odore di fantasma", che ha il suo punto più alto al centro della mappa, quindi il fantasma si sposta semplicemente nella direzione di questo odore.


Mi piace molto questo approccio e proverò anche questo
RoflcoptrException il

5
Questo non è corretto; se tutti seguissero questo algoritmo finirebbero per inseguirlo in un singolo file. Il comportamento di ogni fantasma è diverso; puoi trovare maggiori informazioni sull'articolo di Wikipedia.
divisore

5

Supponendo che tu abbia già la logica necessaria per inseguire pacman perché non riutilizzarlo? Basta cambiare il bersaglio. Sembra che sarebbe molto meno lavoro che cercare di creare una routine completamente nuova usando la stessa logica esatta.


sì, ho la logica per inseguire pacman già implementata, ma non ne sono anche soddisfatto;)
RoflcoptrException

Nella mia esperienza (adoro scrivere versioni pacman solo per divertimento), farlo può far rimanere gli occhi fuori dal buco per molto tempo. Questo perché l'algoritmo di inseguimento generalmente segue la linea "se pacman è al nord, vai a nord" ma il labirinto potrebbe contenere "trappole" dove gli occhi dovrebbero prima andare a sud. Poiché Pacman si muove, il fantasma fuggirà prima o poi, ma il buco è un bersaglio fisso. (Nota: sto parlando di labirinti generati)
Erich Kitzmueller,


3

Che ne dici di ogni quadrato che abbia un valore di distanza dal centro? In questo modo per ogni dato quadrato è possibile ottenere i valori dei quadrati vicini immediati in tutte le direzioni possibili. Scegli il quadrato con il valore più basso e passa a quel quadrato.

I valori sarebbero pre-calcolati usando qualsiasi algoritmo disponibile.


Stavo per suggerire questo. Un diluvio verso l'esterno a partire dal 'mostro'. Penso che la tua risposta trarrebbe beneficio da una foto.
AjahnCharles l'

3

Questa è stata la migliore fonte che ho potuto trovare su come funzionava effettivamente.

http://gameai.com/wiki/index.php?title=Pac-Man#Respawn Quando i fantasmi vengono uccisi, i loro occhi disincarnati tornano alla posizione di partenza. Ciò si ottiene semplicemente impostando la tessera bersaglio del fantasma in quella posizione. La navigazione utilizza le stesse regole.

In realtà ha senso. Forse non è il più efficiente del mondo, ma un modo piuttosto carino di non doversi preoccupare di un altro stato o di qualcosa del genere, stai solo cambiando il bersaglio.

Nota a margine: non mi rendevo conto di quanto fossero fantastici quei programmatori pac-man che fondamentalmente creavano un intero sistema di messaggi in uno spazio molto piccolo con una memoria molto limitata ... è incredibile.


2

Penso che la tua soluzione sia giusta per il problema, più semplice di così, è rendere una nuova versione più "realistica" in cui gli occhi fantasma possono attraversare i muri =)


2
Per aggiungere ancora più realismo, consenti agli stessi fantasmi di muoversi attraverso i muri: D
Thomas Eding,

3
Quelle sono le pareti opache del fantasma, ma i fantasmi del secondo ordine (fantasma di un fantasma) sono più trasparenti. (potresti trovare molti manuali utente con bug trasformati in funzionalità)
Hernán Eche,

1
+1 per "fantasmi del secondo ordine" - oh sì, la derivata di un fantasma deve sicuramente trascendere i meri oggetti del primo ordine come i muri ... :)
Assad Ebrahim

2

Ecco un analogo e uno pseudocodice all'idea di riempimento inondazione di 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'idea è che si tratta di una prima ricerca, quindi ogni volta che incontri un nuovo quadrato adiacente s, il percorso migliore è attraverso p. È O (N), credo.


2

Non so molto su come hai implementato il tuo gioco, ma potresti fare quanto segue:

  1. Determina la posizione relativa degli occhi rispetto al cancello. cioè è lasciato sopra? Proprio sotto?
  2. Quindi sposta gli occhi di fronte a una delle due direzioni (come farla spostare a sinistra se si trova a destra del cancello e sotto il cancello) e controlla se ci sono e muri che ti impediscono di farlo.
  3. Se ci sono muri che ti impediscono di farlo, allora spostalo nella direzione opposta (ad esempio, se le coordinate degli occhi rispetto al perno sono proprio a nord e si stava muovendo a sinistra ma c'è un muro nel modo di farlo spostati a sud.
  4. Ricorda di continuare a controllare ogni volta per muoverti per continuare a controllare dove si trovano gli occhi rispetto al cancello e controlla per vedere quando non ci sono coordinate latitudinali. cioè è solo sopra il cancello.
  5. Nel caso in cui sia solo sopra il cancello, spostati verso il basso se c'è un muro, muoviti a sinistra oa destra e continua a fare questo numero 1 - 4 fino a quando gli occhi non sono nella tana.
  6. Non ho mai visto un vicolo cieco in Pacman questo codice non terrà conto dei vicoli ciechi.
  7. Inoltre, ho incluso una soluzione a quando gli occhi "oscillano" tra un muro che attraversa l'origine nel mio pseudocodice.

Alcuni pseudocodici:

   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

Il suggerimento di dtb23 di scegliere semplicemente una direzione casuale ad ogni angolo, e alla fine troverai che il mostro suona orribilmente inefficace.

Tuttavia, potresti sfruttare il suo inefficiente algoritmo di ritorno a casa per rendere il gioco più divertente introducendo più variazioni nella difficoltà del gioco. Lo faresti applicando uno dei suddetti approcci come i tuoi waypoint o il riempimento di alluvione, ma facendo ciò in modo non deterministico. Quindi ad ogni angolo, potresti generare un numero casuale per decidere se prendere la strada ottimale o una direzione casuale.

Man mano che il giocatore avanza di livello, riduci la probabilità che venga presa una direzione casuale. Ciò aggiungerebbe un'altra leva sul livello di difficoltà generale in aggiunta alla velocità del livello, alla velocità dei fantasmi, alla pausa del consumo di pillole (ecc.). Hai più tempo per rilassarti mentre i fantasmi sono solo occhi innocui, ma quel tempo diventa sempre più breve man mano che avanzi.


2

Risposta breve, non molto bene. :) Se alteri il labirinto di Pac-man gli occhi non torneranno necessariamente. Alcuni degli hack che fluttuano intorno hanno questo problema. Quindi dipende dall'avere un labirinto cooperativo.


2

Proporrei che il fantasma memorizzi il percorso che ha preso dal buco al Pacman. Quindi non appena il fantasma muore, può seguire questo percorso memorizzato nella direzione opposta.


2
molto probabilmente quel percorso sarà troppo lungo
Ahmad Y. Saleh,

Ogni volta che si rivisita un nodo, è possibile eliminare un ciclo dalla cronologia. Ciò lo renderebbe un po 'più diretto. Potrebbe essere più interessante che seguire sempre lo stesso percorso diretto, ma abbastanza spesso includerà alcuni loop piuttosto sciocchi (ad esempio 3 lati di un quadrato).
AjahnCharles l'

1

Sapendo che i percorsi pacman sono non casuali (ad esempio, ogni livello specifico 0-255, inky, blinky, pinky e clyde funzioneranno esattamente nello stesso percorso per quel livello).

Lo prenderei e indovinerei che ci sono alcuni percorsi principali che avvolgono l'intero labirinto come un "percorso di ritorno" che un oggetto bulbo oculare porta in attesa dov'è quando l'uomo pac ha mangiato il fantasma.


1

I fantasmi in Pacman seguono schemi più o meno prevedibili in termini di tentare di abbinare prima su X o Y fino al raggiungimento dell'obiettivo. Ho sempre pensato che fosse esattamente lo stesso per gli occhi che cercavano di tornare indietro.


1
  1. Prima che inizi il gioco, salva i nodi (intersezioni) nella mappa
  2. Quando il mostro muore, prendi il punto (coordinate) e trova il nodo più vicino nell'elenco dei tuoi nodi
  3. Calcola tutti i percorsi a partire da quel nodo alla buca
  4. Prendi il percorso più breve per lunghezza
  5. Aggiungi la lunghezza dello spazio tra il punto e il nodo più vicino
  6. Disegna e sposta sul percorso

Godere!


1

Il mio approccio richiede un po 'di memoria (dal punto di vista dell'era Pacman), ma devi solo calcolarlo una volta e funziona per qualsiasi livello di progettazione (compresi i salti).

Etichetta nodi una volta

Quando carichi un livello per la prima volta, etichetta tutti i nodi 0 della tana dei mostri (che rappresentano la distanza dalla tana). Procedere con l'etichettatura esterna verso nodi collegati 1, nodi collegati a loro 2 e così via, fino a quando tutti i nodi vengono etichettati. (nota: questo funziona anche se la tana ha più ingressi)

Presumo che tu abbia già oggetti che rappresentano ciascun nodo e connessioni ai loro vicini. Lo pseudo codice potrebbe assomigliare a questo:

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());
    }
}

Riempi dalla tana

Gli occhi si spostano verso il vicino con l'etichetta della distanza più bassa

Una volta che tutti i nodi sono stati etichettati, instradare gli occhi è banale ... basta scegliere il nodo vicino con l'etichetta della distanza più bassa (nota: se più nodi hanno la stessa distanza, non importa quale sia selezionato). Pseudo codice:

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

Esempio completamente etichettato

Mappa completa


0

Per il mio gioco PacMan ho realizzato un po '"shortest multiple path home " algoritmo in che funziona per qualsiasi labirinto in cui lo fornisco (nel mio insieme di regole). Funziona anche attraverso questi tunnel.

Quando il livello viene caricato, tutto path home data in every crossroadè vuoto (impostazione predefinita) e una volta che i fantasmi iniziano a esplorare il labirinto, crossroad path home informationcontinuano ad aggiornarsi ogni volta che si imbattono in un "nuovo" incrocio o da un altro percorso inciampano di nuovo sul loro incrocio noto.


-2

Il pac-man originale non usava la ricerca di percorsi o l'intelligenza artificiale. Ha solo fatto credere ai giocatori che ci fosse più profondità di quanto non fosse in realtà, ma in realtà era casuale. Come affermato in Artificial Intelligence for Games / Ian Millington, John Funge.

Non sono sicuro che sia vero o no, ma per me ha molto senso. Onestamente, non vedo questi comportamenti di cui parlano le persone. Red / Blinky per ex non segue sempre il giocatore, come si suol dire. Nessuno sembra seguire costantemente il giocatore, di proposito. La possibilità che ti seguiranno mi sembra casuale. Ed è molto allettante vedere il comportamento nella casualità, soprattutto quando le possibilità di essere inseguiti sono molto alte, con 4 nemici e opzioni di svolta molto limitate, in un piccolo spazio. Almeno nella sua implementazione iniziale, il gioco era estremamente semplice. Dai un'occhiata al libro, è in uno dei primi capitoli.


sì, ha usato un po 'di intelligenza artificiale. E sì Blinky segue Pacman quando è in modalità inseguimento (passa di tanto in tanto), quindi è AI tutto bene
Jean-François Fabre
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.