Pacman: como os olhos voltam para o buraco dos monstros?


321

Eu encontrei muitas referências à IA dos fantasmas em Pacman, mas nenhum deles mencionou como os olhos voltam para o buraco central dos fantasmas depois que um fantasma é comido por Pacman.

Na minha implementação, implementei uma solução simples, mas terrível. Eu apenas codifiquei em cada esquina qual direção deveria ser tomada.

Existe melhor / ou a melhor solução? Talvez um genérico que funcione com diferentes níveis de design?


11
Tem certeza de que a codificação na esquina é boa o suficiente? Isso não garante a melhor rota. Imagine o fantasma enfrentando uma passagem longa e estreita. Pelo seu algoritmo, ele teria que percorrer toda a passagem, chegar a um canto e seguir o caminho mais rápido. Se você codificou em cada quadrado em que direção seguir, ele pode saber apenas se virar primeiro.
Mark Peters

3
@ Mark, depende da sua definição em um canto. Se for uma conexão T, mesmo que você simplesmente vá direto na linha superior, tudo bem.
Thorbjørn Ravn Andersen

1
@ Thorbjørn: nem estou falando de cruzamentos. Dê uma olhada neste fórum: en.wikipedia.org/wiki/File:Pac-man.png . Se o fantasma estivesse se movendo para a direita e posicionado no segundo ponto do canto inferior esquerdo, ele não encontraria nenhum cruzamento por um tempo. Isso fará com que percorra 10 quadrados a mais do que se tivesse virado para trás (esquerda) e tomado o caminho mais curto.
Mark Peters

6
sua solução utiliza waypoints (ou migalhas de pão), e acho que é uma técnica comum usada para acelerar os algoritmos de localização de caminhos.
Nick Dandoulakis

1
obrigado por todas as respostas! Eu apenas aderi à minha solução anterior e codifiquei as instruções em cada esquina. Para torná-lo genérico, é necessário que o designer de nível / um arquivo de nível também defina essas informações na definição de nível.
RoflcoptrException

Respostas:


152

Na verdade, eu diria que sua abordagem é uma solução impressionante, com custo quase zero de tempo de execução em comparação com qualquer tipo de busca de caminhos.

Se você precisar generalizar para mapas arbitrários, poderá usar qualquer algoritmo de busca de caminhos - a busca pela primeira largura é simples de implementar, por exemplo - e usar isso para calcular quais direções codificar em cada um dos cantos, antes do jogo começar.

