modelo de tcc para o curso de ciência da computação da …siaibib01.univali.br/pdf/nauro da silva...
TRANSCRIPT
UNIVERSIDADE DO VALE DO ITAJAÍ
CENTRO DE CIÊNCIAS TECNOLÓGICAS DA TERRA E DO MAR
CURSO DE CIÊNCIA DA COMPUTAÇÃO
AGENTE INTELIGENTE QUE APRENDE A JOGAR MARIO BROS.
por
Nauro da Silva Júnior
Itajaí (SC), novembro de 2012
UNIVERSIDADE DO VALE DO ITAJAÍ
CENTRO DE CIÊNCIAS TECNOLÓGICAS DA TERRA E DO MAR
CURSO DE CIÊNCIA DA COMPUTAÇÃO
AGENTE INTELIGENTE QUE APRENDE A JOGAR MARIO BROS.
Área de Inteligência Artificial
por
Nauro da Silva Júnior
Relatório apresentado à Banca Examinadora
do Trabalho Técnico-científico de Conclusão
do Curso de Ciência da Computação para
análise e aprovação.
Orientador: Benjamin Grando Moreira,
M.Eng.
Itajaí (SC), novembro de 2012
Dedico esta pesquisa a minha família e a todos aqueles que me apoiaram, por mais difícil
que tenham sido os momentos, sempre estiveram do meu lado me dando forças para nunca
desistir.
AGRADECIMENTOS
Agradeço aos meus pais que sempre confiaram em mim e garantiram tudo que estava
ao alcance deles para conseguir o melhor para mim, à minha namorada por nos dias mais
difíceis quando cheguei a pensar em desistir sempre me apoiou e me fez sempre seguir em
frente, a todos os amigos que sempre me ajudaram de toda forma possível, e ao meu
orientador por sempre estar presente quando necessário para me auxiliar nesta pesquisa.
“É preciso amar as pessoas como se não houvesse amanhã, porque se você parar pra pensar,
na verdade não há...” – Legião Urbana, Pais e Filhos.
RESUMO
DA SILVA JR, Nauro. Agente Inteligente que aprende a jogar Mario Bros. Itajaí, 2012.
68f. Trabalho Técnico-científico de Conclusão de Curso (Graduação em Ciência da
Computação) – Centro de Ciências Tecnológicas da Terra e do Mar, Universidade do Vale do
Itajaí, Itajaí, 2012.
Os jogos de computadores podem ser divididos em duas grandes áreas, jogos com inteligência
e sem inteligência. Os jogos que possuem inteligência aumentam a jogabilidade e
consequentemente motivam os jogadores, mas em alguns jogos essa inteligência artificial é
criada de maneira precária, causando desconforto ao jogador, pois sempre realizam as
mesmas ações, independente das ações de um inimigo ou do próprio jogador. Um outro caso
que pode causar desconforto é o personagem que conhece o cenário inteiro sem nunca ter
passado por lá fazendo com que o jogador acabe não tendo a sensação de estar interagindo
com outros jogadores. Esta pesquisa teve por objetivo desenvolver um agente para o jogo
Mario Bros. Para criação do agente, foi utilizada a plataforma do campeonato Mario AI
Championship, que é uma competição que visa desenvolver um agente para superar a fase o
mais rápido possível. Este agente iniciou sem conhecer o cenário e conforme ele interagiu
com os objetos adquiriu conhecimento sobre os mesmos, fazendo com que com o passar do
tempo fosse capaz de superar obstáculos previamente vistos e quando encontrasse obstáculos
novos aprendesse como é capaz de interagir ou superá-los, utilizando de técnicas de
inteligência artificial como sistemas baseados em regras, máquinas de estados e árvores de
decisão. O agente após o desenvolvimento foi capaz de superar os obstáculos sem problemas,
utilizando conhecimentos obtidos em tentativas anteriores e com seus erros.
Palavras-chave: Inteligência Artificial. Jogos Digitais. Aprendizado de Máquina
ABSTRACT
The computer games can be divided in two big areas, games with intelligence and games
without intelligence. The games that have intelligence increase the gameplay and
consequently motivate players, but in some games this artificial intelligence is poorly made,
causing discomfort to the player, because always perform the same actions, independently of
the actions of an enemy or the player. Another case that can cause discomfort is the character
that knows the entire world without has been there before, that don’t give to the player the
sensation to being interacting with other players. This research has the objective to develop
an agent to the game Mario Bro. To create the agent, will be utilized the Mario AI
Championship platform, that is a competition that has the objective to develop an agent to
overcome the map as fast as it can. This agent will start without having any knowledge about
the scenario and as it interacts with objects it will learn about them, doing that with it goes
forward it will be capable of overcome obstacles that was seen previously, and when it finds
new obstacles, try to learn how it’s capable of interact or overcome them, utilizing AI
techniques like rule based systems, state machines and decision trees. Is expected that with
the interaction with many situations, obstacles, items and enemies, the agent will be capable
of overcome the situations without any troubles, utilizing its previous knowledge acquired by
similar situations.
Keywords: Artificial Intelligence. Digital Games. Machine Learning.
LISTA DE FIGURAS
Figura 1. Exemplo de árvore de decisão para ação de personagem.. ....................................... 27
Figura 2. Casos de uso do agente ............................................................................................. 38 Figura 3. Imagem do jogo com matriz ..................................................................................... 39 Figura 4. Execução da regra ..................................................................................................... 41 Figura 5. De frente para um buraco, foco só ao redor do agente.............................................. 42 Figura 6. Obstáculo que exige planejamento............................................................................ 43
Figura 7. Árvore de Planejamento ............................................................................................ 44
Figura 8. Agente após um salto para trás e um salto para frente. ............................................. 45
Figura 9. Buraco de 3 blocos .................................................................................................... 47 Figura 10. Cenário para a primeira etapa de testes. .................................................................. 48 Figura 11. Agente executando "abaixar" indefinidamente ....................................................... 48 Figura 12. Agente em Loop ...................................................................................................... 49 Figura 13. Cenário da segunda etapa de testes ......................................................................... 49
Figura 14. Obstáculo que necessita de planejamento ............................................................... 50 Figura 15. Executando sequência planejada ............................................................................. 51 Figura 16. Alteração de estados. ............................................................................................... 52 Figura 17. Fase de testes da máquina de estados com flor ....................................................... 53
Figura 18. Fase de testes da máquina de estados sem flor ....................................................... 53
Figura 19. Alterando o estado ao colidir. ................................................................................. 54 Figura 20. Planejando passo 1. ................................................................................................. 65 Figura 21. Planejando passo 2. ................................................................................................. 65
Figura 22. Planejando passo 3. ................................................................................................. 65 Figura 23. Segundo exemplo, passo 1. ..................................................................................... 68
Figura 24. Segundo exemplo, passo 2. ..................................................................................... 68
LISTA DE EQUAÇÕES
Equação 1. ................................................................................................................................ 26
Equação 2. ................................................................................................................................ 26 Equação 3 ................................................................................................................................. 26
Equação 4 .................................................................................................................................28
LISTA DE QUADROS
Quadro 1. Tomada de decisão baseada na situação do personagem.. ...................................... 26
Quadro 2. Resultado do cálculo de entropia.. ........................................................................... 27 Quadro 3. Ações criadas. .......................................................................................................... 47 Quadro 4. Classe Main. Colocando limite de tempo alto, criaturas congeladas e 999 tentativas.
.......................................................................................................................................... 59 Quadro 5. Classe BasicTask. Linhas referentes a eliminar o agente depois de 40ms foram
comentadas. ...................................................................................................................... 59
Quadro 6. Classe LevelScene. Adicionando código para carregar arquivo de fase criado pelo
LevelGenerator. ................................................................................................................ 59 Quadro 7. Classe GeneralizerLevelScene. Adicionando blocos do LevelGenerator que não
estavam mapeados pela Engine. ....................................................................................... 60 Quadro 8. Código percorrendo a árvore. .................................................................................. 62 Quadro 9. Base de regras parte 1. ............................................................................................. 63
Quadro 10. Base de regras parte 2 ............................................................................................ 64 Quadro 11. Base de regras do segundo exemplo. ..................................................................... 67
LISTA DE ABREVIATURAS E SIGLAS
AI Artificial Intelligence
REALM A Rule-Based Evolutionary Computation Agent
that Learns to Play Mario
SUMÁRIO
1 INTRODUÇÃO ........................................................................................................... 13 1.1 PROBLEMATIZAÇÃO ................................................................................................ 13
1.1.1 Formulação do Problema .................................................................................. 13
1.1.2 Solução Proposta ............................................................................................... 14
1.2 OBJETIVOS .................................................................................................................. 14
1.2.1 Objetivo Geral ................................................................................................... 14
1.2.2 Objetivos Específicos........................................................................................ 14
1.3 METODOLOGIA .......................................................................................................... 14 1.4 ESTRUTURA DO TRABALHO .................................................................................. 15
2 FUNDAMENTAÇÃO TEÓRICA .............................................................................. 16 2.1 INTELIGÊNCIA ARTIFICIAL PARA JOGOS ........................................................... 16
2.1.1 O Aprendizado de Máquina .............................................................................. 17
2.1.2 Sistemas baseados em Regras ........................................................................... 21
2.1.3 Comportamento Orientado a Objetivos ............................................................ 23
2.1.4 Árvores de Decisão ........................................................................................... 24
2.1.5 Máquinas de Estado Finito ............................................................................... 29
2.1.6 Reinforcement Learning ................................................................................... 30
2.2 MARIO IA CHAMPIONSHIP ...................................................................................... 32
2.2.1 Sobre o Campeonato ......................................................................................... 32
2.2.2 Documentação ................................................................................................... 32
2.2.3 Competidores Anteriores .................................................................................. 33
2.2.4 Sistemas Similares ............................................................................................ 34
3 Desenvolvimento .......................................................................................................... 37
3.1.1 Implementação .................................................................................................. 45
4 CONCLUSÃO .............................................................................................................. 54
APÊNDICE A. ALTERAÇÕES NA ENGINE .................................................................. 59 APÊNDICE B. CÓDIGO PERCORRENDO A ÁRVORE .............................................. 61 APÊNDICE C. EXEMPLO DA UTILIZAÇÃO DA ÁRVORE. ..................................... 63
13
1 INTRODUÇÃO
Atualmente a inteligência artificial tem evoluído muito nos jogos, sendo em muitos
casos um requisito para que o jogo tenha qualidade, principalmente em casos de jogos de
estratégia onde sem inteligência artificial não haveria nenhum tipo de dificuldade. Muitos
outros jogos como de tiro em primeira pessoa, ação ou rpg utilizam da inteligência artificial
para alterar técnicas dos inimigos durante o jogo, fazendo com que o jogador não possa
simplesmente realizar as mesmas ações o tempo todo, pois os inimigos irão prevê-las em
pouco tempo e serão capazes de evita-las. Em outros jogos como The Sims ou Black & White
que são jogos de simulação, a inteligência artificial é sutilmente aplicada, mas faz com que o
jogo tenha toda a diferença. No caso do consagrado Black & White, ela é aplicada na criatura
que o jogador possui, e baseando em suas ações, nos itens que ele dá para a criatura comer ou
o que fazer, com pouco tempo de jogo ela consegue reagir sozinha, comer tais itens quando
avistá-los, ou evitar outras situações.
Na maioria dos jogos que empregam inteligência artificial os inimigos ou personagens
que acompanham o jogador ou já conhecem todos os itens do cenário previamente, o que dá a
sensação de ser muito artificial, pois se o personagem que acompanha o jogador, dotado de
inteligência artificial, nunca presenciou tal cenário, ele deveria não ser capaz de reconhecer os
itens ali presentes, não sabendo como interagir com eles. Em outros jogos o personagem ou
inimigo não adquire nenhum conhecimento durante o jogo, fazendo com que o mesmo sempre
aja da mesma forma, independente das condições do cenário, das ações tomadas pelo jogador
ou das ações tomadas por inimigos, no caso de um personagem que acompanha o jogador.
1.1 PROBLEMATIZAÇÃO
1.1.1 Formulação do Problema
No cenário atual de jogos, alguns deles implementam soluções baseados em
inteligência artificial para aumentar sua jogabilidade, mas outros acabam ignorando e
desenvolvendo personagens que têm comportamentos previsíveis ou altamente artificiais,
conhecendo totalmente o cenário antes mesmo de explorá-lo.
14
1.1.2 Solução Proposta
Desenvolver um agente inteligente, que seja capaz de executar sobre a plataforma de
Mario Bros, permitindo que ele descubra o cenário sem um conhecimento prévio sobre o
mesmo, sendo capaz de realizar tomada de decisões baseado em erros e acertos anteriores,
aprendendo com o cenário enquanto interage com o mesmo.
1.2 OBJETIVOS
1.2.1 Objetivo Geral
Criar um agente inteligente que aprende a jogar Mario Bros, permitindo ao
personagem principal reconhecer o cenário e descobrir formas de superar obstáculos sem
conhecimento prévio.
1.2.2 Objetivos Específicos
Estudar e descrever conceitos de técnicas de IA utilizadas para o projeto;
Analisar pesquisas sobre IA na área de jogos;
Analisar implementações do Mario IA Championship;
Realizar a modelagem do agente.
Desenvolver o agente e suas estratégias; e
Testar o agente responsável pelo aprendizado e analisar os resultados obtidos;
1.3 Metodologia
Neste trabalho foi realizada uma pesquisa em livros, artigos, outros TTCs, sites de
universidades, e no site oficial do Mario IA Championship, a fim de conhecer os possíveis
métodos e técnicas para serem usadas no desenvolvimento do agente. Foi realizada a
execução do software do Mario para verificar como funciona, os métodos que o framework
disponibiliza, a visão do personagem e como interagir com o cenário. Na parte de projeto do
agente, para a criação do diagrama de classe foi utilizado o software Enterprise Architect , e
as figuras referentes ao jogo foram retiradas da execução do software, bem como realizada a
codificação e testes do agente em três etapas, sendo elas a criação do agente sem uma árvore
de decisão para o planejamento das execuções, a segunda etapa adicionado a árvore de
15
decisão para o planejamento e por fim adicionado uma máquina de estados, permitindo
habilitar novas ações como a de atirar quando o agente estiver no estado com flor de fogo.
Em cada etapa, o agente era codificado e era executada a simulação em ambientes
específicos para que ele pudesse superar os obstáculos, e durante a execução era verificado se
as regras estavam sendo criadas conforme o planejado, se ele realmente estava criando regras
negativas no caso de uma ação ter sido prejudicial ao agente.
Na etapa com a árvore de decisão, foi também codificado o agente e testado se a
sequência de decisões era válida, ou seja, se realmente ele estava seguindo o caminho que
deveria seguir e aprendendo com seus erros e acertos e foi adicionada uma motivação ao
agente para chegar ao final da fase. Por último, foi adicionada a máquina de estados, e
verificado se ele realmente estava trocando de estado e habilitando as novas ações, bem como
iniciando seu aprendizado com essas novas decisões.
1.4 Estrutura do trabalho
Este documento está estruturado em quatro capítulos. O Capítulo 1, Introdução,
apresentou a visão geral do trabalho. No Capítulo 2, Fundamentação Teórica, é apresentada
uma revisão bibliográfica sobre árvores de decisão, sistemas baseados em regras, sistemas
especialistas, técnicas de inteligência artificial aplicadas em jogos eletrônicos, também
demonstrando sobre o Mario IA Championship, um pouco de sua documentação, sistemas
similares e técnicas utilizadas. O Capítulo 3 será destinado à documentação do trabalho, assim
como os diagramas necessários e a modelagem do agente, também será demonstrada a
metodologia utilizada. Neste mesmo capítulo é apresentado o desenvolvimento do agente,
problemas que foram identificados no meio do desenvolvimento e como foram resolvidos,
testes realizados e resultados obtidos. Por fim no Capítulo 4, apresentam-se as conclusões e
como resultados obtidos.
16
2 FUNDAMENTAÇÃO TEÓRICA
Neste relatório será realizada a pesquisa sobre árvores de decisão, sistemas
especialistas, máquinas de estados e suas aplicações em áreas da computação e jogos, bem
como algumas de suas utilizações para ajuda na decisão da melhor técnica e método possível
para resolver o problema.
2.1 Inteligência Artificial para Jogos
Um dos primeiros jogos a utilizar inteligência artificial é o pac-man, que se baseava
em uma máquina de estados finitos bem precária, onde podia apenas estar caçando o
personagem, andando pelo cenário ou fugindo, mas apesar de ser bem simples, foi um marco
para os jogos pela popularidade de um jogo que não era mais de jogador contra jogador, e sim
contra o computador. A partir daí até meados de 1990, a inteligência artificial em jogos
prosseguiu da mesma forma, até que foi lançado Goldeneye 007 onde o inimigo apesar de
utilizar uma máquina de estados, ganhava uma maior percepção do ambiente podendo
perceber se seus companheiros foram mortos. Essa percepção do cenário foi sendo mais
explorada e tornou-se o ponto central de jogos como Thief: The Dark Project ou Metal Gear
Solid (MILLINGTON, 2006).
Jogos de estratégia em tempo real foram tomando força em meados de 1990, como o
famoso Warcraft e com eles algoritmos de Pathfind cada vez mais utilizados, até que
surgiram como The Sims e Black&White onde utilizavam várias técnicas de IA, como redes
neurais para definir seus comportamentos, baseando-se em ações tomadas pelo jogador e
percepção do cenário (MILLINGTON, 2006).
Nos jogos mais modernos, a IA é utilizada para suprir três principais necessidades: A
habilidade dos personagens se moverem, a capacidade de tomada de decisões e pensar
taticamente ou estrategicamente (MILLINGTON, 2006).
Para aumentar a habilidade dos personagens se movimentarem pelo cenário são
necessários algoritmos de busca tentando criar os caminhos de forma que o personagem se
mova de forma mais natural possível, realizando o cálculo para achar a melhor rota antes de
realizar o movimento e para este fim, os algoritmos mais conhecidos são Djikstra, Waypoints
e A* (A estrela).
17
Em questão de tomada de decisão, tipicamente o personagem tem um grupo de
possíveis comportamentos e a IA é aplicada para escolher qual desses comportamentos deve
ser executado. Em jogos como Zelda, os animais utilizam técnicas bastante simples para
tomada de decisão, onde permanecem parados no estado aguardando até que o jogador se
aproxime demais, nesse caso eles mudam seu estado para mover-se para longe, utilizando
algoritmos de movimento. Em outros jogos como Half-Life 2, os inimigos necessitam de
decisões mais complexas e para isso utilizam de regras mais elaboradas para atingir seus
objetivos, encadeando uma série de ações para chegar no ponto desejado que muitas vezes é
o jogador (MILLINGTON, 2006).
Alguns jogos como F.E.A.R. dão uma maior autonomia para os inimigos serem
capazes de planejar as decisões a serem tomadas, adicionando objetivos de alto nível para os
agentes, onde não é programado exatamente como ele deve se comportar e sim que alcance o
objetivo definido. Em questão de baixo nível o programador cria as ações que os agentes
podem realizar. A relação entre objetivos e ações não são criadas explicitamente, deixando
com que eles aprendam por si só. (LIM, Mei. et al, 2010).
O último ponto principal em jogos é a escolha da estratégia a ser tomada, e só alguns
jogos utilizam esse ponto, mas é muito importante quando o computador tem que controlar
um grupo de personagens, onde decisões são baseadas no time inteiro, possibilitando a
formação de agrupamentos de combate e podendo preparar emboscadas, como no caso de
Half-Life 2 ou jogos de estratégia em tempo real, onde inimigos tentavam técnicas para cercar
o jogador e pegá-lo desprevenido (MILLINGTON, 2006).
2.1.1 O Aprendizado de Máquina
O aprendizado de máquina para a computação pode estar relacionada a dois tipos
diferentes de objetivos, o refinamento de habilidades, referente a executar a mesma tarefa
diversas vezes, e cada vez que é executada acaba sendo feita melhor que a vez anterior,
aperfeiçoando sua execução em questão de acerto ou velocidade. Em contrapartida, o
aprendizado pode ser visto como a aquisição de conhecimento baseado em informações
armazenadas, exemplos ou aconselhamento (RICH; KNIGHT, 1994).
A aquisição de conhecimento pode ser feita por memorização, ou seja, armazenamento
de informação que é a atividade mais básica da aprendizagem, nesse caso até um banco de
dados poderia ser considerado um sistema que aprende pela sua capacidade de guardar
18
informações, mas alguns programas utilizam essa base de dados para melhorar a sua
velocidade ou quantidade de acertos. Este caso é utilizado muito para ganho de desempenho,
por exemplo em jogos de tabuleiro que exijam a utilização do minimax muitas vezes é
inviável o cálculo de todas as possibilidades para uma jogada, assim é regularmente previsto
apenas algumas jogadas futuras, mas utilizando da aquisição de conhecimento por
memorização, o software executa as ações calculando só algumas jogadas como na aplicação
do minimax regular e grava em uma base de dados o resultado obtido daquele cenário. Em um
jogo futuro caso ele se depare com o mesmo cenário, ele terá gravado em sua base de dados o
resultado deste cenário, não necessitando da realização do mesmo cálculo novamente para
prever o resultado desta jogada, em uma árvore com muitos nós folha, saber previamente o
resultado de alguns deles pode resultar em uma poda significativa (RICH; KNIGHT, 1994).
Outro modo de adquirir conhecimentos é pelo aconselhamento, que é feito por outras
pessoas, mas este método exige primeiro uma forma de transformar essas informações de alto
nível em algo que o software consiga compreender. Este método funciona como um
programador criando um software, ele indica o que o software deve realizar em uma
linguagem de alto nível, então um compilador transforma essa linguagem de alto nível em
uma linguagem que o software consegue compreender. Caso surja uma nova necessidade, o
programador pode alterar o software, permitindo que ele seja capaz de realizar novas ações
que antes não podia (RICH; KNIGHT, 1994).
A aprendizagem a partir de experiência com solução de problemas, diferente de um
programa que utiliza a técnica de aconselhamento, ele não utiliza o mundo externo e ele não
tenta resolver problemas com conhecimentos que antes não estavam disponíveis, ele utiliza da
generalização de soluções anteriores para tentar obter o resultado de um problema anterior
resolvido e similar, mas não exatamente igual. Seu funcionamento mais especificamente, é
baseado em reajustar seus valores de entrada, tentando encontrar valores com que o resultado
final seja melhor que o anterior, seja aumentando ou diminuindo os pesos de coeficientes
(RICH; KNIGHT, 1994).
O aprendizado a partir de exemplos é uma forma que exige estímulos externos para
conseguir adquirir conhecimento, como um professor que ajuda uma pessoa a classificar itens,
corrigindo seus erros e apoiando seus acertos (RICH; KNIGHT, 1994).
19
2.1.1.1 Aprendizado em Jogos
O aprendizado é um ponto importante em jogos, ele tem a capacidade de criar
personagens mais interessantes, capazes de conhecer o meio em que estão situados e o jogo
acabar se adaptando ao jogador, por um lado isso dificulta a criação e modelagem dos jogos,
pois requer uma complexidade maior no desenvolvimento e na questão da aprendizagem, por
outro, facilita a parte de desenvolvimento no caso de mapeamento de regras, onde um cenário
muito complexo acaba tornando uma prática quase impossível mapear cada regra para cada
ação do jogador. Utilizando de técnicas de aprendizado, os personagens se adaptam ao
ambiente, ao jogador, escolhem as melhores técnicas, e independente de como o cenário
estiver, se a inteligência estiver bem implementada, os personagens serão capazes de reagir de
forma adequada. É possível classificar o aprendizado de máquina em alguns grupos,
baseando-se nos efeitos que esse aprendizado causa, no que será aprendido e em que etapa do
processo ele ocorre (MILLINGTON, 2006).
2.1.1.2 Aprendizado Online e Offline
O aprendizado de máquina para a computação pode ser classificado como Online e
Offline, onde o que varia é a hora que as informações são analisadas e o conhecimento é
adquirido. Para muitos casos o aprendizado Offline é a melhor escolha, pois ele é mais
simples de ser tratado, exige muita performance, mas não é executado junto com o código que
captura as informações e executa ações, e esse tipo de aprendizado é projetado para ser obtido
com um grande volume de dados, em um processamento em lote. Infelizmente para muitos
casos, é necessário que esse aprendizado seja incremental e dinâmico fazendo-se necessário
um aprendizado Online, ou seja, em tempo de execução (CORRÊA; CERQUEIRA, 2008).
O período que ocorre o aprendizado pode ser classificado como online, no caso de
jogos em que as técnicas de aprendizado são executadas enquanto o jogador está realizando
ações no jogo, ou pode ser off-line, que são executadas antes do jogo sair da empresa de
desenvolvimento, neste caso montando árvores de decisão e treinando as redes neurais em
tempo de desenvolvimento, ou durante as telas de carregamento dos jogos entre fases
(MILLINGTON, 2006).
Cada tipo de aprendizado tem suas vantagens e desvantagens, sendo a off-line mais
amplamente utilizada, onde os personagens não aprendem realmente durante o jogo, e sim
enquanto há pausas, ou em casos onde há o treinamento prévio dos meios de decisão enquanto
20
o jogo é desenvolvido, baseando em bases de dados de jogos anteriores para os personagens
escolherem as melhores técnicas e serem treinados. Nesse método, a maior desvantagem é que
os personagens realmente não aprendem em tempo de execução, necessitando de pausas ou
treinamento prévio, e as grandes vantagens são evitar consumo de processamento no
aprendizado, permitindo que o jogo utilize mais os recursos do computador, é mais fácil de
depurar e prever que o aprendizado online, pois no aprendizado online é difícil simular
exatamente o mesmo cenário. As vantagens do jogo com aprendizado online acabam sendo na
capacidade de aumentar o desafio enquanto o personagem está jogando, sem necessidade de
pausa ou treinamento prévio, o jogo acaba se adaptando melhor ao jogador dinamicamente
(MILLINGTON, 2006).
2.1.1.3 Aprendizado Intra-Comportamental e Inter-Comportamental
É traduzido como intra-comportamental todo aquele aprendizado que altera pequenas
porções bem específicas do personagem, não modificando o suficiente para ele ser capaz de
enfrentar novos desafios, mas para se modificar a ponto de realizar melhor as ações que ele
sempre realiza, sendo assim alguns ajustes de cálculos ou melhores rotas para seguir.
Enquanto o aprendizado inter-comportamental se refere a algo que é praticamente fantasia,
onde um personagem consegue gerar novos comportamentos praticamente do zero. O que é
muito praticado em jogos é um grupo de possíveis ações previamente programadas, onde
utilizando o aprendizado intra-comportamental elas vão sendo levemente aperfeiçoadas, ou
quando é utilizada uma árvore de decisão ele tem o grupo de possíveis ações e a árvore ajuda
na escolha de qual ação tomar (MILLINGTON, 2006).
2.1.1.4 Problemas no Aprendizado de Máquina
Alguns problemas são recorrente em implementações de Inteligência Artificial, que
em alguns casos os riscos de acontecer são altamente minimizados, e em outros casos eles
acabam acontecendo frequentemente. Quanto maior a complexidade do aprendizado, maior a
capacidade de tomada de decisão pelo personagem e mais abrangente é sua gama de decisões,
mas com isso, a chance de ocorrência de um erro, onde o personagem por algum problema no
conjunto de informações, ele acaba realizando ações que não correspondem ao desejado,
como ficar preso em algum lugar correndo contra a parede. O mais complicado nas técnicas
de IA é a depuração desses casos, pois foi um conjunto muito específico de ações e eventos
21
que acabaram fazendo com que o personagem tomasse aquela decisão, e para conseguir
realizar o mesmo conjunto é difícil (MILLINGTON, 2006).
Outro grande problema que pode acabar ocorrendo em softwares que utilizam
aprendizado é o chamado over-fitting, que ocorre quando o personagem é exposto à um
número de experiências com algo muito específico em comum, ou pouco genéricas, o que
acaba acontecendo dele aprender à lidar muito bem com essas situações, mas quando acaba
ocorrendo alguma situação que não compartilha dessa característica em específico, ele não
sabe lidar (MILLINGTON, 2006).
2.1.2 Sistemas baseados em Regras
O conhecimento pode ser representado de duas formas, ou da forma declarativa ou da
forma procedimental. Na forma declarativa o conhecimento é especificado, mas seu uso não é
fornecido, para poder usar um conhecimento na forma declarativa, é necessário o uso de
algum programa que especifique como utilizar este conhecimento, enquanto na representação
procedimental as informações para usar o conhecimento estão incluídas junto com o próprio
conhecimento, mas para utilizá-las é necessário um interpretador delas (RICH E; KNIGHT,
1994).
Sistemas que utilizam regras geralmente são usados para gerar um diagnóstico ou para
gerar uma ação ou cadeia de ações dependendo do estado atual do sistema, esse tipo de
técnica é muito usado para criar sistemas especialistas, e ele consiste em um banco de dados
contendo as regras, conhecido também como base de conhecimento e representa todo o
conhecimento que o sistema possui, e uma base de fatos que representa as entradas que serão
processadas pelas regras e um interpretador que é o pedaço do sistema responsável por
realizar o processamento, comparação e obtenção de conclusões. (RICH; KNIGHT, 1994).
Os sistemas baseados em regras começaram a ser pesquisados na década de 70 e foram
utilizados em jogos desde então, apesar de uma reputação de serem ineficientes e difíceis de
implementar, geralmente a utilização destes é uma abordagem um tanto quanto incomum pois
muitas vezes resultados similares podem ser adquiridos de maneira mais simples, utilizando
árvores de decisão ou máquinas de estados (MILLINGTON, 2006).
O ponto mais forte da utilização de sistemas baseados em regras em jogos é quando os
personagens precisam perceber e raciocinar sobre o mundo de uma maneira que o
22
programador não pode antecipar. Estes são constituídos de um banco de dados contendo todo
o conhecimento adquirido pelo personagem e um grupo de regras. Estas regras ficam
constantemente testando a base de dados e ativando gatilhos para ações, a maior diferença em
relação a máquina de estados é que é baseado em uma base de dados e os efeitos geralmente
são mais genéricos que apenas a transição de um estado para o outro (MILLINGTON, 2006).
Nos sistemas baseados em regras, caso uma regra ou um grupo de regras agrupadas
coincida com as informações do banco de dados, normalmente não é apenas efetuada uma
alteração no banco de dados e sim o disparo de uma nova ação, para ser testada por mais
regras e condições do sistema que muitas vezes irão falhar também, forçando o jogo a tomar
novas decisões.
A abordagem utilizada nesses sistemas geralmente define um objetivo final para o
personagem, e ele tenta várias regras para atingir esse objetivo enquanto falhar, e assim
encadeia um grupo de ações até que o objetivo seja alcançado.
Há dois tipos de métodos para a análise em sistemas baseados em regras, a cadeia de
avanço ou retrocesso. No caso do avanço, muito aplicado em jogos, o personagem começa
com uma base de conhecimentos previamente estabelecida, e repetidamente tenta testar as
regras até atingir o seu objetivo final. Em outro caso, quando é efetuado o retrocesso, a base
de conhecimentos está vazia, contendo apenas o objetivo final, e o computador irá executar
uma série de regras para tentar atingir esse objetivo, observando primeiramente o resultado
final do teste das regras, caso atinja o objetivo ele para neste ponto, caso não atinja, ele tentará
executar uma série de outras regras, anotando os resultados e modificando a base de dados
quando necessário, verificando as condições de trás para frente até que consiga atingir seu
objetivo (MILLINGTON, 2006).
Nos sistemas baseados em regras, uma regra é definida pela comparação de um objeto
com um possível valor, utilizando regras do tipo SE ENTAO para produzir um resultado, e
esse resultado pode ser encadeado com outras regras utilizando os operadores E e OU para
gerar resultados baseados em várias regras e testes. (RICH; KNIGHT, 1994).
No encadeamento para frente, um grupo de fatos que coincidem com regras resultam
em uma conclusão, por exemplo, se na entrada de dados há um grupo de fatos e que eles
coincidem com uma única regra, então a conclusão dessa regra é obtido e considerado como
resposta para essa entrada. Caso ocorra de mais de uma regra combinar com o fato, então é
23
causado um conflito, e deve ser aplicada uma técnica para a solução do mesmo. (RICH;
KNIGHT, 1994).
Para a solução de conflitos há algumas técnicas, uma delas é a definição de prioridade
para as conclusões, então se um fato pode ser encaixado em um grupo de regras, mas a
primeira tem uma prioridade maior que a segunda, a primeira regra é tratada como mais
importante e sua conclusão é a resposta do teste. Outra técnica para a solução do problema é a
verificação de qual regra se encaixa melhor com os fatos, por exemplo, se o sistema possuir
na regra 1 SE frio ENTAO aquecer, e possuir a regra 2 SE frio E fome ENTAO procurar
comida, e o fato ser “frio” e “fome”, como a segunda regra encaixa mais condições, então ela
deve ser seguida. Outros casos podem utilizar técnicas como analisar o conjunto de regras
mais novo. (RICH; KNIGHT, 1994).
No caso de encadeamento para trás, é quando uma hipótese é formulada, e deseja
reconhecer qual regra gerou esta hipótese, para realizar esse tipo de teste é necessário possuir
uma base de objetivos também. Primeiro, procura-se as regras que geram a conclusão o
objetivo contido na base de objetivos e depois de localizado, é testada as regras da base de
fatos para localizar a regra que mais se encaixa nesse caso. Dependendo da base de dados, o
encadeamento para trás pode ter grande ganho de desempenho sendo capaz de testar um
grupo menor de regras, mas em certos casos é impossível esse tipo de técnica, pois não há
objetivo definido ainda. (RICH; KNIGHT, 1994).
Metarregras são as regras sobre regras, em sistemas baseados em regras,
principalmente em sistemas especialistas, em alguns casos pode ocorrer de em certas
situações a classificação de prioridade das regras deve ser alterada, por exemplo, em sistemas
especialistas podem ter especialistas que tem um conhecimento mais profundo na área que
outros, e a opinião desses deve valer mais pois tendem à ser mais precisas, ou dependendo da
área que estiver sendo analisada, a prioridade deve ser a mais nova primeiro. As regras que
definem esse tipo de comportamento são chamadas de metarregras, e funcionam como uma
regra normal só que possuem prioridades maiores que as regras normais. (RICH; KNIGHT,
1994).
2.1.3 Comportamento Orientado a Objetivos
Comportamento orientado a objetivos é um termo que pode ser utilizado para qualquer
técnica que descreva personagens que têm desejos ou objetivos. Ao utilizá-los, o personagem
se tornará mais complexo, evitando tomar sempre decisões simples. Ao avistar um
24
personagem ele não irá simplesmente atacar, pois ele terá emoções e/ou objetivos, fazendo
com que naquele momento ele possa tomar uma decisão diferente para conseguir alcançá-lo.
Em jogos que implementam esse tipo de comportamento, o personagem tem várias ações
possíveis à serem executadas, e suas decisões são executadas baseado em seu estado
emocional naquele momento, um dos maiores exemplos deste tipo de abordagem é o jogo The
Sims, criado pela Maxis, e geralmente esse tipo de abordagem só é adotada quando há poucos
personagens em cena, e apesar do jogador controla-los, eles tem a capacidade de uma tomada
de decisão independente (MILLINGTON, 2006).
Em jogos que utilizam esta técnica, os personagens podem ter um ou mais objetivos
ativos ao mesmo tempo, e o jogo pode permitir que eles sejam completados, como no caso do
The Sims, ou eles podem permanecer ativos durante todo o jogo, só que a insistência de sua
execução é reduzida, ou seja, quanto mais ele está longe de satisfazer seu objetivo, mais
insistentemente a tomada de decisão tenderá à esse objetivo. Esses objetivos geralmente tem
uma pontuação, onde alguns tem mais peso no jogo que outros, tendendo esses à serem mais
importantes e sempre tentando ser completos primeiro (MILLINGTON, 2006).
2.1.4 Árvores de Decisão
A árvore de decisão é uma forma de representar de uma maneira gráfica as
consequências futuras de decisões, utilizando a estratégia de dividir para conquistar, partindo
um problema complexo em vários problemas menores e mais simples, que é aplicado nos
problemas menores, recursivamente. Sua capacidade de discriminação vem da divisão de
espaço em espaços menores, e esses espaços menores são associados a uma classe. Essas
árvores funcionam como um conjunto de regras se/então, onde é usado em sistemas
especialistas e sistemas de classificação, onde a entrada é um grupo de atributos e baseado em
um conjunto de regras, é tomada uma decisão (POZZER, 2006).
Árvores de decisão são representações do conhecimento, podem representar o
conhecimento de um modo simples, mas são meios poderosos de construir classificadores. No
processo de mineração de dados, as árvores de decisão são úteis para descobrir informações
baseando-se em uma base de dados. Uma árvore de decisão nada mais é do que um conjunto
de desvios condicionais que se aplicados em um registro, é capaz de classificá-lo. Sua
utilização mais interessante é de que, após ser treinada, ela pode ser ampliada a partir de
novos casos (TAN Pang-Ning; STEINBACH Michael; KUMAR Vipin, 2005).
25
Nesta árvore, cada nó representa um teste a ser feito em um atributo onde os ramos
representam possíveis valores para o resultado do teste e suas folhas representam as classes.
Para a construção de uma árvore de decisão é necessário escolher um atributo a ser testado,
criar os devidos ramos com os possíveis resultados para esse atributo e associar classes às
folhas (TAN Pang-Ning; STEINBACH Michael; KUMAR Vipin, 2005).
Em uma árvore de decisão há duas estratégias para aprender uma regra, Top Down,
que é mais geral para mais específico, ou seja, começa por uma regra mais genérica e
sequencialmente adiciona restrições ao antecedente para conseguir um resultado mais preciso.
E também há a abordagem Bottom Up, partindo de uma regra específica e ir repetidamente
removendo restrições do antecedente. (CALIFF; MOONEY, 2010).
Problemas que podem ser resolvidos de maneira adequada por uma árvore de decisões
são aqueles que possuem pares de atributo-valor, ou seja, que há um grupo de atributos fixos e
cada um possui alguns valores. Esses atributos são melhores trabalhados quando podem
possuir poucos valores, mas caso haja necessidade podem ser usados números contínuos.
(MELLO, 2011).
No paradigma Top Down de uma árvore de decisão, especialistas devem fornecer
informações, para montar um modelo de classificação, enquanto no modelo Bottom Up o
modelo é obtido baseado no relacionamento de variáveis e utilizando de mecanismos de
generalização (ZUBEN; ATTUX; 2010).
Os algoritmos mais conhecidos para árvores de decisão são ID3 e C4.5. O algoritmo
ID3 foi desenvolvido por Ross Quinlan em 1983 (PENG; CHEN; ZHOU, 2002) e pode ser
interpretado como “Inductive Decision Tree Algorithm 3” ou “Interactive Dichotomizer 3”
(MILLINGTON, 2006), e em sua essência, o ID3 constrói uma árvore de decisão com um
grupo de dados para treinamento, utilizando o paradigma Top-Dow, testando os atributos e
avaliando sua capacidade de se tornar um nó-raiz, caso os valores sejam discretos, e cria nós-
raiz para cada valor possível que esse atributo possa assumir (MELLO, 2011). Para tentar
conseguir o melhor modo para classificar um grupo de dados, tenta-se minimizar a
profundeza da árvore, para encontrar o nó-raiz mais importante o ID3 (PENG; CHEN;
ZHOU, 2002). Pode utilizar de uma medida chamada ganho de informação ou no índice de
Gini para conseguir encontrar o nó-raiz (SILVA, 2005).
26
A entropia é um método de medir o grau de pureza ou impureza de um nó, dado pela
Equação 1, enquanto o cálculo do ganho pode ser observado na Equação 2:
( ) ∑
Equação 1.
( ) ( ) ∑| |
| | ( )
Equação 2.
( )
Equação 3
Um exemplo de como pode ser usado o cálculo de entropia para calcular a árvore de
decisão pode ser descrito como, um personagem que tem três atributos, sendo eles saúde,
abrigo e munição, deve decidir se deve atacar ou se defender. O grupo de informações inicial
é mostrado no Quadro 1.
Saúde Abrigo Munição Decisão
Saudável Protegido Com munição Atacar
Machucado Protegido Com munição Atacar
Saudável Protegido Sem munição Defender
Machucado Protegido Sem munição Defender
Machucado Exposto Com munição Defender
Quadro 1. Tomada de decisão baseada na situação do personagem. Retirada do livro Artificial
Intelligence for Games, (MILLINGTON, 2006).
É aplicada a fórmula de entropia descrita na Equação 3 para apenas dois possíveis
resultados da decisão (caso houvessem mais resultados possíveis, deve ser utilizada a Equação
1), onde Pa é a proporção de ações de ataque no exemplo (ou seja, 2/5) e Pd é a proporção de
ações de defesa (ou seja, 3/5), então aplicando a fórmula o conjunto de dados tem 0,971 como
valor de entropia. Dividindo pelas respectivas entropias, temos como demonstrado no Quadro
2.
Saúde Saudável = 1.000 Machucado = 0.918
27
Abrigo Protegido = 1.000 Exposto = 0.000
Munição Com Munição = 0.918 Sem Munição = 0.000
Quadro 2. Resultado do cálculo de entropia. Retirada do livro Artificial Intelligence for
Games, (MILLINGTON, 2006).
Utilizando a fórmula do ganho, temos Saúde = 0.020, Abrigo = 0.171 e Munição =
0.420, é possível perceber que o ganho de munição é maior do que os outros, e ele deverá ser
o nó principal. Esse mesmo cálculo é usado para os nós abaixo recursivamente, podendo
assim montar uma árvore de decisão (MILLINGTON, 2006).
Figura 1. Exemplo de árvore de decisão para ação de personagem.
Retirada do livro Artificial Intelligence for Games, (MILLINGTON,
2006).
Para a aplicação do método ID3 em atributos contínuos, é necessário repartir o número
de valores em grupos de valores discretos, geralmente são divididos em apenas dois grupos,
onde é definido um valor de corte, valores acima deste vão para o grupo superior e abaixo vão
paga o grupo inferior, e essa divisão acaba gerando categorias que são utilizadas no processo
de cálculo normalmente como outro atributo qualquer (MILLINGTON, 2006).
Uma árvore de decisão pode muitas vezes não ser representada apenas por decisões
binárias, ou seja, um personagem quase morrendo não pode se comportar como um
personagem que sofreu apenas um dano leve, mas calcular uma árvore de decisão com vários
ramos pode acabar gerando um cenário onde a execução acaba sendo complicada. Para
resolver este problema, uma das técnicas adotadas é quebrar essa decisão de várias
possibilidades em apenas duas, e caso uma delas seja escolhida, testar o mesmo atributo com
um novo parâmetro de comparação. Por exemplo, na questão da análise comportamental de
um personagem, entre ele ser ferido ou estar quase morrendo, pode ser criada uma árvore
onde verifique se sua energia é cheia ou não, caso seja cheia ele toma a decisão de ataque,
caso não, a energia é reavaliada, se ela está quase nula ou não, caso esteja quase nula, pode
28
ser tomada a decisão de agir em total defesa, caso não, podem ser avaliados outros atributos
para permitir a tomada de decisão (MILLINGTON, 2006).
O índice de Gini foi desenvolvido por Conrado Gini em 1912, e ele é capaz de medir a
impureza de um nó, ou o grau de heterogeneidade de um conjunto de dados, é demonstrada na
Equação 4 (SILVA, 2005).
∑
Equação 4
Onde: Pi é a frequência relativa de cada nó e c é o número de classes.
Esse índice pode ser interpretado sabendo que quanto mais próximo de 1 mais impuro
é um nó, ou seja o número de classes uniformemente distribuídas no nó é maior. O oposto
significa que o nó é mais puro, quando ele se aproxima do 0 (SILVA, 2005).
Árvores de decisão incrementais podem ser bastante úteis se forem pré-processadas,
ou seja, se houver uma base de dados grande, ela é previamente gerada, e na hora da tomada
decisão elas são apenas percorridas, mas isso pode gerar problemas em jogos, pois esse
processo de gerar a árvore de decisão é computacionalmente custoso, e se cada movimento
que for dado tiver que gerar uma nova árvore de decisão, ela será muito otimizada na questão
da tomada da melhor decisão, mas o tempo de geração dela após algum tempo de jogo torna
impraticável essa técnica. Uma abordagem que pode ser utilizada, é gerar uma árvore de
decisão inicial, quando ocorre um evento, a árvore de decisão é percorrida até o encontro do
nodo final, caso esse nodo seja exatamente o esperado, nenhuma atualização é necessária, e o
novo evento pode ser só adicionado no grupo de exemplos. Caso esse evento novo exija uma
nova tomada de decisão, o nó final encontrado pode ser dividido em dois novos nós, criando
uma nova tomada de decisão e adicionando esse evento novo em um dos ramos, mas há o
risco de que, adicionando sempre novos exemplos na árvore, ela fique muito profunda, por
isso, deve ser analisado métodos que tornem a árvore o mais rasa possível, podendo assim
realizar a tomada de decisão mais rapidamente (MILLINGTON, 2006).
Um dos problemas que podem aparecer no treinamento de árvores de decisão que deve
ser analisado é o overfitting, ou seja, quando o grupo de dados de treinamento é muito grande,
a árvore pode ser muito profunda e pode ocorrer com que a decisão acabar sendo moldada de
forma que resultados formados fora do modelo de treinamento causem grande discrepância, e
as respostas baseadas dentro do grupo de treinamento se encaixem perfeitamente com o
resultado esperado (SILVA, 2005).
29
O algoritmo C4,5 é uma melhoria do ID3, desenvolvido pelo mesmo criador, Ross
Quinlan, e lida com uma série de problemas que existiam no ID3, como prevenção de
overfitting, evitando que a árvore cresça muito, reduz erros nas podas, é capaz de lidar com
podas após a árvore ter sido gerada, lida melhor com valores faltantes, escolhe a melhor
medida de atributo para o nó-raiz e melhora a capacidade computacional em relação ao ID3
(QUINLAN; 1993).
Jogos já utilizaram de árvores de decisão para representar o conhecimento com
sucesso.
O primeiro deles foi Black&White, onde as árvores representam experiências
anteriores que a criatura já teve ao longo do jogo, como por exemplo, se a criatura realiza uma
ação e o jogador a pune, ela gravará em sua árvore de decisão um novo nó, representando que
aquela nova ação tomada causou prejuízo. Ou também, dependendo do tipo de alimento que
ela ingere, se foi apropriado ou não, isso faz com que em uma ação futura a criatura possa
realizar a tomada de decisão baseado no resultado dessa ação anteriormente (POZZER, 2006).
Neste projeto, a utilização da árvore de decisão utiliza o mesmo conceito de
Black&White, quando o personagem se depara com uma nova situação, onde não estava na
árvore de decisão ou caso haja apenas resultados negativos nessa árvore, ele realizará uma
ação qualquer e analisará se seu resultado foi positivo ou negativo, podendo assim, adquirir
conhecimento e construir sua árvore de decisão. Caso a situação atual já esteja previamente
cadastrada na árvore de decisão e esse resultado seja positivo, será necessário apenas
percorrê-la, para gerar os mesmos resultados.
2.1.5 Máquinas de Estado Finito
Em 1955 Mealy escreveu um livro chamado A Method for Synthesizing Sequential
Circuits, que foi um dos primeiros a definir o conceito de máquina de estados, e em seu
conceito cada transição da máquina exigia o estado atual e uma entrada de dados. Nessa
mesma época, Moore criou uma forma de representação dos estados e suas transições de
forma diferente, onde o estado muda de um para o outro dependendo da entrada, mas não é
anotado nada acima da linha de transição, e a saída é gerada pelo estado final. As máquinas de
estados finitos geram uma saída que está contida dentro de um alfabeto, conhecido como
alfabeto de saída, que pode ser o mesmo alfabeto de entrada, as máquinas geram como
resultado o estado final, que é uma condição de aceitação da palavra de entrada ou não, e
30
também pode gerar uma saída contida na fita de saída. (BRITO; MARTENDAL; OLIVEIRA,
2003).
Uma máquina de estados finitos para a computação é um controlador de estados
finitos que tem uma cabeça móvel e percorre uma fita com informações de entrada, onde para
cada entrada, é gerada uma saída (KELLER, 2001).
Máquina de estado finito é um sistema algébrico de memória finita que se baseia no
conceito de “estados” e pode ser classificada em duas categorias, tradutora que também é
chamada de Autômato Finito com Saída, ou ela pode ser reconhecedora, que também é
conhecida por Autômato Finito. A diferença entre as duas categorias é que as máquinas de
estado tradutoras possuem apenas uma entrada e uma saída, enquanto para as reconhecedoras
de linguagens cada entrada possui duas saídas, uma para as sentenças válidas e outras para as
sentenças inválidas, que devem ser geradas a partir de gramáticas regulares (BRITO;
MARTENDAL; OLIVEIRA, 2003).
No contexto de jogos que utilizam máquina de estados, ela é um grupo limitado de
estados que são interconectados por transições, onde cada transição move o personagem de
um estado para outro, caso um grupo de condições seja satisfeita, fazendo com que este
personagem tome uma decisão. Na aplicação para o desenvolvimento deste projeto, será
necessário a utilização de uma máquina de estados onde representa com quais habilidades o
personagem está naquele momento, por exemplo, com a “flor de fogo” ou com o “cogumelo”,
e cada vez que um dos itens é pego, o estado do personagem é alterado, alterando seu estado
atual e fazendo com que novas decisões baseadas em uma árvore de decisão sejam tomadas.
2.1.6 Reinforcement Learning
O reinforcement learning, ou aprendizado por reforço, é um nome dado a um grupo de
técnicas baseados no aprendizado na experiência e repetição, que são formados por três
componentes, uma estratégia de exploração, ou seja, quando encontrar alguma situação
inesperada no jogo como ele deve agir, um mecanismo de feedback para dar uma resposta à
ação executada, se ela foi bem executada e o resultado foi positivo ou ocorreu algum
problema na execução, e por fim uma regra que seja capaz de realizar a ligação entre uma
ação e seu feedback, para poder ser executada novamente caso seja a melhor opção
disponível.
31
O reinforcement learning representa o processo de aprendizado na vida real, onde há
um ambiente com vários animais e eles devem aprender o que fazer e o que não fazer para
conseguir sobreviver. Com esta técnica de aprendizado, os agentes realizam ações e verificam
suas consequências, sejam elas positivas ou negativas (DAYAN; WATKINS, 2004).
Normalmente, nas modelagens para a utilização do reinforcement learning, o agente
não conhece o mundo, não sabe se suas ações resultarão em consequências boas ou ruins e
principalmente, o resultado imediato das consequências não pode ser o melhor, necessitando
que seja feito um cálculo de todas as respostas positivas e negativas de uma sequência de
ações para decidir se aquelas ações tomadas encadeadas foram melhor que outras (DAYAN;
WATKINS, 2004).
Formalmente, agentes que utilizam o reinforcement learning enfrentam o que é
conhecido como MDP, ou Markov Decision problem, que é o tipo de problema onde o efeito
de uma ação tomada em um estado depende apenas daquele estado, e não de um histórico, o
modelo MDP precisa de grupos de estados possíveis, um grupo de ações possíveis, um
resultado positivo ou negativo e uma descrição do efeito de cada ação em cada estado
(JAAKKOLA; SINGH; JORDAN, 2002);
Uma das técnicas mais comuns em jogos para o aprendizado por reforço é o método
Q-Learning, onde ele trata o cenário todo como uma máquina de estados, e esses estados
devem possuir todas as informações necessárias sobre ambiente, personagens, itens, etc...
Então se um personagem está em duas situações exatamente iguais, só que com quantidades
diferentes de munição, por exemplo, e isso for importante para o aprendizado, o algoritmo
considerará isso como dois estados diferentes. O estado atual pode ser salvo apenas como um
número ou uma letra, para o algoritmo isso é indiferente, mas para o jogo é essencial que ele
consiga fazer o processo oposto, sendo capaz de traduzir este identificador para um estado
com informações do personagem e cenário (MILLINGTON, 2006).
No caso do Q-Learning em alguns casos um estado leva para ele mesmo indefinidas
vezes, até que o cenário ou alguma situação ocorra e ele possa trocar para um próximo estado,
por exemplo, caso o personagem esteja num jogo de tiro com pouca vida, e está procurando
por algo que recupere sua vida, caso ele veja um inimigo por perto, sua atitude (por ter
aprendido antes), será de se esconder, então na situação “pouca vida”, “inimigo por perto”,
32
”local X”, a ação é continuar escondido, e só irá alterar quando o inimigo sair de perto, nesse
caso, para ele prosseguir.
2.2 Mario IA Championship
2.2.1 Sobre o Campeonato
Mario IA Championship é uma competição que começou em 2009 e foi criada por
Julian Togelius, Sergey Karakovsky, Jan Koutnik e Jürgen Schmidhuber, onde seu objetivo é
criar um agente programado em Java ou Python que seja capaz de chegar ao final das fases
com maior velocidade possível, chamando esse tipo de jogo de GamePlay Track, os
programadores podem se inscrever gratuitamente, tendo feito um certo sucesso na época que
foi lançado, os criadores abriram duas novas categorias, Level Generation Track, que consiste
em os competidores programarem um cenário em java, codificando suas características, e
outras pessoas jogam esses níveis e votam pelo melhor nível, e a Turing Test Track, onde os
programadores desenvolvem agentes que executam as fases e outras pessoas votam pelo
personagem que tem a maneira de jogar mais próxima de um ser humano. No modo
GamePlay Tracking, para evitar personagens muito lentos na execução, os criadores
definiram um tempo limite de 40ms para a execução do movimento do personagem em um
MacBook PRO com 2GHz Core 2 Duo (KARAKOVSKIY; TOGELIUS, 2012).
A engine de Mario IA é baseada no jogo Mario Infinity para computador e utiliza dos
mesmos conceitos de física, colisão e itens do jogo, mas o Mario IA Championship permite
com que os jogadores desenvolvam um agente para conseguir interagir com o cenário,
analisando-o e realizando a tomada de decisão, para chegar ao seu objetivo com menor tempo
possível. Todos os seus códigos são open-source, permitindo que os competidores possam
analisar como é calculada a física, analisar como são obtidas as informações e até enviar
sugestões de melhorias nos códigos.
2.2.2 Documentação
Os desenvolvedores da competição desenvolveram uma interface que o agente deve
ser implementado para poder ser compreendido pela engine chamada de
ch.idsia.agents.Agent, enquanto todas as informações sobre o cenário podem ser obtidas pela
classe ch.idsia.benchmark.mario.environments.MarioEnvironment, que implementa a
33
interface Environments, útil para caso o jogador queira desenvolver seus próprios cenários
(KARAKOVSKIY; TOGELIUS, 2012);
A interface Environment provê métodos que retornam uma matriz de 21x21, que
representa o cenário visto pelo personagem principal, onde ele sempre está localizado na
posição 11x11, e nessa mesma interface, há métodos capazes de interagir com o ambiente,
coletando informações, como o getEnemiesPos, que retorna um array de coordenadas dos
inimigos. Nessa interface também permite o uso do método getMarioState, que contém
informações como o tempo restante e o tempo limite do cenário (KARAKOVSKIY;
TOGELIUS, 2012);
Na classe Environment, é possível obter as informações de localização dos inimigos
pelo método getEnemiesFloatPos, enquanto para saber se o agente consegue realizar a ação
de pulo, pode utilizar do método isMarioAbleToJump, ou caso necessite o reconhecimento do
estado dele ou seja, se ele possui uma flor de fogo ou não, pode-se utilizar o método
isMarioAbleToShoot (KARAKOVSKIY; TOGELIUS, 2012);
Há outras classes úteis que podem ser usadas para o desenvolvimento como
ch.idsia.benchmark.mario.engine.Recorder que permite salvar um arquivo contendo as
informações sobre a última execução do jogo, e combinada com a classe Replayer pode
realizar novamente a execução (KARAKOVSKIY; TOGELIUS, 2012);
Para a utilização de seus códigos e aprendizado, o Mario IA Champioship
disponibiliza uma interface chamada LearningAgent, onde ela deve ser estendida, e possui os
métodos básicos para criar um agente capaz de ter alguma inteligência artificial, onde deve ser
implementado em learn. Nesse método, é possível executar os códigos para localização do
cenário, obtendo a matriz contendo os inimigos ao redor do personagem, e no agente pode ser
implementada a árvore que representa o conhecimento (KARAKOVSKIY; TOGELIUS,
2012);
2.2.3 Competidores Anteriores
O campeonato tem uma filosofia de tentar manter o mais transparente possível,
liberando assim em sua documentação oficial algumas técnicas usadas por outros
competidores em versões passadas do evento, e como o objetivo é passar o mais rápido os
níveis sem ir atrás de bônus ou outros itens, a maior parte dos algoritmos enviados e
34
vencedores foram baseados em buscas de caminho, principalmente utilizando algoritmos A*,
por ser rápido e flexível (KARAKOVSKIY; TOGELIUS, 2012);
A técnica utilizada por trás dos algoritmos de buscas de caminho, que acabou sendo a
do vencedor do primeiro campeonato Robin Baumgarten, basicamente funcionava em três
partes, primeira simulavam a física, pelo fato do código ser aberto, é possível verificar como a
engine calcula a física, então os algoritmos faziam simulações de física com forças do salto e
velocidades diferentes conseguindo prever onde o personagem aterrissará ao final do salto.
Após isso, o segundo passo é executar o algoritmo para realizar a busca dos caminhos
possíveis, verificando não apenas onde o personagem aterrissará, mas seus vizinhos e seus
próximos passos. Por fim, é realizado uma otimização das variáveis porque há a restrição de
40ms, então o algoritmo ficava tentando calcular todas os possíveis saltos e movimentos,
quando chegava muito perto do tempo limite de 40ms, ele parava sua execução, independente
se tinha encontrado a solução ótima ou não, e executava a melhor do grupo de soluções que
ele havia localizado (KARAKOVSKIY; TOGELIUS, 2012);
2.2.4 Sistemas Similares
No seu pacote básico de demonstração, Mario IA Championship disponibiliza um
agente extremamente simples, que é capaz de realizar o aprendizado utilizando algoritmos
genéticos, com a classe chamada MLPESLearningAgent, onde são executadas uma série de
ações aleatórias inicialmente, é escolhido o melhor de sua geração e executada essa ação, com
objetivo de tentar chegar o mais longe.
Erek Speed, um dos participantes do concurso no ano de 2009 implementou um agente
que utiliza de um sistema baseado em regras para realizar a tomada de decisões e evolui com
algoritmos genéticos, onde o agente mapeia toda a matriz visível como suas regras, apesar de
uma abordagem interessante ele foi desclassificado do jogo por excesso de uso de memória,
pois com a utilização de algoritmos genéticos e mapeando regras para a matriz completa, seus
arquivos XML com as informações para o agente ultrapassavam os 100Mb.
(KARAKOVSKIY; TOGELIUS, 2009);
Sergio Lopez também participante da competição de 2009 desenvolveu um sistema de
regras altamente simples, mas não com o intuito de aprendizado sobre o cenário, ao contrário
de Erek Speed, onde o personagem principal deveria responder apenas duas questões, se era
capaz de saltar e qual o tipo de pulo ele deveria executar, e calculava a posição de sua queda
35
apenas baseado em heurísticas e informações da classe Environment, também levando em
consideração o valor de perigo, que é a verificação se está próximo de encontrar o inimigo e a
necessidade de salto, para quando houver um buraco, realiza-la sempre que possível.
(KARAKOVSKIY; TOGELIUS, 2009);
O projeto REALM (A Rule-Based Evolutionary Computation Agent that Learns to
Play Mario) utiliza de sistemas baseados em regras para realizar o aprendizado, onde ele
analisa algumas variáveis, como por exemplo, se o agente consegue saltar, se o inimigo está
na frente dele ou se há um buraco, onde o possível resultado delas é verdadeiro, falso ou não-
relevante. Neste projeto foi criados grupos de ações, sendo eles do tipo progresso, ataque,
esquiva ou de evolução. O tipo progresso é o objetivo de ir adiante, com destino ao final da
fase, e ele utiliza de ações como salto, andar e correr, enquanto do grupo de ataque, seu
objetivo é destruir um inimigo, com flor ou saltando sobre sua cabeça, do grupo esquiva o
objetivo é desviar de inimigos que se aproximam, enquanto o grupo de evolução o objetivo é
pegar flores e cogumelos para melhorar as chances do agente passar a fase (BOJARSKI;
CONGDON, 2010).
No REALM, é criada uma tabela contendo as condições que o agente se encontra, se
consegue saltar ou se há inimigo a frente, caso as condições se encaixem com o estado atual, o
agente altera seu objetivo para um dos citados, como por exemplo, atacar. Caso nenhuma das
condições aconteça, ele toma a opção padrão que é progresso, ou seja, alcançar o final da fase,
e caso duas condições coincidam, ele utiliza a mais específica. Neste projeto, foi
implementado também a opção de carregar as regras digitadas por um humano, da mesma
forma que o agente utiliza elas, e para sua escrita, deve ser descrito as condições (utilizando 0
para falso, 1 para verdadeiro, ou não codificando para indiferente) (BOJARSKI; CONGDON,
2010).
Quando o agente decide um plano de ação, no caso progredir, atacar, esquivar ou
tentar pegar um item, e para cada plano de ação há um peso de cada inimigo e objeto do
mapa, no caso do ataque os inimigos tem um peso maior que os objetos identificando assim
que é naquele ponto que o agente deve interagir. Após todas as informações coletadas, do
plano de ação e dos pesos dos objetos, são enviadas para o simulador interno, que define o
melhor caminho para chegar em seu objetivo, utilizando A*. Para o aprendizado, faz-se da
utilização do ECJ, um sistema de computação evolucionária em java, onde é gerada as ações
com aproximadamente 50 indivíduos e 20 ações, sorteadas com 40% da condição ser
36
“indiferente”, são executadas e verificados os resultados para ver qual o melhor deles. Um dos
grandes problemas do REALM é o tempo necessário para a tomada de decisão de uma ação
(BOJARSKI; CONGDON, 2010).
37
3 DESENVOLVIMENTO
Neste capítulo será apresentada a lógica e o desenvolvimento de um agente utilizando
a engine do Mario AI, onde foi dividido em três etapas de desenvolvimento, cada uma
utilizando uma técnica de IA e verificando os resultados de testes para validar se a lógica
estava implementada corretamente.
Para o desenvolvimento do agente foi necessário estender a classe BasicAIAgent, que
provê alguns métodos que devem ser implementados. O mais importante deles é o
getAction(), onde exige o retorno de um vetor de dados booleanos que simboliza a tecla
pressionada, e é executado aproximadamente 15 vezes por segundo, e dentro desta ação é
definido o que o agente deve executar.
A classe Mario de ch.idsia.benchmark.mario.engine.sprites tem as teclas que o agente
consegue interpretar mapeadas, sendo elas KEY_LEFT, KEY_RIGHT, KEY_DOWN,
KEY_JUMP, KEY_SPEED e KEY_UP, também informa algumas informações importantes
sobre o agente como se está com o jogo em andamento STATUS_RUNNING, caso tenha sido
morrido STATUS_DEAD ou se terminou o cenário STATUS_WIN.
No pacote ch.idsia.benchmark.mario.engine.sprites, podem ser destacadas algumas
classes importantes, como SPRITE, onde mapeia os possíveis blocos do jogo, sendo estes
inimigos, simples blocos, espaços vazios ou cogumelos por exemplo, onde cada um contém
um código único. Podem ser destacados blocos importantes como KIND_GOOMBA mapeado
pelo código 80, ou KIND_MUSHROOM mapeado pelo código 2. Durante a execução do jogo,
pode ser percorrida a matriz do campo de visão do agente, verificar os códigos obtidos e
compará-los com a lista de tipos nos Sprites. Alguns outros blocos como os blocos de chão de
borda, ou seja, quando é uma borda lateral são tratados na matriz com o código -125, e
utilizando a classe GeneralizerLevelScene, pode ser convertido para um grupo de blocos de
chão, que é agrupado com os -60 (chão normal), todos eles representados pela constante
BORDER_CANNOT_PASS_THROUGH.
Outras duas classes úteis que podem ser encontradas no pacote sprites, são
GreenMushroom e Mushroom, onde podem ser obtidas informações em relação à velocidade
e se está no chão ou caindo, por exemplo.
38
Em Mario IA, como citado anteriormente, é possível utilizar a classe Environment
para obter uma matriz 21x21 onde no centro dela está posicionado o personagem principal. O
método para a realização dos testes pode ser baseado em uma árvore de decisão ou em um
sistema baseado em regras.
Na Figura 2 é possível verificar os casos de uso do agente, onde demonstra que o agente pode
realizar as ações de movimento, ou seja, nos casos onde não há regras ele irá se mover
aleatoriamente, a fim de conseguir identificar quais os efeitos daquele movimento naquela
situação, e com isso poder criar uma nova regra. O ato de criar uma nova regra se refere ao
verificar as consequências que um movimento trouxe, se ela foi boa ou ruim. Ao utilizar
regra, abrange verificar se a regra é positiva ou negativa e executá-la, para a árvore de
decisão, a utilização da regra é referente a utilizá-la em cada nodo da árvore.
Figura 2. Casos de uso do agente
Mover se refere a toda ação que o personagem realiza de deslocamento pelo cenário, e
inclui as ações de “saltar para frente”, “saltar para trás”, “saltar para cima”, “saltar para frente
correndo”, “saltar para trás correndo”, “andar para frente”, “andar para trás”, “abaixar-se”,
“correr para frente”, “correr para trás”. Caso o personagem esteja num estado diferente, ou
seja, ele tenha coletado uma flor de fogo ele é capaz de atirar fogo.
39
O agente é capaz de perceber o cenário de três formas diferentes, usando o método
getMergedObservationZZ, este recebe por parâmetro qual a forma de visualização do cenário,
1, 2 ou 0. Na forma 2, o agente é capaz de perceber apenas se ele consegue atravessar um
bloco ou não, no modo 1 libera algumas outras informações como a distinção de blocos
quebráveis e não quebráveis (mas não difere um bloco de chão e um bloco de parede), se um
local está um inimigo do tipo casco com espinhos ou tartaruga, e por fim, no modo 0 que será
utilizado para a implementação do agente, ele consegue perceber todos os tipos diferentes de
blocos ou inimigos adjacentes, onde cada número representa um tipo de bloco específico
(sendo -90 um cano e -128 uma parede curva, por exemplo), como representando na Figura 3.
Blocos fora do cenário são sempre vistos com o código 0.
Figura 3. Imagem do jogo com matriz
Para a implementação do agente, é necessário um sorteio com as possíveis ações que o
agente pode tomar e conforme a ação escolhida avaliar se o Mario morre ou não, criando uma
regra positiva ou negativa.
40
Inicialmente no projeto foi cogitada a utilização de uma matriz de 3x3 para representar
a visão do personagem, pois sendo uma matriz pequena a quantidade de vezes que uma
mesma visão se repetia era maior e a quantidade de regras necessárias para ultrapassar os
obstáculos era menor. Após algumas execuções de cenários criados pela própria engine foi
verificado que era necessária a execução de saltos de até quadro blocos adiante e atrás, por
este motivo a visão foi alterada para uma matriz 9x9.
As regras são criadas em cima da visão do personagem (neste caso, os 81 blocos que o
circundam) e da ação tomada por ele, sendo que estas regras podem ser positivas ou
negativas.
Se o agente se encontra em uma situação nova, ele deve sortear uma de suas ações e
verificar se ela causou um prejuízo ou não, caso tenha causado danos ao agente, o mesmo
guarda a matriz ao seu redor (sua visão), caso não tenha causado danos será guardado como
uma regra positiva, permitindo assim ao agente que caso se depare com a mesma situação
novamente ele seja capaz de verificar em sua base de regras se há uma regra negativa naquela
situação e não executá-la novamente, ou se há uma regra positiva e deve executá-la para
prosseguir com o cenário e ir aprendendo com o mesmo.
A primeira etapa da implementação do agente não foi abrangido a árvore de decisão
para tomada de decisão e nem a máquina de estados. Foi utilizado inicialmente apenas um
sistema baseado em regras mapeando a matriz de visão ao seu redor.
No projeto foi realizada a comparação entre sistemas de regras de matrizes menores
que 9x9, mas foi visto que não era possível prever todos os obstáculos, onde em uma matriz
3x3, por exemplo, se o agente acabava verificando a sua frente um buraco ele era incapaz de
prever se após aquele bloco havia mais um bloco de buraco, se era um cano ou se era chão.
Matrizes superiores a 9x9 acabavam causando overfitting, pois uma moeda no canto superior
direito poderia acabar influenciando na decisão do agente, apesar da mesma não ter
significado nenhuma para a decisão.
Em casos de matrizes onde o agente não se encontrava no centro, sendo ele
posicionado no canto mais esquerdo da mesma, por exemplo, quando o agente necessitava da
execução de um salto para trás, ele era incapaz de verificar o que estava atrás dele.
41
No exemplo da Figura 4, caso o a gente possuísse a regra representando que no caso (0
e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0
e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e -90 e 0 e 0 e 0 e 0 e 0 e -128 e -60 e -60 e -60 e -60 e -60 e -60
e -60 e -60 e -125 e -60 e -60 e -60 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e
0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 => “Salto para Frente”), como resultado desta execução,
é apresentado o cenário citado na segunda parte da Figura 4.
Figura 4. Execução da regra
Se o agente não for capaz de encontrar nem a regra específica para determinada
situação e nem uma regra próxima, verifica suas regras negativas, ou seja, todas as regras que
foram executadas em outras vezes e acabaram dando errado, e sorteia na sua roleta de ações
uma ação que não seja uma dessas regras negativas.
Para a exemplificação de como acontece o aprendizado baseado nas regras, o agente
encontra-se perto de um buraco como mostrado na Figura 5, e não possui nenhuma
informação em sua base de regra sobre a ação que deve ser tomada, então ele realiza um
sorteio em cima de suas possíveis ações.
42
Figura 5. De frente para um buraco, foco só ao redor do agente.
Neste exemplo, baseando-se no cenário citado na Figura 5, o personagem como não
possui nenhuma regra sorteou a ação “Andar para Frente”, o que fez cair no buraco, causando
dano, então anotou em sua base de regras (0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e
0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e -60 e -60 e -60 e -60 e -
128 e 0 e 0 e 0 e -60 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0
e 0 e 0 e 0 e 0 e 0 => NÃO “Andar para Frente”). Ao deparar-se novamente com o mesmo
cenário, onde ele se encontra de frente com um buraco, sorteará uma de suas possíveis ações,
exceto “Andar para Frente”, caso ele sorteie “Saltar para Frente” e caia em um local seguro,
guardará a regra que (0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e
0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e -60 e -60 e -60 e -60 e -128 e 0 e 0 e 0 e -60 e 0
e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 e 0 =>
“Saltar para Frente”).
Observando a situação sem planejamento, o agente consegue realizar apenas ações que
estão em sua matriz 9x9 sendo analisada, mas para situações com obstáculos mais complexos
que necessitem que o personagem volte algumas casas para tomar outro caminho é impossível
que ele realize sem o planejamento. Para a criação do planejamento é necessário que seja
definido o objetivo de chegar o mais para a direita possível, para evitar situações onde o
personagem acabe estando em uma parede e seu planejamento faça-o retornar
indefinidamente, pelo fato de ser uma ação que não causa dano.
Na segunda etapa do projeto, o agente foi capaz de realizar planejamento antes da
tomada de decisão da ação que executa, para conseguir superar situações onde seja necessário
43
um encadeamento de ações para a realização da ação, esse planejamento é executado para
uma sequência de quatro ações seguintes. Nesta etapa, o planejamento executado pelo agente
fpo realizado baseando em uma árvore, onde ele verifica se há uma regra para a situação
atual, como faria anteriormente, caso ele tenha essa regra, é adicionada na árvore do
planejamento, executada a simulação (verifica se ele executar essa ação onde ele irá parar), e
cria um novo nodo na árvore, tendo como posição inicial a posição simulada. Se ele conseguir
chegar ao quarto passo da árvore de decisão com sucesso e sua posição final for mais à direita
do que a posição inicial, significa que a árvore gerou um resultado válido, e ele segue o
caminho planejado. Caso não consiga chegar ao final da árvore com o planejamento, sorteia
uma ação a executar como antes, executa a mesma e anota seu resultado como positivo ou
negativo.
Figura 6. Obstáculo que exige planejamento.
Para visualização do funcionamento do planejamento da ação, na Figura 6 é possível
ver um cenário onde é necessário o planejamento devido à complexidade do obstáculo a
superar. Neste caso é necessário que o agente realize dois saltos em sequência para conseguir
superar o obstáculo. Primeiro será realizada uma simulação simples, sem planejamento para
demonstrar o comportamento de um agente nesta situação, e após isso, demonstrando a
execução com planejamento.
Para conseguir esse tipo de situação é possível adicionar uma árvore de decisão para o
agente realizar o planejamento, que consiste em antes de realizar seus movimentos realizar
uma simulação, ou seja, antes de executar cada movimento ele realiza a simulação do
próximo movimento, toma a próxima decisão baseado em suas regras, realiza a outra ação e
44
assim por diante, por fim, se na simulação ele não sofreu dano ele pode executar esta
sequência de ações que garante que no último passo ele esteja vivo, caso ocorra algum erro na
simulação, tenta realizar outra ação.
Na Figura 7 é demonstrada como funciona uma árvore de planejamento na situação da
Figura 6, para permitir que o agente consiga se locomover para frente, evite ficar executando
diversos movimentos e acabe sempre na mesma situação.
Figura 7. Árvore de Planejamento
Na Figura 8 o agente estava na posição demostrada na Figura 7, começa a executar seu
planejamento baseado em regras que já havia adquirido, ele acaba realizando a simulação do
salto para trás, e depois de andar para frente, ao final desse processo verifica se ele acabou se
locomovendo mais para a frente que sua posição inicial, nisso percebe que não houve
alteração do movimento (pois na simulação ele acaba caindo e voltando para a posição
inicial), então descarta essa situação e tenta outra ação para simulação, que no caso é o salto
para cima, nisso percebe que sua situação é anterior a situação atual, então também descarta,
por fim , realiza a simulação com a ação de “saltar para frente 1 bloco” e percebe que
consegue realizar. Ele finaliza a simulação (se esta for de dois passos) e executa em sequência
o que foi planejado.
45
Figura 8. Agente após um salto para trás e um salto para frente.
Por último foi desenvolvido uma máquina de estados, onde cada estado representa se o
agente possui algum item especial, como a pena, fazendo com que ele comece uma nova base
de regras para cada estado, pois possui uma nova gama de ações possíveis.
3.1.1 Implementação
Para este projeto, inicialmente foi criado um agente, sendo este a classe “MeuAgente”,
que implementa a interface “Agent”, o que faz com que a classe “MeuAgente” necessite de
um método chamado “getAction”. Este método, como descrito anteriormente é chamado em
torno de 45 vezes por segundo pela engine do MarioAI, e esta engine requisita como retorno
um grupo de teclas pressionadas que o agente está executando, sendo essas: “UP”, “DOWN”,
“RIGHT”, “LEFT”, “SPEED” e “JUMP”, onde mais de uma dessas pode estar sendo
executada ao mesmo tempo.
Após a criação do agente, ele foi registrado na classe principal, ou seja, para quando a
engine começar a processar, esta saber qual agente deverá ser chamado. Também, como
opção da engine o tempo limite para o jogo foi alterado para 999999 segundos, mais do que o
suficiente para toda a simulação necessária. Além disso, o numero de vidas teve que ser
colocado para 9999, permitindo assim a simulação não ser cancelada enquanto o agente está
em fase de aprendizado. O número de inimigos foi definido para “none” para os testes
iniciais, e quando os mesmos foram adicionados, a opção “frozen” foi habilitada, pois no
escopo do projeto estava definido que não haveriam inimigos móveis no cenário.
Para iniciar o projeto foi necessário realizar algumas alterações na engine do Mario
AI, sendo necessário criar o código para a engine carregar um nível criado para testes.
46
Atualmente a engine permite criar cenários, mas não era permitido carrega-lo para simulação
(o gerador de nível era utilizado para criação de cenários para outra parte do campeonato,
onde era destinado a competição de criação do melhor cenário). O cenário na simulação
normal onde estava sendo desenvolvido era gerado baseado numa semente aleatória e na
dificuldade do nível, sendo esse não adequado para realização dos testes.
Outra alteração necessária foi após permitir a simulação carregar um cenário, a engine
era incapaz de localizar alguns blocos como do cano e acabava ocasionando erro na
simulação, então foi necessário implementar a localização desses blocos.
A engine, como previsto no projeto, chama o método “getAction” aproximadamente
15 vezes por segundo, e dentro deste método é enviado parâmetros referentes ao agente (como
posição atual, se está vivo ou morto, se tem a flor de fogo ou não).
Para realização dos testes de cada etapa do projeto foi criado um grupo de cenários
onde era previsto que o agente deveria ser capaz de superar, e no caso do teste sem a árvore
de decisão, casos onde o agente não seria capaz de superar.
Para a primeira parte do projeto, que foi definida como o Mario conseguir se
locomover e criar regras sem utilizar uma árvore de decisão de planejamento, foi criado um
grupo de possíveis ações que o agente poderia realizar, sendo essas ações nada mais do que
um agrupamento das teclas pressionadas por um período de tempo (quantidade de vezes que o
getAction é acionado), e esse grupo de ações ser o necessário para superar o obstáculo. As
ações criadas segue no Quadro 3:
Ação Teclas Pressionadas Ciclos
andarFrente KEY_RIGHT 3
andarTras KEY_LEFT 3
pularFrente1 KEY_RIGHT, KEY_JUMP 3
pularFrente2 KEY_RIGHT, KEY_JUMP 6
pularFrente3 KEY_RIGHT, KEY_JUMP 9
pularFrente4 KEY_RIGHT, KEY_JUMP, KEY_SPEED 6
pularTras1 KEY_LEFT, KEY_JUMP 3
pularTras2 KEY_LEFT, KEY_JUMP 6
pularTras3 KEY_LEFT, KEY_JUMP 9
47
pularTras4 KEY_LEFT, KEY_JUMP, KEY_SPEED 6
olharCima KEY_UP 6
abaixar KEY_DOWN 6
pular KEY_JUMP 3
Atirar KEY_SPEED 3
Quadro 3. Ações criadas.
As ações referentes a pular tem um número após elas que é a quantidade de quadrados
que o Mario deve se deslocar caso esteja em um terreno plano, dessa forma fica mais fácil de
depurar e aumentar o nível de ações possíveis, fazendo com que ele possa superar obstáculos
como buracos de 1 quadrado (usando o pularFrente2) ou obstáculos onde ele deve subir em
cima de um bloco (pularFrente2), por exemplo, enquanto a ação “Atirar” só está disponível
caso o agente esteja no estado “Com Flor”.
A quantidade de ciclos definidos pelas ações foi determinado como o mais adequado
para abranger um grupo de ações necessárias para superar os obstáculos, mas nada impede
que novas ações sejam criadas levando em consideração outras necessidades como pular
atirando.
3.1.1.1 Desenvolvimento do Agente sem árvore de decisão para planejamento
Um dos problemas verificados nos testes do agente quando estava sendo verificada a
possibilidade de utilização de uma matriz 3x3 foram situações como a demonstrada na Figura
9, onde havia buraco de 3 blocos impedindo que ele apenas visualizando um bloco ao seu
redor pudesse saber como ultrapassar. Para superar obstáculos como esse foi necessário
alterar a visão para uma matriz 9x9 e adicionar a ação pularFrente4 e pularTras4.
Figura 9. Buraco de 3 blocos
Para realização de testes do agente sem a árvore de planejamento, foi criado o cenário
da Figura 10, sendo este possível do agente superar.
48
Figura 10. Cenário para a primeira etapa de testes.
Um problema identificado nesta execução é que sem motivação de ir para frente, ações
como olhar para cima geravam regras positivas, pois o agente não morria, como após a
execução desta ação ele acabava na mesma situação que antes, ele executava novamente a
mesma regra, ficando preso na posição, como demonstrado na Figura 11.
Figura 11. Agente executando "abaixar" indefinidamente
Foi adicionada a cláusula que ao final da ação ele não deve estar na mesma situação
que antes de ser executada a mesma, impedindo assim que este ficasse realizando movimentos
repetidos indefinidamente, como a ação de abaixar, ou um salto vertical.
Após a adição da cláusula impedindo-o de ficar parado no mesmo lugar, foi localizado
outro problema, ele entrava em loopings já previstos no projeto, causando situações como a
ilustrada na sequência mostrada na Figura 11. Os loops aconteciam porque o agente sorteava a
ação “andar para trás” e a executava. Como ele não morreu e nem colidiu com um bloco
danoso, a ação era considerada válida. Após isso, caso ele sorteasse a ação “andar para
frente”, ele executava a mesma e também não colidia com um bloco danoso, nem causava
morte, anotando a mesma como uma ação válida. Sempre que ele verificava as regras, na
posição 1 da Figura 12 ele tinha uma regra para se mover para trás 1 bloco, na posição 2 da
Figura 12 ele tinha a regra para se mover para frente em 1 bloco, como previsto no projeto.
49
Figura 12. Agente em Loop
Neste caso, foi adicionada a motivação no agente, sendo esta chegar ao ponto mais “à
direita” do cenário, impedindo que ele acabasse entrando em loops ou indo indefinidamente
para a esquerda.
Para o cenário simulado foi possível que o personagem chegasse ao final após algumas
tentativas, então esta etapa foi considerada validada. (SILVA, 2012).
3.1.1.2 Desenvolvimento do Agente com árvore de decisão para planejamento
Na etapa anterior, o agente conseguia percorrer o cenário sem maiores problemas,
desde que o cenário não necessitasse que ele se movesse para trás, mas foi visto que em
algumas fases geradas pela própria engine isso era necessário, então um novo mapa de testes
foi criado, demonstrado pela Figura 13.
Figura 13. Cenário da segunda etapa de testes
Neste cenário, nos primeiros obstáculos não houve aumento de dificuldade e foram
utilizados para validação do código após as alterações, mas o principal desafio era a coluna de
blocos inquebráveis, pois a única maneira de superá-la seria passar por baixo, pular no bloco
anterior acima (feito de grama) e saltar para frente como demonstrado na Figura 14, exigindo
50
que a motivação de apenas andar para frente fosse removida, mas que ainda assim o agente
tivesse a motivação para chegar à extrema direita do cenário.
Figura 14. Obstáculo que necessita de planejamento
Nesta etapa foi desenvolvida uma árvore de planejamento, onde toda vez antes de
realizar uma ação, a mesma era preenchida com a base de regras para cada passo, permitindo
assim que o agente pudesse planejar qual a sequência de decisões que ele deveria seguir com
que fizessem que o mesmo chegasse mais longe.
Uma das modificações necessárias a fazer no que estava sendo desenvolvido é que ao
invés do agente simplesmente guardar as regras e ação que foi gerada, o mesmo deveria
também guardar o deslocamento que a regra gerou, pois para o planejamento adequado, ele
necessita saber onde o seu deslocamento o levará, por exemplo, uma regra descrita como “0 E
0 E 0 E 0 E 0 E 0 E -60 E -60 E -60” não poderia apenas guardar “andar para frente”, e sim,
“andar para frente” se deslocará 1 bloco na posição X e 0 blocos na posição Y.
Sendo assim, foi adicionada a solução a possibilidade de guardar o seu deslocamento
fazendo com que o agente percorra a árvore procurando as regras válidas para a atual posição,
sendo estas regras compostas de ações possíveis que não estão no grupo de regras negativas
(como acontecida na primeira etapa do projeto).
Para realização desta etapa também foi necessário criar uma simulação, onde quando o
agente encontra uma regra válida, antes de se locomover ele verifica o mapa, verifica sua
posição atual e soma com o deslocamento anotado previamente para aquela regra, depois
51
continua verificando a árvore e realizando as simulações até que ele chegue no nível desejado
ou não encontre um caminho que tenha tanta profundidade.
A cada novo nodo da árvore de decisão é anotado o comando a ser executado, pois
caso chegue no nível de profundidade desejado, é necessário apenas percorrer os comandos
anotados. Caso em algum nível ele chegue a um ponto que não há ações possíveis ou ele
chegue ao nível de ação esperado, mas a motivação não é válida (ele terminar o movimento
mais perto da extrema esquerda da tela), ele coloca esse nodo como inválido e remove da lista
de ações a serem executadas aquela ação.
Caso seja criada a árvore, mas em nenhum caminho ele chega ao nó com profundidade
desejada da árvore (no caso dos testes, 3 passos), a árvore é percorrida novamente o máximo
possível no primeiro caminho e, ao fim é sorteada uma nova ação seguindo sua base de
regras.
A partir deste ponto, o agente era capaz após algumas tentativas de percorrer e chegar
ao fim do cenário. Ao realizar os testes neste cenário, o agente ao chegar no ponto indicado
pela Figura 15 executou a sequência de movimentos “pularTras1”, “pularFrente2” e
conseguiu superar este obstáculo.
Figura 15. Executando sequência planejada
3.1.1.3 Adicionando máquina de estado
Neste ponto, com a geração da árvore de decisão concluída e funcionando foi
adicionado uma máquina de estados, onde em um estado mostra o agente numa situação que
52
possui a flor de fogo, permitindo que seja adicionado um grupo de ações como “atirar”,
enquanto outro estado ele está sem a flor.
Para verificação disso, quando a engine chamava o método “getAction” era verificado
o status do agente, caso a variável Mario.fire seja verdadeira seu status era alterado para
“com flor”, caso ela seja falsa seu status é trocado para “sem flor” como demonstrado na
Figura 16.
Figura 16. Alteração de estados.
Ao alterar o estado as regras são reiniciadas, então o agente acaba tendo que
reaprender com a situação, pois com estados diferentes há diferentes ações possíveis, criando
assim novos caminhos quando executada a árvore de decisão e novas regras para as situações
(ao invés de saltar sobre um obstáculo pode atirar nele).
A adição da máquina de estados influenciou pouco no agente, pois a flor de fogo
influencia principalmente na destruição de inimigos e para facilitar a passagem de alguns
cenários. Para a realização dos testes com a máquina de estado, foi utilizado a fase
demonstrada na Figura 17, onde o personagem acabava pulando o obstáculo caso estivesse
normal ou pequeno (estado sem flor) demonstrado na Figura 18, e algumas vezes, quando
conseguia criar a regra acabava destruindo o inimigo caso possuísse a flor de fogo (estado
com flor) mostrada na Figura 17.
53
Figura 17. Fase de testes da máquina de estados com flor
Figura 18. Fase de testes da máquina de estados sem flor
A ação “atirar” do personagem acabou não surtindo efeito esperando, que seria ser
utilizado para conseguir superar o cenário, pois quando ele atira o agente acaba ficando
parado e criando uma regra negativa. Uma alteração possível para solucionar esta situação
seria ao atirar o fogo verificar se seu campo de visão foi alterado, mas caso o personagem
acabe acertando um personagem do outro lado do cenário ele não será capaz de saber, pois
não há meio da engine informar se o fogo atingiu um inimigo ou não.
Para realização de testes de funcionamento da máquina de estados, no estado “com
flor” foram adicionados apenas uma ação, “andarFrente”, e para o estado “sem flor” foram
adicionados os métodos “pularFrente1”, “pularFrente2”. O resultado é apresentado na Figura
19, com o agente iniciando no estado “com flor”, caminhando em direção ao inimigo e
colidindo com o mesmo para poder trocar de estado, após isso ele começa a se locomover
com pulos, que estão só presentes no estado sem flor.
54
Figura 19. Alterando o estado ao colidir.
Os resultados obtidos com o agente contendo as três técnicas foram razoáveis,
permitindo o mesmo completar o percurso, apesar de quando adicionado a árvore de decisão o
agente acabar levando muito mais tempo para conseguir aprender a superar obstáculos pelo
fato da motivação não ser algo instantâneo (a motivação é avaliada só após percorrer a árvore
de decisão completa), mas com isso permitindo o mesmo superar obstáculos mais complexos.
4 CONCLUSÃO
Esta pesquisa foi importante permitindo mostrar que é possível utilizar uma mistura
das três técnicas de IA (sistema baseado em regras, árvore de decisão e máquina de estados)
para fazer com que o agente, após uma série de tentativas e adicionada motivação,
conseguisse manter um grupo de regras que permitiam ele avançar sem morrer por cenários
que não contém inimigos móveis.
Com a utilização de uma matriz menor do que uma 9x9, o projeto acabou mostrando
que o agente era incapaz de superar obstáculos comuns em fases da própria engine, como
buracos de três blocos. A adição da motivação foi importante para que o agente pudesse
chegar ao final da fase na extrema direita.
É possível também adicionar uma matriz maior do que o 9x9, só que quanto maior a
matriz mais difícil é para uma regra acabar repetindo, então casos com moedas em algum
canto que não influencia o personagem pode acabar atrapalhando na decisão (gerando regras
novas). A matriz 9x9 é a menor possível utilizada e não há necessidade de uma matriz maior
(não há obstáculos nos cenários gerados pela engine que necessitem de uma visão maior que
essa). Como o personagem pode realizar saltos de até quatro blocos para cima, foi utilizada
uma matriz quadrática.
55
Não foi possível a utilização de uma matriz onde o agente não estava no centro da
mesma, pois em vários movimentos era necessário um salto para trás de três blocos, e caso o
agente estivesse na extrema esquerda da matriz ele seria incapaz de prever onde iria cair. Para
a utilização de uma matriz onde o agente não estivesse centralizado, seria necessário que a
matriz fosse deslocada para várias posições dependendo da ação que o agente fosse executar.
A árvore de decisões foi essencial para superação de obstáculos onde era necessária a
realização de mais de um movimento para superar, como salto para trás e depois para frente (o
que com a utilização de apenas uma base de regras não era possível).
A máquina de estados foi importante para conseguir adicionar novas habilidades para
o agente, e em um caso onde outra combinação de botões pode ser apertada para gerar uma
ação em um estado específico. Por exemplo, no caso da flor, o fato dele não estar no estado
que contenha a flor, apertar o botão de corrida parado não gera efeito nenhum, então não é
necessário que ele execute isso, a menos que ele tenha a flor.
O aprendizado de máquina online foi essencial para o desenvolvimento, pois neste
caso onde cada ação gera um aprendizado, o mesmo deve ser constante e não pode ser
baseado apenas numa análise de regras geradas após a simulação. Também ficou claro que o
aprendizado do agente foi intra-comportamental, o que quer dizer que as suas ações estavam
previamente definidas antes do jogo ser simulado e novas ações não eram criadas do nada, ele
apenas modificava as regras, ou seja, qual o grupo de ações deve ser combinado em cada
situação para gerar um resultado positivo, permitindo assim que o mesmo siga adiante.
Para trabalhos futuros é possível implementar a habilidade do agente conseguir
superar cenários com inimigos em movimento, adicionar motivações para quando for mais
vantajoso o agente possa escolher entre pegar cogumelo, vida, flor, andar para frente ou até
atacar um inimigo para continuar prosseguindo. Também é possível adicionar uma visão
móvel para o personagem, para quando ele for verificar o cenário ao seu redor, não analisar
como uma matriz só, mas sim, a visão dele percorrer tudo em volta em pequenas matrizes de
4x4 e a cada local ele poder tentar combinar com uma regra que o faça se locomover para
atingir sua motivação.
Este projeto foi importante para reforçar o aprendizado sobre inteligência artificial,
adicionando novos conhecimentos e verificando de maneira empírica a utilização de suas
técnicas e como funciona o aprendizado de máquina por reforço. Foi importante também em
56
relação ao estudo de criação de regras pela realização de tentativa e erro, agentes e sua
interação com ambientes, e neste caso da necessidade de adicionar a motivação, como a
mesma funciona e como criar um agente que aprende e é capaz de realizar planejamento com
aquilo que aprendeu.
57
REFERÊNCIAS
BOJARSKI, Slawomir; CONGDON, Clare Bates; REALM: A rule-based evolutionary
computation agent that learns to play Mario. 2010. Disponível em: <
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.173.4586&rep=rep1&type=pdf>.
Acesso em: 07 jun. 2012.
BRITO, Roberta C; MARTENDAL, Diogo M.; OLIVEIRA, Henrique E. M., Máquinas de
estados finitos de Mealy e Moore., Florianópolis: Editora da UFSC, 2003
CALIFF, Mary E.; MOONEY, Raymond J.; Bottom-Up Relational Learning of Pattern
Matchin Rules for Information Extraction., Austin, 2003.
CORRÊA, Sand L.; CERQUEIRA, Renato F.G., Estudo de métodos de aprendizado online
em sistemas autônomos. Monografia (Pós-Graduação em Ciência da Computação) - PUC-
Rio, Rio de Janeiro, 2008.
DAYAN, Peter; WATKINS, Christopher J.C.H, Encyclopedia of Cognitive Science.
Londres: The MIT Press, 2005, 4v.
JAAKKOLA, Tommi; SINGH, Satinder P.; JORDAN, Michael I., Reinforcement learning
algorithm for partially observable Markov decision problems. Advances in Neural
Information Processing Systems 7, 1994.
LIM, Mei Yii. et al. Creating adaptive affective autonomous NPCs. 2010.
KARAKOVSKIY, Sergey; TOGELIUS, Julian, Mario AI Competition. 2009. Disponível
em: <http://julian.togelius.com/mariocompetition2009/CIG2009Competition.pdf>. Acesso
em: 14 de maio. 2012.
KARAKOVSKIY, Sergey; TOGELIUS, Julian, Mario AI Championship. 2012. Disponível
em: <http://www.marioai.org/>. Acesso em: 14 de maio. 2012.
KELLER, Robert M., Computer science: abstraction to implementation., Claremont,
Setembro 2001.
MILLINGTON, Ian, Artificial intelligence for games. San Francisco: Elsevier, 2006.
PENG, Wei; CHEN, Juhua; ZHOU, Haiping, An implementation of ID3 decision tree
learning algorithm., Sydney, 2002
POZZER, Cesar T., Aprendizado por árvores de decisão., Santa Maria, 2006.
QUINLAN, Jhon R., C4.5: Programs for Machine Learning., Morgan Kaufmann, 1993.
RICH, Elaine; KNIGHT, Kevin; Inteligência Artificial. 2. ed. São Paulo: MAKRON, 1994.
SILVA, Luiza M. O,; Uma Aplicação de Árvores de Decisão, Redes Neurais e KNN para
a Identificação de Modelos ARMA Não-Sazonais e Sazonais. 2005. 90 f. Teste
(Engenharia Elétrica) - Curso de Pós-Graduação em Engenharia Elétrica, PUC-Rio, Rio de
Janeiro.
58
SILVA, Nauro Jr.; TCC – Sem Árvore de Decisão. Disponível em:
<http://www.youtube.com/watch?v=bYOBsK5rtBg>. Acesso em 03 Nov. 2012.
TAN Pang-Ning; STEINBACH Michael; KUMAR Vipin, Introduction to Data Mining.,
Boston: Addinson-Wesley, Maio 2005.
ZUBEN, Fernando J. V.; ATTUX Romis R. F.; Árvores de decisão, 2010. Notas de aula.
59
APÊNDICE A. ALTERAÇÕES NA ENGINE
public static void main(String[] args) {
final MarioAIOptions marioAIOptions = new MarioAIOptions(args);
marioAIOptions.setScale2X(true);
marioAIOptions.setTimeLimit(999999);
marioAIOptions.setMarioMode(0);
marioAIOptions.setAgent(new MeuAgente());
marioAIOptions.setFrozenCreatures(true);
marioAIOptions.setLevelName("final.lvl");
final BasicTask basicTask = new BasicTask(marioAIOptions);
basicTask.doEpisodes(999, true, 999);
System.exit(0);
}
Quadro 4. Classe Main. Colocando limite de tempo alto, criaturas congeladas e 999 tentativas.
while (!environment.isLevelFinished())
{
environment.tick();
if (!GlobalOptions.isGameplayStopped)
{
c = System.currentTimeMillis();
agent.integrateObservation(environment);
agent.giveIntermediateReward(environment.getIntermediateReward());
boolean[] action = agent.getAction();
/*
if(System.currentTimeMillis()-c> COMPUTATION_TIME_BOUND)
return false;
* */
// System.out.println("action = " + Arrays.toString(action));
// environment.setRecording(GlobalOptions.isRecording);
environment.performAction(action);
}
}
Quadro 5. Classe BasicTask. Linhas referentes a eliminar o agente depois de 40ms foram
comentadas.
if (!marioAIOptions.getLevelName().equals("")) {
level =
LevelGenerator.loadMyLevel(marioAIOptions.getLevelName());
} else {
level = LevelGenerator.createLevel(marioAIOptions);
}
Quadro 6. Classe LevelScene. Adicionando código para carregar arquivo de fase criado
pelo LevelGenerator.
60
switch (ZLevel) {
case (0):
switch (el) {
case 16: // brick, simple, without any surprise.
case 17: // brick with a hidden coin
case 18: // brick with a hidden friendly flower
return BREAKABLE_BRICK;
case 20: //Adicionando bloco de LevelScene
case 21: // question brick, contains coin
case 22: // question brick, contains
flower/mushroom
case 23: // question brick, N coins inside.
prevents cheating
return UNBREAKABLE_BRICK; // question brick,
contains something
case 34:
return COIN_ANIM;
case 4:
case (5): //Adicionando bloco de LevelScene
case -111: //Adicionando bloco de LevelScene
case -127:
return BORDER_CANNOT_PASS_THROUGH;
case 14:
return CANNON_MUZZLE;
case 30:
case 46:
return CANNON_TRUNK;
case 10:
case 11:
case 26:
case 27:
return FLOWER_POT;
case 1:
return 0; //hidden block
case -124:
case -123:
case -122: //Adicionando bloco de LevelScene
case -74:
return BORDER_HILL;
case -108:
case -107:
case -106:
return 0; //background of the hill. empty space
case (61):
return LADDER;
case (93):
return TOP_OF_LADDER;
case (-1):
return PRINCESS;
}
return el;
Quadro 7. Classe GeneralizerLevelScene. Adicionando blocos do LevelGenerator que
não estavam mapeados pela Engine.
61
APÊNDICE B. CÓDIGO PERCORRENDO A ÁRVORE
public void criaPlanejamento() throws CaminhoNaoEncontradoException,
ExceptionExecutaCaminho {
//Enquanto não chegar na profundidade desejada
if (this.nivel < MeuAgente.MAX_NIVEL_PLANEJAMENTO) {
ArrayList<Regra> possiveisRegras =
agente.buscaRegrasPositivas(this.visaoSimulada);
for (Regra regraSimulacao : possiveisRegras) {
//Percorre caminhos possíveis
int xSomado = xSimulado + regraSimulacao.getMovimentacaoX();
int ySomado = ySimulado + regraSimulacao.getMovimentacaoY();
try {
byte[][] visaoResultado = simulaPasso(regraSimulacao);
NodoSimulacao n = new NodoSimulacao(this,
regraSimulacao.getMetodo(), agente, visaoResultado, xSomado, ySomado,
this.nivel + 1);
//Recursividade para percorrer a árvore
n.criaPlanejamento();
} catch (ExceptionExecutaCaminho ex2) {
// Achou um caminho. Pára de percorrer a árvore.
throw ex2;
} catch (ExceptionExecutaCaminho e) {
//Não há caminho possível. Sai do planejamento para criar novo
//caminho
}
}
//Beco sem saída. Remove a última regra.
agente.removeUltimaRegra();
//Não achou nenhum caminho
if (this.superior == null) {
throw new CaminhoNaoEncontradoException();
}
} else {
//Se chegou no nível de planejamento
System.out.println("Caminho");
for (Method m : agente.getCaminho()) {
System.out.print(m + " - >");
}
//Verifica motivação
if (this.xSimulado > (agente.posicaoUltimoCalculo)) {
System.out.println("Condiz com motivação");
agente.executaCaminhoPlanejado();
throw new ExceptionExecutaCaminho();
} else {
System.out.println("Não Condiz com Motivação");
62
agente.removeUltimaRegra();
return;
}
}
}
Quadro 8. Código percorrendo a árvore.
63
APÊNDICE C. EXEMPLO DA UTILIZAÇÃO DA ÁRVORE.
Regras Positivas:
{ 0,0,0,0,0,0,0,0,0
0,0,0,-20,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,-128,-60,-128,0
0,0,-128,-60,-60,-60,-60, -120,0
0,0,-128,-60,-60,-60,-60, -120,0
-60,-60,-120,-60,-60,-60,-60,-120,0
0,0,0,0,0,0,0,0,0 } => andarFrente (X+1, Y+0)
{ 0,0,0,0,0,0,0,0,0
0,0,0,-20,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,-128,-60,-128,0
0,0,-128,-60,-60,-60,-60, -120,0
0,0,-128,-60,-60,-60,-60, -120,0
-60,-60,-120,-60,-60,-60,-60,-120,0
0,0,0,0,0,0,0,0,0 } => pularFrente (X+1, Y+1)
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,-20,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,-128,-60,-128,0,0
0,-128,-60,-60,-60,-60, -120,0,0
0,-120,-60,-60,-60,-60, -120,0,0
0,-120,-60,-60,-60,-60, -120,0,0
-60,-120,-60,-60,-60,-60,-120,0,0} => andarFrente (X+1,
Y+0)
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,-20,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,-128,-60,-128,0,0,0
-128,-60,-60,-60,-60, -120,0,0,0
-120,-60,-60,-60,-60, -120,0,0,-128
-120,-60,-60,-60,-60, -120,0,0,-120
-120,-60,-60,-60,-60,-120,0,0,-120} => andarFrente (X+1,
Y+0)
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,-20,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,-128,-60,-128,0,0,0,0
-60,-60,-128,-60,-128,0,0,-128,-60
-60,-60,-128,-60,-128,0,0,-120,-60
-60,-60,-128,-60,-128,0,0,-120,-60
} => pularFrente3 (X+3, Y-1)
Quadro 9. Base de regras parte 1.
64
Regras Positivas:
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,-128
-128,0,0,0,0,0,-30,0,-120
-120,0,0,-128,-60,-60,-60,-60,-128
-120,0,0,-128,-60,-60,-60,-60,-60
-120,0,0,-128,-60,-60,-60,-60,-60
0,0,0,0,0,0,0,0,0
} => andarFrente (X+1, Y+0)
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,-128
-128,0,0,0,0,0,-30,0,-120
-120,0,0,-128,-60,-60,-60,-60,-128
-120,0,0,-128,-60,-60,-60,-60,-60
-120,0,0,-128,-60,-60,-60,-60,-60
0,0,0,0,0,0,0,0,0
} => pularTras4 (X-4, Y+1)
Regras Negativas:
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,-20,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,-128,-60,-128,0,0,0,0
-60,-60,-128,-60,-128,0,0,-128,-60
-60,-60,-128,-60,-128,0,0,-120,-60
-60,-60,-128,-60,-128,0,0,-120,-60
} => andarFrente
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,-20,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,-128,-60,-128,0,0,0,0
-60,-60,-128,-60,-128,0,0,-128,-60
-60,-60,-128,-60,-128,0,0,-120,-60
-60,-60,-128,-60,-128,0,0,-120,-60
} => pularFrente1
Quadro 10. Base de regras parte 2
65
Figura 20. Planejando passo 1.
Figura 21. Planejando passo 2.
Figura 22. Planejando passo 3.
66
Regras Positivas:
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,-128
-128,0,0,0,0,0,-85,0,-120
-120,0,-128,-60,-60,-60,-60, -60,-60
-120,0,-120,-60,-60,-60,-60, -60,-60
-120,0,-120,-60,-60,-60,-60,-60,-60
0,0,0,0,0,0,0,0,0 } => andarFrente (X+1, Y+0)
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,-128
-128,0,0,0,0,0,-85,0,-120
-120,0,-128,-60,-60,-60,-60, -60,-60
-120,0,-120,-60,-60,-60,-60, -60,-60
-120,0,-120,-60,-60,-60,-60,-60,-60
0,0,0,0,0,0,0,0,0 } => andarTras (X-1, Y+0)
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0
-60,-128,0,0,0,0,0,-85,0
-60,-120,0,-128,-60,-60,-60,-60, -60
-60,-120,0,-120,-60,-60,-60,-60, -60
-60,-120,0,-120,-60,-60,-60,-60,-60
-60,0,0,0,0,0,0,0,0 } => pularFrente1 (X+1, Y+0)
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,-128,-60
0,0,0,0,0,-85,0,-120,-60
0,-128,-60,-60,-60,-60, -60,-60,-60
0,0,-120,-60,-60,-60,-60, -60,-60,-60
0,-120,-60,-60,-60,-60,-60,-60,-60
0,0,0,0,0,0,0,0,-60 } => pularFrente3 (X+3, Y+2)
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,-85,0
0,0,0,0,-128,-60,-60,-60,-60
0,0,-85,0,-120,-60,-60,-60,-60
-60,-60,-60,-60,-60,-60,-60,-60,-60
-60,-60,-60,-60,-60,-60,-60,-60,-60} => andarFrente(X+1,
Y+0)
Regras Negativas:
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0
67
-60,-128,0,0,0,0,0,-85,0
-60,-120,0,-128,-60,-60,-60,-60, -60
-60,-120,0,-120,-60,-60,-60,-60, -60
-60,-120,0,-120,-60,-60,-60,-60,-60
-60,0,0,0,0,0,0,0,0 } => andarTras
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0
-60,-128,0,0,0,0,0,-85,0
-60,-120,0,-128,-60,-60,-60,-60, -60
-60,-120,0,-120,-60,-60,-60,-60, -60
-60,-120,0,-120,-60,-60,-60,-60,-60
-60,0,0,0,0,0,0,0,0 } => pularTras2
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,-128,-60
0,0,0,0,0,-85,0,-120,-60
0,-128,-60,-60,-60,-60, -60,-60,-60
0,0,-120,-60,-60,-60,-60, -60,-60,-60
0,-120,-60,-60,-60,-60,-60,-60,-60
0,0,0,0,0,0,0,0,-60 } => andarFrente
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,-85,0
0,0,0,0,-128,-60,-60,-60,-60
0,0,-85,0,-120,-60,-60,-60,-60
-60,-60,-60,-60,-60,-60,-60,-60,-60
-60,-60,-60,-60,-60,-60,-60,-60,-60} => pularTras2
{ 0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,-85,0,0
0,0,0,-128,-60,-60,-60,-60,-60
0,-85,0,-120,-60,-60,-60,-60,-60
-60,-60,-60,-60,-60,-60,-60,-60,-60
-60,-60,-60,-60,-60,-60,-60,-60,-60} => pularTras3
Quadro 11. Base de regras do segundo exemplo.
68
Figura 23. Segundo exemplo, passo 1.
Figura 24. Segundo exemplo, passo 2.