Como escrevi AI para estratégia baseada em turnos

Olá pessoal. Penso que, a partir do cabeçalho, fica claro que falaremos sobre a criação de inteligência artificial (daqui em diante simplesmente AI), sobre quais decisões foram tomadas e o que acabou acontecendo. Mas primeiro você precisa se atualizar.

O jogo está escrito na linguagem de programação Lua, então darei exemplos de código nessa linguagem.

Vou descrever alguns detalhes do jogo que são importantes para a IA:

  1. O jogo é uma estratégia baseada em turnos. Primeiro, o jogador caminha, depois a IA faz suas ações para cada país. O AI só funciona quando você clica em Avançar e não faz ideia do que acontece em outro momento.
  2. O jogo tem um mapa no qual você pode recrutar / mover / implantar tropas. A IA deve analisá-lo e tomar as decisões necessárias.
  3. No jogo, você pode fazer a paz / declarar guerra / assinar um pacto de não agressão / firmar e encerrar alianças. A IA deve ser capaz de lidar com isso.
  4. As instituições políticas e de tecnologia estão disponíveis apenas para o jogador. Os bônus de IA não mudam desde o início do jogo, diferentemente do jogador.

A função responsável por iniciar a próxima jogada é assim:

function next_step() --     --   ,    for k, v in pairs(game_data.lands) do calc_ai(k) end --  End 

Você deve ter notado a função mágica calc_ai , responsável por todas as ações dos bots. Você ainda pode ver um detalhe interessante: a função é executada alternadamente para cada país.

Agora, respondemos à pergunta, o que acontece no calc_ai .

 function calc_ai(land) if land == game_data.player_land or land == "Undeveloped_land" or not game_data.lands[land] then return end --    ,     for k, v in pairs(game_data.lands) do local option = math.random() --  ,       . if k == game_data.player_land then ai_data = fixed_ai_data[game_data.difficulty].player else ai_data = fixed_ai_data[game_data.difficulty] end end move_army( math.random(), land) --  balance_army( math.random(), land) --   end 

Até entendermos profundamente como a IA toma decisões na política, observamos o seguinte:

  1. Há uma verificação de que a IA não vai acidentalmente para o jogador ou para o incompreensível Undeveloped_land. Esta é apenas uma terra sem país (de fato, uma província deve sempre ter um país que a possui; portanto, Undeveloped_land é a designação principalmente para o jogo).
  2. O AI seleciona tabelas diferentes para interagir com o país, dependendo se o jogador o controla ou não.
  3. A IA primeiro move o exército e só depois contrata.

fixed_ai_data - a própria tabela. É nomeado assim porque não muda (mais precisamente, a variável sempre se refere à tabela raiz).
ai_data - a tabela em si, que muda dependendo se o bot lida com o jogador ou não (a variável se refere simplesmente à tabela desejada).

Na verdade, o jogo tem apenas uma tabela relacionada à IA e fica assim:

 local ai = { standard = { peace = { conquer = 0.0001, war = 0.0002, war_neighbour = 0.004, pact = 0.005, agree_pact = 0.018, alliance = 0.001, alliance_small = 0.002, agree_alliance = 0.002, kick = 0.0005, envy = 0.02 }, war = { agree_peace = 0.005, }, player = { peace = { war = 0.0002, war_neighbour = 0.002, pact = 0.008, agree_pact = 0.08, alliance = 0.001, alliance_small = 0.002, agree_alliance = 0.002, kick = 0.0005, support = 0.005, voluntary_support = 0.002, envy = 0.01 }, war = { agree_peace = 0.02, } }, bonuses = { population_increase = 1.4, money_increase = 1.5, upgrade_province = 0.005 } }, } 

standard - nível de dificuldade. Existem vários níveis de dificuldade, e os valores em tabelas diferentes variam.

peace , war - estado do país. A tabela de peace é usada para qualquer ação, a tabela de war é apenas para ações com o inimigo.

A tabela do terceiro player contém as tabelas de peace e war com os valores alterados. Como você já sabe, em um jogo de IA pode ter uma atitude diferente em relação ao jogador e ao bot.

Os valores nas tabelas, eu acho, são claros por nome. Mas, de qualquer forma, consideraremos alguns deles.