EDIT (11 de agosto de 2010): Acabei de me referir a uma página muito detalhada no sistema Pacman: O Dossiê Pac-Man e, como tenho a resposta aceita aqui, achei que deveria atualizá-la. O artigo não parece cobrir o ato de retornar à casa dos monstros explicitamente, mas afirma que a busca direta de caminhos no Pac-Man é um caso do seguinte:

  • continue se movendo em direção ao próximo cruzamento (embora este seja essencialmente um caso especial de 'quando for dada uma escolha, escolha a direção que não envolve inverter sua direção, como visto na próxima etapa);
  • no cruzamento, observe os quadrados de saída adjacentes, exceto o de onde você veio;
  • escolhendo um que está mais próximo da meta. Se mais de um estiver igualmente próximo da meta, escolha a primeira direção válida nesta ordem: cima, esquerda, baixo, direita.

16
Acho que ele quer dizer que você pode calculá-lo em tempo de execução (quando o nível é carregado, mas antes de começar a jogá-lo), mas apenas uma vez. Isso não é difícil de manter.
Mark Peters

3
Sim, ou se houver uma ferramenta para criar os mapas, como parte disso.
Kylotan

6
Não há nada errado em pré-computar os caminhos de retorno. Você está trocando armazenamento (caminhos) pelo desempenho do tempo de execução.
Steve Kuo

6
Obrigado. Eu acho que vou ficar com esta solução. Alguém sabe como foi feito no Pacman original?
RoflcoptrException

4
Não eu não. A pergunta original usava esse termo, mas não é exatamente juridicamente vinculativo.
Kylotan

85

Resolvi esse problema para níveis genéricos dessa maneira: Antes do início do nível, faço algum tipo de "preenchimento" do buraco do monstro; todo azulejo do labirinto que não é uma parede recebe um número que diz a que distância está do buraco. Portanto, quando os olhos estão em um ladrilho com uma distância de 68, eles olham qual dos ladrilhos vizinhos tem uma distância de 67; esse é o caminho a seguir então.


15
Sim. O preenchimento é muito bom para encontrar caminhos em qualquer situação em que o mundo não seja grande demais para torná-lo viável. Eu pensaria que poderia ser usado mesmo em grandes mundos impondo uma grade mais grossa cuja conectividade foi pré-calculada. Isso faria as coisas correrem um pouco fora do caminho, mas isso seria melhor do que os engarrafamentos que eu já vi nesses jogos.
Loren Pechtel 01/07

1
Para economizar espaço (para mundos maiores ou sistemas restritos), você pode salvar a direção para viajar em cada interseção, em vez de salvar um valor para cada bloco. Isso é essencialmente o que o OP estava sugerindo.
BlueRaja - Danny Pflughoeft

BlueRaja: Claro, mas é mais complexo fazer isso e o resultado não é o ideal - o fantasma é comido entre duas interseções, para que ele possa correr na direção errada por algum tempo. Minha solução funcionou bem em um en.wikipedia.org/wiki/HP_200LX, então, quanto mais restrito poderia ser?
Erich Kitzmueller

5
(Estou atrasado ...) Sim, o preenchimento é bom, mas na verdade você não precisa de um número completo, apenas uma direção (dois bits) em cada quadrado para apontar para o próximo quadrado a ser usado.
Matthieu M.

Matthieu: Sim, isso seria uma possível otimização.
Erich Kitzmueller

42

Para uma alternativa aos algoritmos de busca de caminho mais tradicionais, você pode dar uma olhada no padrão (apropriadamente nomeado!) Do Pac-Man Scent Antiobject .

Você poderia difundir o cheiro de buraco de monstro ao redor do labirinto na inicialização e fazer com que os olhos o seguissem para casa.

Depois que o cheiro é configurado, o custo do tempo de execução é muito baixo.


Edit: infelizmente o artigo da wikipedia foi excluído, então o WayBack Machine para o resgate ...


2
essa seria a minha resposta. É o mesmo que ammoQ essencialmente, mas lembre-se sempre sobre o cheiro pacman :)
Luke Schafer

Parece que o artigo da Wikipedia está morto / excluído. O resultado principal do google é esse tópico, mas acho que isso chega perto.
David

2
Fiquei confuso por um segundo, mas entendi instantaneamente o que se entende por "perfume". É uma ótima maneira de descrever essas coisas de campo escalar!
Steven Lu


18

Qualquer solução simples que funcione é sustentável, confiável e tem bom desempenho é uma boa solução. Parece-me que você já encontrou uma boa solução ...

É provável que uma solução de localização de caminho seja mais complicada do que a solução atual e, portanto, é mais provável que exija depuração. Provavelmente também será mais lento.

OMI, se não estiver quebrado, não conserte.

EDITAR

IMO, se o labirinto for corrigido, sua solução atual é um código bom / elegante. Não cometa o erro de equiparar "bom" ou "elegante" a "inteligente". Código simples também pode ser "bom" e "elegante".

Se você tem níveis de labirinto configuráveis, talvez você deva fazer a busca de caminhos ao configurar os labirintos inicialmente. O mais simples seria conseguir que o designer do labirinto o fizesse manualmente. Eu só me incomodaria em automatizar isso se você tiver um labirinto de bazilhões ... ou os usuários puderem projetá-los.

(Além disso: se as rotas forem configuradas manualmente, o designer do labirinto poderá tornar um nível mais interessante usando rotas abaixo do ideal ...)


Sim, está funcionando. No entanto, gostaria de escrever um bom código e não apenas um código. Além disso, adicionei a última frase na minha pergunta, portanto, se possível, o algoritmo deve ser não apenas para um labirinto, mas para vários.
RoflcoptrException

