Trabalho desenvolvido para a disciplina de Inteligência Artificial da UFES, campus Alegre.
O trabalho segue a linha de projetos em Prolog desenvolvidos para a disciplina. Alguns trabalhos anteriores são:
- Corrida em Prolog - (Online)
- Batalha de Tanques - (Online)
- Batalha de Jatos - (Online)
- Batalha de OVNIs - (Online)
Você também pode jogar ele online em: Jogar Online
O código inicial, ainda da corrida, foi baseado do projeto do Radu Mariescu-Istodor
Atualmente, o código dele deve ser somente uma base, a ideia da estrutura. Mas, a inspiração inicial veio do trabalho dele.
Esse trabalho se parece com o Batalha de Jatos. Porém, ele não usa sensores como esse outro trabalho e não possui bordas em seu espaço.
Ao invés disso, ele fornece as informações das posições dos outros aviões e também dos mísseis aos agentes, que podem utilizar essas informações como um radar.
O objetivo é implementar um agente em Prolog capaz de controlar um jato em uma batalha aérea. O agente deve utilizar as informações disponibilizadas pelo jogo para tomar decisões de movimento e disparo e permanecer como o último jato sobrevivente.
Cada jato representa um jogador. Os jogadores podem ser controlados pelo teclado, por regras aleatórias implementadas em JavaScript ou por agentes implementados em Prolog.
Cada jato possui:
- posição
(X,Y); - ângulo de rotação;
- velocidade;
- pontuação/vida (
SCORE); - nome;
- tipo de controle.
A arena é toroidal. Não existem paredes nas bordas: quando um jato sai por uma extremidade, ele reaparece na extremidade oposta. O mesmo comportamento é utilizado pelos mísseis.
Os jatos podem disparar mísseis. Cada jato pode realizar, no máximo, um disparo por segundo. Os mísseis atravessam as bordas da arena e desaparecem gradualmente até serem desativados.
Atualmente, um jato inicia com 100 pontos de vida. Um impacto de míssil reduz sua vida em 10 pontos. O jogo termina quando apenas um jato permanece com vida maior que zero.
Os jatos podem passar sobre outros jatos sem causar dano entre si.
Os antigos sensores laterais foram removidos. O agente recebe uma informação global semelhante a um radar.
A chamada principal do agente é:
obter_controles(
INFORMACAO,
ADVERSARIOS,
MISSEIS,
CONTROLES
).INFORMACAO possui:
[X,Y,ANGLE,SCORE,SPEED]onde:
X: posição horizontal do jato;Y: posição vertical do jato;ANGLE: ângulo do jato em radianos, com0apontando para cima;SCORE: vida atual do jato;SPEED: velocidade atual.
ADVERSARIOS é uma lista com a posição de todos os outros jatos vivos:
[[X1,Y1],[X2,Y2],...]MISSEIS é uma lista com a posição dos mísseis ativos:
[[X1,Y1],[X2,Y2],...]Assim, o agente pode, por exemplo, procurar o adversário mais próximo, identificar um míssil próximo ou escolher uma rota de fuga.
O predicado obter_controles/4 deve retornar:
[FORWARD,REVERSE,LEFT,RIGHT,BOOM,MSG]onde:
FORWARD:1para acelerar e0para não acelerar;REVERSE:1para desacelerar e0para não desacelerar;LEFT:1para virar para a esquerda e0para não virar;RIGHT:1para virar para a direita e0para não virar;BOOM:1para tentar disparar e0para não disparar;MSG: mensagem de texto para depuração.
O jogo controla a limitação de um disparo por segundo; portanto, o agente pode retornar BOOM=1 continuamente sem conseguir disparar mais de uma vez por segundo.
As principais configurações ficam no início de main.js:
const dummyJets=5; // quantidade de jatos aleatórios
const keysJet=true; // jato controlado pelo teclado
const prologJets=[]; // jatos controlados pelo PrologPara adicionar jatos controlados pelo Prolog, utilize:
prologJets.push("Ligerin");
prologJets.push("Apaga Fogo");A quantidade de elementos em prologJets define a quantidade de jatos Prolog criados.
Para não utilizar nenhum jato Prolog, remova/comente as chamadas prologJets.push(...) e deixe:
const prologJets=[];Para não utilizar o jato controlado pelo teclado:
const keysJet=false;Para não utilizar jatos aleatórios:
const dummyJets=0;Os arquivos jato0.pl, jato1.pl etc. correspondem aos agentes Prolog de acordo com o índice atribuído em prologJetIDs. Ao adicionar mais jatos Prolog, também é necessário acrescentar o respectivo agente em jatos_controle.pl e criar o arquivo correspondente.
Os exemplos fornecidos implementam regras simples e aleatórias para que o projeto possa ser executado imediatamente.
O primeiro agente é definido em:
jato0.pl
e o segundo em:
jato1.pl
A interface esperada é sempre:
obter_controles([X,Y,ANGLE,SCORE,SPEED], ADVERSARIOS, MISSEIS, [FORWARD,REVERSE,LEFT,RIGHT,BOOM,MSG]) :-
...Os arquivos jatos_controle.pl e servidor.pl fazem a ligação entre o navegador e os agentes Prolog.
Quando não houver jatos controlados pelo Prolog, o jogo pode ser aberto diretamente no navegador de Internet.
Foi testado no navegador Brave.
É necessário instalar o SWI-Prolog.
Em distribuições GNU/Linux baseadas em Debian, por exemplo:
sudo apt install swi-prologTambém é possível obter o SWI-Prolog em:
Depois, dentro do diretório do projeto, execute:
swipl -s servidor.plO servidor será iniciado automaticamente na porta 8080 e deverá apresentar uma mensagem semelhante a:
--========================================--
% Started server at http://localhost:8080/
--========================================--
Com o servidor em execução, acesse:
http://localhost:8080/
O navegador realiza requisições HTTP para:
/action
A requisição informa:
id
x
y
angle
score
speed
adversarios
misseis
Os vetores adversarios e misseis são enviados em JSON. O servidor.pl converte os valores para números Prolog antes de chamar o agente.
Exemplo conceitual:
adversarios=[[468,380],[489,539],[89,55]]
misseis=[[500,340],[720,350]]
A resposta do servidor contém:
forward
reverse
left
right
boom
msg
O último elemento do vetor de controles é MSG.
Exemplo:
term_string([ADVERSARIOS,MISSEIS],MSG).Isso pode ser utilizado para enviar ao navegador uma representação textual das informações recebidas pelo agente.
Por exemplo:
?- term_string([1,2,"teste",oi],MSG).
MSG = "[1,2,\"teste\",oi]".O ângulo é fornecido ao agente em radianos.
A referência visual utilizada no jogo considera aproximadamente:
0° = 0 rad -> para cima
90° = PI/2 rad -> para a direita
180° = PI rad -> para baixo
270° = 3*PI/2 rad -> para a esquerda
360° = 2*PI rad -> novamente para cima
A imagem doc/info.png apresenta a referência visual utilizada pelo trabalho.
.
├── arena.js
├── boom.js
├── colors.js
├── controls.js
├── jet.js
├── main.js
├── servidor.pl
├── jatos_controle.pl
├── jato0.pl
├── jato1.pl
├── utils.js
├── index.html
├── style.css
├── jquery.min.js
├── airplane.png
├── airplane_dummy.png
├── background.jpg
├── favicon.ico
└── doc/
├── LEIA-ME.html
├── info.png
└── screenshot.png
A implementação fornecida é apenas uma base. O objetivo do trabalho é substituir as regras aleatórias dos arquivos jato0.pl, jato1.pl etc. por estratégias de Inteligência Artificial implementadas em Prolog.
O agente deve utilizar as informações disponíveis para criar estratégias de ataque, fuga, perseguição e sobrevivência.
A atividade também pode ser utilizada em uma competição entre os agentes desenvolvidos pelos alunos.
Boa diversão! :)