A * Algoritmo para RPGs táticos?


15

Estou brincando com a escrita de um RPG tático muito ruim em C ++. Até agora, eu tenho um mapa em 2D e acabei de obter o algoritmo A * funcionando com base no pseudocódigo da wikipedia .

Mas RPGs táticos reais não apenas encontram o melhor caminho em um avião plano e se mudam para lá. Eles geralmente têm intervalos de movimento limitados e devem subir ou descer. Se você já jogou Final Fantasy Tactics, isso será afetado pelas estatísticas de Movimento e Salto. É aqui que eu me perco. Como altero o algoritmo A * para encontrar o melhor caminho em direção a um destino, mas o caminho tem apenas tantos blocos? Como devo levar em consideração as diferenças de altura e pular as estatísticas? Como faço para implementar pulando uma lacuna?

Se ajudar, agora meu mapa é representado por um objeto Vector of Tile. Cada bloco possui ponteiros para o bloco Norte, Sul, Leste e Oeste, que são definidos como nullptr se não existir nenhum bloco, como ao longo da borda do mapa ou se um bloco estiver definido como não passável.


5
Não sei por que o range de movimento é um problema. Encontre o caminho mais curto e, depois disso, mova os quadrados de 'velocidade' ao longo desse caminho.
Mooing Duck

Respostas:


33

Escalada e lacunas são apenas funções de custo diferentes. Para uma unidade que pode pular a lacuna, tem um custo normal (?), Enquanto para uma unidade sem salto, ela tem um custo arbitrariamente alto. Escalar custos extras, assim como terrenos difíceis, etc. O algoritmo A * é capaz de lidar com funções de custo; portanto, se sua implementação ainda não estiver sendo feita, pesquise no Google como implementar o A * com uma função de custo.

Dito isto, no entanto, não acho que A * seja uma abordagem particularmente boa para um RPG tático. Ou, mais precisamente, não é uma história completa. Você não quer que suas unidades mancem cegamente em direção ao seu objetivo, você quer que elas se posicionem para explorar cobertura, terreno elevado, o que quer que seja, enquanto progridem em direção ao objetivo final e procuram flanquear os oponentes e assim por diante. Portanto, o valor tático do ponto final de cada jogada é de enorme importância, não apenas o quão perto é a meta. Isso requer uma solução de problemas mais aprofundada do que a simples busca de caminhos.


10
Bons pontos sobre o 'posicionamento tático', mas essas decisões podem ser aplicadas em um nível superior ao do caminho básico. Por outro lado, aplicar custos aos nós no algoritmo de busca de caminhos que são gerados por algum tipo de analisador tático pode ser uma boa opção. Por exemplo, se o inimigo tem uma linha de visão com o terreno, faça com que os nós nesse terreno tenham um custo muito alto.
precisa saber é o seguinte

11
@DrMcCleod: De fato, e é isso que eu quis dizer com "Ou, mais precisamente, não é uma história completa". Você certamente poderia estar usando A * ou outro algoritmo para fazer parte do processamento, no entanto, acho que evitaria abordagens como tentar evitar nós observados pelo custo de movimento, uma vez que mover-se pelo terreno onde uma unidade pode estar sob fogo é mais bem tratado como um cálculo de risco / recompensa, IMO.
Jack Aidley

13

Quando você quiser todas as opções de movimento possíveis de uma unidade, use o algoritmo de Dijkstra .

A diferença entre A * e Dijkstra é que Dijkstra oferece todas as rotas mais curtas possíveis com um determinado custo e, se nenhuma delas chegar ao seu destino, aumenta o custo em um e continua. A *, por outro lado, prefere calcular primeiro as rotas que têm boas chances de chegar ao destino.

Portanto, quando você deseja apenas o caminho mais curto do ponto A ao ponto B, A * é uma boa opção. Mas se você deseja todas as opções de movimento possíveis e o caminho mais curto para cada uma delas, o Dijkstra é exatamente o que você deseja.

Tudo o que você precisa fazer é executar o algoritmo do Dijksta sem um nó de destino específico, mas com um custo máximo que não deve ser excedido (a faixa de movimento da unidade). Quando viajar para um nó exceder o custo máximo, não o visite. Quando o algoritmo termina devido à falta de arestas não visitadas, cada nó no conjunto visitado é um destino possível, e os marcadores de nós anteriores dos nós formam uma lista vinculada que representa o caminho de volta ao nó inicial.

Em relação aos saltos: esses podem ser representados como mais uma vantagem em A * e Dijkstra. Eles podem ter o mesmo custo que atravessar uma borda regular ou outra. Você também pode passar um parâmetro "jump_height" para o algoritmo que diz ao algoritmo para ignorar as bordas do salto que excedem uma determinada altura.


9
Vale mencionar aqui que isso A*é apenas uma generalização de Dijkstra; portanto, se você entende um, não deve ser muito difícil entender o outro.
cúbico

8
De fato, se você tem uma heurística que apenas retorna 0 no seu algoritmo A *, parabéns! Você acabou de escrever o algoritmo de Dijkstra.
Yann

9
"O Dijkstra oferece a você todas as rotas mais curtas possíveis com um determinado custo, e se nenhuma delas chegar ao seu destino ainda, aumenta o custo em um e continua" - Não é assim que funciona nem o que produz. Na verdade, é apenas uma generalização da busca pela primeira vez em gráficos ponderados. Ele encontra um único caminho mais curto. A * é apenas uma generalização disso, pois quando você tem uma heurística à distância disponível.
BlueRaja - Danny Pflughoeft 28/01