labirintos também pode ser gerado (eu tenho um algoritmo que gera aparência agradável labirintos pacman), então um pouco de automação é o caminho a percorrer
Erich Kitzmueller

"... ou os usuários podem projetá-los." Nesse caso, você tem um labirinto de bilhões.
Phuzion

@ phuzion - estou ciente disso. No entanto, há uma distinção entre os dois casos. Se o OP está criando labirintos de bazzilion, é um inconveniente ter que criar o roteamento manualmente. Se for um usuário final ... significa que o OP precisa escrever documentação, solucionar problemas sem fim dos labirintos dos usuários finais, apresentar queixas sem fim sobre o quão hostil é, etc. Em outras palavras, os motivos para implementar a geração automática de rota são diferentes .
Stephen C

14

No Pacman original, o Fantasma encontrava o comedor de pílulas amarelas pelo seu "cheiro", ele deixava um rastro no mapa, o fantasma vagava aleatoriamente até encontrar o cheiro, então eles simplesmente seguiam o caminho do cheiro que os levava diretamente para o jogador. Cada vez que o Pacman se movia, os "valores do olfato" eram reduzidos em 1.

Agora, uma maneira simples de reverter todo o processo seria ter uma "pirâmide de cheiro de fantasma", que tem seu ponto mais alto no centro do mapa, então o fantasma se move na direção desse cheiro.


Eu realmente gosto desta abordagem e eu também vou tentar este
RoflcoptrException

5
Isso não está correto; se todos seguissem esse algoritmo, acabariam perseguindo-o em um único arquivo. O comportamento de cada fantasma é diferente; você pode encontrar mais informações no artigo da Wikipedia.
divider

5

Supondo que você já tenha a lógica necessária para perseguir o pacman, por que não reutilizá-lo? Apenas mude o alvo. Parece que seria muito menos trabalhoso do que tentar criar uma rotina totalmente nova usando exatamente a mesma lógica.


sim eu tenho a lógica para pacman perseguição já implementadas, mas im também não está feliz com ele;)
RoflcoptrException

Na minha experiência (adoro escrever versões pacman apenas por diversão), fazer isso pode fazer com que os olhos fiquem presos do lado de fora por um longo tempo. Isso porque o algoritmo de perseguição geralmente segue as linhas de "se pacman está no norte, vá para o norte", mas o labirinto pode conter "armadilhas" onde os olhos teriam que ir para o sul primeiro. Como o pacman se move, o fantasma escapará mais cedo ou mais tarde, mas o buraco é um alvo fixo. (Nota: Eu estou falando sobre labirintos gerados)
Erich Kitzmueller


3

Que tal cada quadrado ter um valor de distância do centro? Dessa forma, para cada quadrado dado, você pode obter valores de quadrados vizinhos imediatos em todas as direções possíveis. Você escolhe o quadrado com o valor mais baixo e move-se para esse quadrado.

Os valores seriam pré-calculados usando qualquer algoritmo disponível.


Eu ia sugerir isso. Uma inundação externa começando no 'buraco do monstro'. Eu acho que sua resposta se beneficiaria de uma imagem.
AjahnCharles

3

Essa foi a melhor fonte que eu pude encontrar sobre como realmente funcionou.

http://gameai.com/wiki/index.php?title=Pac-Man#Respawn Quando os fantasmas são mortos, seus olhos desencarnados retornam ao local de partida. Isso é simplesmente conseguido definindo o bloco de destino do fantasma para esse local. A navegação usa as mesmas regras.

Na verdade, faz sentido. Talvez não seja o mais eficiente do mundo, mas uma maneira bastante agradável de não ter que se preocupar com outro estado ou qualquer coisa nesse sentido. Você está apenas mudando o alvo.

Nota lateral: Eu não percebi o quão impressionantes esses programadores pac-man eram eles basicamente criaram um sistema de mensagens inteiro em um espaço muito pequeno com memória muito limitada ... isso é incrível.