Enquanto isso, precisamos descobrir como a IA funciona no jogo. Tudo é simples aqui, dependendo do estado, o bot pode selecionar qualquer valor da lista. Os números acima são a probabilidade de ocorrência de cada evento. Considere um exemplo:
pact = 0.005 - significa que, com uma chance de 0,005, um país oferecerá outro país para concluir um pacto de não agressão. Sim, tudo é simples. Você pode dizer: "Como então você pode jogar, sabendo que a IA faz tudo aleatoriamente?" Na verdade, não é bem assim, e analisaremos isso um pouco mais tarde.

Enquanto isso, observe a seguinte função:

 function get_answer(option,state) local sum_option = 0 for k, v in pairs(state) do sum_option = sum_option + v if option < sum_option then return k end end if sum_option > 1 then print("AI Error, sum_option > 1") end end 

option - número aleatório de 0 a 1
state - estado do país
A função get_answer simplesmente retorna uma ação aleatória. Por que é necessário e por que você não pode apenas marcar a option <chance de ação, acho que não é necessário explicar.

Esta função está marcada em todas as ações possíveis para o AI:

 if __ and get_answer(option, ai_data.peace) == "pact" then _ end 

Tudo é simples. Parece, isso pode ser terminado, mas não.

Vamos esclarecer alguns pontos:

  1. A AI declara guerra a vizinhos e não vizinhos com chances diferentes ( war , war_neighbour )
  2. Os países pequenos são mais propensos a ingressar em sindicatos do que os grandes ( alliance , alliance_small )
  3. A IA tem inveja. O nome não é totalmente claro, mas é uma chance com a qual o país declarará guerra forte demais pelos padrões do poder do jogo.
  4. Esquecemos a tabela de bônus. Ele armazena valores que não estão relacionados à atitude em relação a outros países, por exemplo, um bônus ao crescimento da população ou uma chance de melhorar a província.

Isso não terminou aí (a menos que você estivesse interessado, é claro). É estranho quando um país declara guerra sem motivo, e ainda mais estranho quando não está pronto para esta guerra. Portanto, a IA no jogo tem estratégias. Vou explicar que, em vez de um ataque surpresa, na maioria dos casos o país inicia uma estratégia.

Cada país no arquivo salvo possui os seguintes campos:

  • strategy - identificador da estratégia. Acontece:
    1. retreat - um país reduz seu exército para economizar dinheiro.
    2. recruit - o país emprega o exército máximo.
  • target é o alvo. Este é qualquer país pelo qual nossa IA decidiu declarar guerra, mas iniciou uma estratégia.
  • ultimatum - nulo, se não houver ultimato, dados sobre o ultimato, se houver.
  • value - o número de movimentos antes da declaração de guerra. Não consegui criar um nome de variável melhor, desculpe.

Ou seja, se a IA inicia uma estratégia, ele:

  1. Reduz seu exército e economiza dinheiro.
  2. Contrata o exército mais alto possível.
  3. Declara guerra ao jogador.



Com uma certa chance, um país pode propor um ultimato, em cuja implementação a guerra é cancelada. Por exemplo:
Reduza seu exército na província de lipetsk para 5.000; caso contrário, declararemos guerra a você.

Do engraçado: há um bug interessante ou até uma falha quando o país exige reduzir o exército na província, e o jogador consegue perder o ultimato até que ele expire. A IA não leva em conta a província e, se o ultimato não for respeitado, declara guerra.



Existem duas variáveis ​​responsáveis ​​pela chance de apoiar o jogador (transferir ouro para o jogador). O primeiro sempre funciona, exceto o estado de guerra com o país para o qual é calculado. E o segundo, com grande significado, é levado em consideração quando existe um inimigo comum.

Várias variáveis ​​também foram adicionadas, por exemplo, o medo (quanto o exército inimigo deve exceder o seu próprio para que a IA comece a pensar no mundo). Tudo isso é feito para tornar as ações da IA ​​mais lógicas e compreensíveis. Mas enfim, agora sabemos que esse é realmente um acidente disfarçado comum.

Também notei que os jogadores realmente dotam a IA de alguns recursos incomuns para ele. Por exemplo, se em um determinado momento um jogador declarar guerra a vários países, ele pensará antes de tudo que isso é uma conspiração contra ele, e não apenas uma coincidência. E se o jogador receber uma proposta para concluir um pacto de não agressão, ele pensará que o vizinho tem medo de suas terras. Mas, infelizmente, não é assim. A realidade está cheia de decepções.

Source: https://habr.com/ru/post/pt473952/


All Articles