Obviamente, tentar aplicar o algoritmo min-max na árvore completa dos movimentos funciona apenas para pequenos jogos (peço desculpas a todos os entusiastas do xadrez, por "pequeno" não quero dizer "simplista"). Para jogos de estratégia típicos baseados em turnos, nos quais o tabuleiro costuma ter mais de 100 peças e todas as peças de um lado podem se mover simultaneamente, o algoritmo min-max é inaplicável.
Eu queria saber se um algoritmo min-max parcial que se limita a N configurações de placa em cada profundidade não poderia ser bom o suficiente? Usando um algoritmo genético, pode ser possível encontrar várias configurações de placa que são boas para a função de avaliação. Felizmente, essas configurações também podem ser boas para objetivos de longo prazo.
Eu ficaria surpreso se isso não tivesse sido pensado antes e tentado. Tem? Como funciona?
fonte
Respostas:
Depende da mecânica do jogo. A árvore de jogo min-max pode ser inaplicável em geral, mas talvez se aplique em algumas áreas. É comum que alguns locais em um mapa sejam estrategicamente importantes. Min-max pode ser aplicado em um nível estratégico para qual desses locais controlar. No nível tático, para os quadrados x ao redor de cada local estratégico, min-max pode ser usado para decidir como as unidades serão implantadas para capturá-lo e defendê-lo.
fonte
Este não é um algoritmo minimax, no entanto, os responsáveis pela IA do Killzone lançaram um artigo com base nas funções de avaliação de posição que algumas IA de xadrez também usam.
É muito simples, pois tudo o que faz é escolher uma posição no quadro com base no conhecimento atual do agente. Portanto, se o agente estiver com pouca saúde, as posições mais distantes do inimigo receberão uma pontuação mais alta, pois é mais desejável estar fora do alcance do inimigo.
O artigo pode ser encontrado em AI Game Programming Wisdom 3 e tem o título Avaliação Dinâmica da Posição Tática.
Um rascunho do documento pode ser encontrado on-line aqui:
http://www.cgf-ai.com/docs/straatman_remco_killzone_ai.pdf
Espero que ajude.
fonte
Eu não acho que seria bom o suficiente. Escolher as configurações N específicas, quantas e quais, seria praticamente impossível em algo tão complexo. Lembre-se de que se o seu jogo apresentar recursos infinitos ou algo semelhante, poderá haver círculos em como ele pode ser jogado, facilitando a exploração de uma IA desse tipo.
fonte
Eu sugeriria pelo menos implementar min-max com poda alfa-beta.
Sem tentar e decidir que é impraticável (ou seja, desempenho terrível) e sem mais conhecimento sobre a mecânica do jogo, não vejo por que você acha que o min-max é inaplicável.
O tamanho da placa é potencialmente um problema, mas com a poda, o descarte de caminhos perdidos permite uma pesquisa mais profunda com a mesma quantidade de computação, portanto, talvez as áreas maiores da placa não sejam um problema quando removidas. Além disso, supondo que o tamanho do quadro em si seja um problema pode ser prematuro, não é tanto o tamanho do quadro quanto a complexidade da mecânica e quantos movimentos são possíveis em cada posição do quadro. Se o seu jogo tiver uma área grande, mas pouco povoada, o número de movimentos possíveis de cada estado do tabuleiro pode não ser muito diferente do que se o tabuleiro fosse grande o suficiente para caber em todas as peças. É claro que se você tem um tabuleiro gigantesco com 90% de capacidade e tudo pode se mover para qualquer lugar a cada turno, isso exigirá muita pesquisa.
Também não sei por que o movimento simultâneo é inerentemente um problema. Desde que você faça a transição de um estado discreto para outro e tenha uma função de avaliação, o algoritmo deve ser aplicado.
Suponho que você precise ter uma função de avaliação de qualquer maneira e, independentemente da pesquisa que você usa, a função de avaliação é para onde a maior parte do trabalho provavelmente irá. O algoritmo min-max com remoção é muito simples de implementar, algo que você provavelmente pode fazer em uma ou duas horas e grande parte da infraestrutura funciona como armazenamento do estado da placa, avaliação, geração de movimento, provavelmente será o mesmo, independentemente da procure em que você se instala.
fonte
O vencedor do desafio de AI do Google em 2011 usou min-max (profundidade 1). Outro participante de destaque usou amostragem aleatória . O participante mencionou que uma mistura de min-max e amostragem aleatória, que é basicamente o que eu descrevi na minha pergunta, teve um desempenho ruim. Isso resolve, eu acho.
Por outro lado, mostra que é possível usar min-max em jogos grandes. Parece, no entanto, necessário limitá-lo a pequenos grupos de formigas, trabalhar com o conjunto completo de todas as formigas provavelmente teria sido muito lento. Outra observação interessante é que uma profundidade de 1 foi suficiente. Nós (humanos) nos tornamos muito bons jogando xadrez, e uma IA para este jogo precisa de árvores de pesquisa muito mais profundas para ser um desafio. Novos jogos mais complexos não são jogados e estudados há tanto tempo, e IAs mais burras podem ter valor de entretenimento suficiente.
fonte
A idéia básica de uma IA de xadrez é fazer uma lista de todos os movimentos possíveis da melhor jogada atualmente estimada, depois classificá-los e repetir o processo. Ele descarta aqueles com muito pouca chance, pois eles não serão tomados (ou pode-se presumir que não sejam tomados, pois eles não parecem dar uma vantagem).
A idéia básica requer que você faça uma lista de todos os movimentos possíveis e repita esse processo para todos os movimentos etc. Isso é possível no xadrez (onde a lista dos próximos movimentos prováveis é efetivamente enumerável; um tabuleiro de xadrez inicial tem 20 movimentos possíveis ) e até um ponto para outras coisas, como gamão, damas e resolver um cubo de Rubik.
Se eu tomar um jogo simples baseado em turnos (Civilization 2) como exemplo, cada um de vocês poderá se mover para um total de 8 quadrados (ou 24) em um único turno. Se você tem 10 caras (o que não é muito, normalmente você tem mais quando começa a ficar um pouco interessante) o número total de "movimentos" possíveis do estado atual (portanto, um único nível) já é 8 ^ 10 ou cerca de 4 bilhões. Mesmo se você podar 99,99% deles, ainda não poderá se aprofundar na árvore, pois o número de movimentos possíveis explode rapidamente.
Acrescente a isso que o jogo é um pouco parecido com o problema do cubo de Rubik, onde você só vê progresso após 10 ou 12 jogadas, o problema explode a um ponto em que as vantagens de um mínimo / máximo padrão são predominantes apenas com uma capacidade de memória de mais do que o seu computador típico terá.
Em outras palavras, as estratégias que encontrará serão reproduzíveis, mas ruins.
Para o problema real, como fazer uma IA decente, eu iria na direção do movimento aleatório basicamente orientado (mova cada sujeito com um pouco de inteligência básica), avaliação e ajuste. Faça isso em paralelo para 100 ou 1000 diferentes e escolha o que acaba sendo o melhor. Você pode enviar os resultados disso para a direção inteligente original para ajustá-lo novamente. Um pouco como a simulação de Monte Carlo.
fonte
Para aplicar com sucesso min / max a um jogo de estratégia baseado em turnos, você precisa aplicar corretamente todas as técnicas de xadrez disponíveis ...
Função de avaliação
Até os motores de xadrez têm uma força muito ruim, se as funções de avaliação forem ruins. A versão mais simples de uma função de avaliação é: 1 = jogo vencido por brancos, -1 = jogo vencido por pretos, 0 = todos os outros casos; Mas, isso daria um desempenho muito ruim. O mesmo acontece com o seu jogo baseado em turnos! Se você deseja usar min / max (com poda alfa / beta e outras coisas) como no xadrez, também deve implementar uma função de avaliação razoável! Senão, você não pode comparar o desempenho desses algoritmos ao ser aplicado ao seu jogo de estratégia com o caso em que é aplicado ao xadrez.
O que as funções de avaliação dos mecanismos de xadrez fazem é avaliar coisas como:
Essas partes da função de avaliação devem primeiro ser "traduzidas" para o seu jogo:
As diferentes classificações devem ser resumidas pela função de ponderação (fator_a * classificação_a + fator_b * ranting_b + ...) para todas as unidades ...
Nos jogos de estratégia, os recursos (ouro, madeira, ...) restantes devem ser levados em consideração.
Se a sua função de avaliação for boa o suficiente, na maioria dos casos você não precisará realmente pesquisar "profundamente" na árvore. Então, você provavelmente só precisa examinar mais de perto as 3 ou 10 opções mais promissoras. Veja o próximo capítulo ...
Movimentos possíveis em cada posição
A coisa mais problemática sobre o uso de min / max para jogos de estratégia é que você pode comandar várias unidades em um turno, enquanto no xadrez você só pode comandar uma unidade (exceto para roque, mas essa é uma combinação de movimentos claramente definida). Isso causa 5 ^ N movimentos possíveis para N unidades para cada "posição" (termo do xadrez), se você decidir entre "mover norte, sul, oeste, leste OU parar" para cada unidade. Você pode resolver isso dividindo o comando complexo em comandos de baixo nível: por exemplo, escolha a ação para a unidade A, entre em profundidade e decida pela unidade B .... decida pela unidade N ... e termine este turno. Mas, isso por si só não muda a complexidade! Você deve otimizar a ordem em que as ações são atribuídas às unidades (por exemplo, primeira unidade B, C, D e depois unidade A). Você pode registrar o impacto da decisão para cada unidade durante o último cálculo e depois classificar por importância. Dessa forma, a poda alfa-beta pode ser usada para eliminar qualquer combinação incorreta da árvore de pesquisa muito cedo. A prioridade mais alta deve sempre ser "não fazer mais nada e terminar o seu turno" (remoção de movimento nulo) em cada iteração. Dessa forma, você pode "pular" a atribuição da maioria das tarefas para a maioria das unidades e permitir que elas continuem o que fizeram antes. Dessa forma, a pesquisa será aprofundada rapidamente, basta dar uma olhada nas unidades "críticas" (por exemplo, as que estão realmente em combate no momento). Certifique-se de comandar apenas cada unidade uma vez ... Você também pode usar alguma aleatoriedade para garantir que as unidades "importantes" também recebam um comando de tempos em tempos. Especialmente, unidades que terminam algum trabalho (por exemplo,
Aprofundamento iterativo + cache / tabela de hash
Então, você pode "aprofundamento interativo" para aprofundar-se cada vez mais até que um prazo seja atingido. Portanto, você pesquisará mais profundamente se houver menos unidades e sempre terá algum "resultado" se parar de procurar uma solução melhor. O aprofundamento iterativo exigiria o uso de uma tabela de hash para armazenar em cache os resultados anteriores das pesquisas. Isso também permite reutilizar alguns dos resultados da última pesquisa de turnos (a ramificação da árvore de pesquisa que cobre os comandos que foram realmente executados na última rodada). Para implementar isso, você precisa de uma função de hash muito boa (consulte a "chave zobrist"), que pode ser atualizada iterativamente. Atualizar a chave de hash significa que você pode simplesmente pegar a chave de hash da antiga "posição" e pode simplesmente chutar a alteração na posição (por exemplo, retire a unidade na posição x e coloque-a na posição y). Dessa forma, o cálculo da chave de hash é rápido e você não precisa processar toda a situação das placas para calculá-la, apenas para verificar se o hash contém uma entrada anterior para esta posição. De certa forma, você deve garantir que não ocorram colisões de hash.
Comportamento não determinístico
O comportamento não determinístico é um problema para pesquisas mínimas / máximas. Isso significa que não há certeza se você atingirá um alvo atacado (por exemplo, a probabilidade é de 10%). Então você não pode apenas planejar isso acontecer. Nesse caso, você precisa modificar o algoritmo e colocar uma camada de "probabilidade" no meio. É um pouco como "as probabilidades mudam". Cada resultado independente deve ser considerado separadamente. A avaliação através dessa "camada" de profundidade deve ser amostrada (amostragem de Monte Carlo) e o resultado da avaliação detalhada deve ser ponderado pela probabilidade de ocorrência. Resultados diferentes da camada de probabilidade devem ser considerados como movimentos oponentes diferentes (mas, em vez de min / max, a "média" deve ser calculada). Obviamente, isso aumentará a complexidade da árvore de pesquisa.
Sumário
Ao aplicar todas essas técnicas (que são usadas pelos atuais mecanismos de xadrez) a um jogo determinístico, você certamente também poderá obter resultados razoáveis para um jogo. Para jogos não determinísticos, isso provavelmente será mais complicado, mas acho que ainda é administrável.
Um bom recurso para explicação dessas técnicas (para o xadrez) é http://chessprogramming.wikispaces.com/
Você pode até implementar algum tipo de aleatoriedade direcionada em pesquisas mínimas / máximas. Em vez de investigar deterministicamente os melhores resultados primeiro em cada iteração, você pode aleatoriamente fazer isso e deixar que sua ordem seja decidida por uma distribuição de probabilidade baseada nas avaliações atuais ...
fonte