2

Eu acho que sua solução é correta para o problema, mais simples que isso, é tornar uma nova versão mais "realista" onde olhos fantasmas possam atravessar paredes =)


2
Para adicionar ainda mais realismo, permitir que os próprios fantasmas para ser capaz de se mover através de paredes: D
Thomas Eding

3
Essas são as paredes opacas dos fantasmas, mas os fantasmas de segunda ordem (fantasma de um fantasma) são mais transparentes. (você pode encontrar muitos manuais de usuário com erros transformados em recursos)
Hernán Eche

1
+1 para "segundas fantasmas ordem" - oh sim, o derivado de um fantasma deve certamente transcendem meros primeiros objetos de ordem como paredes ... :)
Assad Ebrahim

2

Aqui está um analógico e um pseudocódigo para a idéia de preenchimento de inundação da munição.

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

A idéia é que seja uma pesquisa pela primeira vez, então cada vez que você encontrar um novo quadrado adjacente s, o melhor caminho será através de p. É O (N) eu acredito.


2

Não sei muito sobre como você implementou seu jogo, mas você pode fazer o seguinte:

  1. Determine a posição relativa dos olhos em relação ao portão. ou seja, é deixado acima? Logo abaixo?
  2. Em seguida, mova os olhos para uma das duas direções (como fazer com que ele se mova para a esquerda, se estiver à direita do portão e abaixo do portão) e verifique se existem paredes e impedindo que você o faça.
  3. Se houver paredes impedindo você de fazê-lo, faça com que ele se mova na direção oposta (por exemplo, se as coordenadas dos olhos em relação ao pino estiverem no norte e ele estiver se movendo para a esquerda, mas houver uma parede no caminho) mude para o sul.
  4. Lembre-se de continuar verificando cada vez que se mover para continuar verificando onde estão os olhos em relação ao portão e verifique se não há coordenadas latitudinais. isto é, apenas acima do portão.
  5. No caso de estar apenas acima do portão, desça se houver uma parede, mova-se para a esquerda ou direita e continue fazendo esse número 1 a 4 até que os olhos estejam na cova.
  6. Eu nunca vi um beco sem saída no Pacman, esse código não será responsável por becos sem saída.
  7. Além disso, incluí uma solução para quando os olhos "balançariam" entre uma parede que se estende pela origem do meu pseudocódigo.

Algum pseudocódigo:

   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

A sugestão do dtb23 de apenas escolher uma direção aleatória em cada esquina e, eventualmente, você descobrirá que o buraco do monstro parece terrivelmente ineficiente.

No entanto, você pode usar seu algoritmo ineficiente de retorno para casa para tornar o jogo mais divertido, introduzindo mais variações na dificuldade do jogo. Você faria isso aplicando uma das abordagens acima, como seus pontos de referência ou o preenchimento de inundação, mas de maneira não determinística. Portanto, em cada esquina, você pode gerar um número aleatório para decidir se deve seguir o caminho ideal ou uma direção aleatória.

À medida que o jogador progride, você reduz a probabilidade de uma direção aleatória ser tomada. Isso adicionaria outra alavanca no nível de dificuldade geral, além da velocidade do nível, velocidade fantasma, pausa na ingestão de pílulas (etc). Você tem mais tempo para relaxar enquanto os fantasmas são apenas olhos inofensivos, mas esse tempo se torna cada vez menor à medida que você progride.


2

Resposta curta, não muito bem. :) Se você alterar o labirinto do Pac-man, os olhos não voltarão necessariamente. Alguns dos hacks que circulam por aí têm esse problema. Portanto, depende de ter um labirinto cooperativo.


2

Eu proporia que o fantasma armazene o caminho que ele seguiu do buraco até o Pacman. Assim que o fantasma morre, ele pode seguir esse caminho armazenado na direção inversa.


2
esse caminho provavelmente será longo demais
Ahmad Y. Saleh