11
Não sei por que isso é tão votado. Do ponto de vista pragmático, Dijkstra é obsoleto. É ensinado no CS por razões educacionais e históricas. Até A * é obsoleto para trabalhos sérios; O Google Maps certamente não o usa. Você estaria olhando as variantes do ArcGraph hoje em dia.
MSalters

2
@MSalters Dijkstra e A * são algoritmos perfeitamente adequados para problemas simples, como RPGs táticos. Há uma gama muito estreita de movimentos válidos (blocos) e uma quantidade muito limitada de maneiras de se mover pelos referidos blocos (ortogonais, às vezes diagonais) e geralmente um caminho máximo bastante curto: SQRT (ArenaWidth² * ArenaHeight²). Em termos computacionais, a diferença é insignificante em uma máquina moderna para o que é provavelmente valores relativamente pequenos. Por que se preocupar com uma implementação mais complexa quando uma simples é suficiente para os fins descritos aqui?
Valthek

2

As outras respostas têm algumas informações boas, portanto, leia-as.

No entanto, para responder à sua pergunta: com base no pseudocódigo ao qual você vinculou, você tem algum tipo de função heuristic_cost_estimate qual está calculando o custo do tileA ao tileB (assumindo que eles sejam adjacentes). Em vez de usar um flat (1) para esse custo, você teria que ajustá-lo para incluir as estatísticas de bloco e estatísticas de unidade e possivelmente estatísticas de borda.

Por exemplo:

if (edge == JUMP && !unit.canJump()) 
    return INF;
if (tile.Type == Forest && unit.moveType == HORSE) 
    return 2;
//Other cases here
//-----
else 
    return 1;

Isso lhe dará seu caminho. Então, você simplesmente moveria a unidade ao longo de seu caminho enquanto consumia pontos de movimento e os interrompeu quando restarPoints <edgeCost. Observe que isso pode não ser completamente ideal se você acabar com Pontos restantes = 1, mas deve ser bom o suficiente para um RPG de prática. Na realidade, você gostaria de ser mais tático, como Jack Aidley apontou!

Desafio:
Se você quer se tornar mais avançado, provavelmente deseja usar o Djikstras, conforme sugerido, para encontrar todos os espaços a uma distância X, então você deseja avaliar cada espaço nessa lista para um "melhor" lugar, com base na proximidade do alvo, na defesa poder, se você pode ou não ser atacado a partir dessa posição, etc. Com base nessas informações, você escolheria um ladrilho e depois seguiria para lá seguindo o caminho que você acabou de calcular usando Djikstras.


1

Escaladas e lacunas são bastante triviais, pois apenas modificam o custo. A busca de caminhos (e a maior parte da IA ​​tática) consiste em resumir o custo em todos os nós a serem visitados e minimizar isso. Um penhasco intransitável terá um custo infinito (muito, muito alto), as encostas terão um custo mais alto do que o normal, etc.

Isso, no entanto, encontra o caminho ideal globalmente que não é a melhor solução, porque adversários reais geralmente não encontram o caminho ideal. É altamente irrealista, às vezes até um ponto óbvio para o jogador, e irritante (especialmente quando a IA como tal é basicamente invencível, porque também escolhe o ideal).

Boas simulações deliberadamente não encontram o melhor caminho. Um algoritmo muito melhor pode ser a busca hierárquica de caminhos - se nada mais, desenhando uma linha reta no mapa e pegando 4-5 waypoints, depois pathfinding de um waypoint para o próximo, considerando apenas os pesos dos nós até agora conhecido e definindo todos os outros pesos de nó como "indiferente". Como alternativa, você pode executar A * em uma grade mais grossa primeiro e depois encontrar o caminho de um nó grande para o próximo (mas acho que desenhar uma linha no mapa também é bom).

Isso é muito mais realista (e também consome uma fração da capacidade de processamento porque o gráfico é muito menor). Sim, isso pode significar que uma unidade se move em direção a um penhasco apenas para descobrir que não pode atravessar. Tudo bem, isso acontece com adversários reais também. Da próxima vez, isso não acontecerá novamente (porque agora o custo infinito é conhecido).


11
Lembre-se de que "o simples caminho hierárquico" pode parecer muito estúpido. Você recebe unidades caminhando diretamente para um cume da montanha, apenas para descobrir lá que o caminho está bloqueado. Eles então passam pela passagem da montanha até o próximo ponto de referência e de lá para o destino - mesmo que esse último ponto de referência esteja fora do caminho para eles. O pré-processamento identificaria a passagem da montanha na frente e o ponto de passagem por lá. Mas mesmo se você não fizer isso, quando estiver muito longe do curso planejado, planeje novamente o restante.
precisa saber é o seguinte

@ MSalters: Isso pode acontecer com o método "desenhar uma linha", mesmo após a primeira tentativa, sim. É improvável que isso aconteça mais de uma vez com o método hierárquico de grade grossa (que, por exemplo, leva a média, a mediana ou até o valor máximo de custo dos nós). É exatamente como um adversário humano jogaria - evite grandes obstáculos que você conhece ou pode ver de longe como uma cadeia de montanhas e, de outro modo, planeje uma rota grossa e quase reta e abra caminho. A menos que você saiba que há uma montanha, você caminha diretamente para ela.
Damon
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.