Sempre que você revisitar um nó, poderá eliminar um loop do histórico. Isso tornaria isso um pouco mais direto. Pode ser mais interessante do que sempre seguir o mesmo caminho direto, mas com bastante frequência incluirá alguns loops quase bobos (por exemplo, 3 lados de um quadrado).
AjahnCharles

1

Saber que os caminhos do pacman não são aleatórios (ou seja, cada nível específico 0-255, tinta, blinky, pinky e clyde funcionará exatamente o mesmo caminho para esse nível).

Eu aceitaria isso e, em seguida, acho que existem alguns caminhos principais que envolvem todo o labirinto como um "caminho de retorno" que um objeto do globo ocular leva pendente onde está quando o homem comeu o fantasma.


1

Os fantasmas em pacman seguem padrões mais ou menos previsíveis em termos de tentar corresponder em X ou Y primeiro até que o objetivo seja alcançado. Eu sempre assumi que isso era exatamente o mesmo para os olhos que encontravam o caminho de volta.


1
  1. Antes do jogo começar, salve os nós (cruzamentos) no mapa
  2. Quando o monstro morre, pegue o ponto (coordenadas) e encontre o nó mais próximo em sua lista de nós
  3. Calcular todos os caminhos que começam desse nó até o furo
  4. Pegue o caminho mais curto por comprimento
  5. Adicione o comprimento do espaço entre o ponto e o nó mais próximo
  6. Desenhar e seguir no caminho

Aproveitar!


1

Minha abordagem é um pouco intensiva de memória (da perspectiva da era Pacman), mas você só precisa calcular uma vez e funciona para qualquer design de nível (incluindo saltos).

Rotular nós uma vez

Quando você carregar um nível pela primeira vez, rotule todos os nós do esconderijo do monstro 0 (representando a distância do esconderijo). Continue rotulando para fora os nós conectados 1, os nós conectados a eles 2 e assim por diante, até que todos os nós sejam rotulados. (nota: isso funciona mesmo se o covil tiver várias entradas)

Suponho que você já tenha objetos representando cada nó e conexões com seus vizinhos. O pseudo-código pode se parecer com isso:

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

Preenchimento do covil

Olhos se movem para o vizinho com o rótulo de menor distância

Uma vez que todos os nós são rotulados, rotear os olhos é trivial ... basta escolher o nó vizinho com o rótulo de distância mais baixa (nota: se vários nós têm distância igual, não importa qual é o escolhido). Pseudo-código:

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

Exemplo totalmente rotulado

Mapa completo


0

Para o meu jogo PacMan, criei um shortest multiple path homealgoritmo " " que funciona para qualquer labirinto que eu forneço (dentro do meu conjunto de regras). Também funciona através deles túneis.

Quando o nível é carregado, tudo path home data in every crossroadfica vazio (padrão) e uma vez que os fantasmas começam a explorar o labirinto, eles crossroad path home informationficam atualizados toda vez que encontram uma "nova" encruzilhada ou de um caminho diferente tropeçar novamente na encruzilhada conhecida.


-2

O pac-man original não usava IA de localização ou fantasia. Isso apenas fez os jogadores acreditarem que há mais profundidade do que realmente era, mas na verdade foi aleatório. Conforme declarado em Inteligência Artificial para Jogos / Ian Millington, John Funge.

Não tenho certeza se é verdade ou não, mas faz muito sentido para mim. Honestamente, não vejo esses comportamentos dos quais as pessoas estão falando. Vermelho / Blinky para ex não está seguindo o jogador o tempo todo, como eles dizem. Ninguém parece estar sempre seguindo o jogador de propósito. A chance de eles seguirem você parece aleatória para mim. E é muito tentador ver o comportamento aleatoriamente, especialmente quando as chances de ser perseguido são muito altas, com 4 inimigos e opções de giro muito limitadas, em um espaço pequeno. Pelo menos em sua implementação inicial, o jogo era extremamente simples. Confira o livro, está em um dos primeiros capítulos.


sim, ele usou alguma IA. E sim, Blinky segue pacman quando ele está no modo de perseguição (alterna para ele de vez em quando), então está tudo bem com a IA
Jean-François Fabre
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.