You are here

Relatório Aula 7 - Utilizando o SOAR para controlar uma criatura no WorldServer3D

Atividade 1)

Estudo dos códigos fonte do DemoSOAR, WorldServer3D e WS3DProxy

  Inicialmente foram testadas as compilações dos códigos fonte do DemoSOAR, WorldServer3D e WS3DProxy. Foi aplicada também a alteração sugerida na página da disciplina (http://faculty.dca.fee.unicamp.br/gudwin/couses/IA006/SoarDebuggerTip) para que o SoarDebugger funcione em conjunto com o DemoSOAR, mostrando os processos do SOAR em conjunto com a simulação.

  Em seguida, foram estudadas algumas das questões levantadas pelo enunciado da aula 7.

 

JNI

  O código Java Native Interface é o responsável pela ligação entre o Java e os aplicativos nativos do sistema. Estes métodos nativos são implementados em outras linguagens e colocados em bibliotecas do sistema operacional. Estas, por sua vez, são acessadas pelo Java Virtual Machine para adicionar funções ou para melhorar a eficiência dos programas. Uma vez que as bibliotecas de cada sistema operacional são diferentes entre si, o uso do Java Native Interface deve ser específico para cada sistema operacional, para garantir portabilidade de plataformas. (http://en.wikipedia.org/wiki/Java_Native_Interface)

 

Classe NativeUtils

  A classe NativeUtils é utilizada para carregar uma biblioteca do arquivo JAR. O arquivo é compiado para uma pasta temporaria, carregado e então deletado após a finalização. (http://adamheinrich.com/blog/2012/how-to-load-native-jni-library-from-jar/)

  A função loadFileFromJar possui exatamente a mesma estrutura que a função loadLibraryFromJar. Ambas funções recebem uma string como entrada. Esta string deve apontar o caminho para um arquivo a ser copiado em um buffer e então passado para um arquivo temporário. A função também realiza um teste para verificar se o arquivo existe e possui um nome e formato adequado.


DemoSOAR

  O loop principal do DemoSOAR cria um ambiente de simulação por meio da classe SimulationTask e inicializa tanto a criatura virtual quanto a sua mente implementada no SOAR. Depois disso, ela executa a simulação em loop infinito, até que um erro force a parada da simulação ou que esta seja finalizada pelo usuário.

  Dentro da classe SimulationTask, as funções initializeCreatureAndSOAR e initializeEnviroment são funções que inicializam a criatura, sua mente em SOAR e o ambiente. A função runSimulation verifica quantos objetos estão no campo de visão da criatura e chama as funções runSimulation da classe SoarBridge (que executa o SOAR) e processResponseCommands da classe SimulationTask (que recebe os comandos do Soar e envia para a criatura instruções correspondentes dos tipos MOVE, GET, EAT e Do Nothing). As funções processMoveCommand, processGetCommand e processEatCommand enviam os respectivos comandos para mover, pegar e comer à criatura no WorldServer3D. A função prepareAndSetupCreatureToSimulation realiza a leitura dos sensores de visão e combustível da criatura no WorldServer3D e envia estes dados para a interface de com o SOAR.

  Dentro do projeto DemoSOAR, existe também o arquivo soar-rules.soar, contendo as regras de preferência, operadores (move, eat, get e wander) e listas de memórias dos objetos detectados. Observando este código, foi possível montar uma árvore com a estrutura das informações sobre o mundo da criatura no SOAR.

 

WS3DProxy

  De dentro do projeto WS3DProxy, algumas classes foram utilizadas pela classe SimulationTask. A classe WS3DProxy é utilizada para conectar o cliente ao ambiente WorldServer3D por meio de sockets, criar ou retornar instancias das criaturas no WorldServer3D e retornar o ambiente conhecido pela criatura. A classe CommandUtility envia comandos ao ambiente WorldServer3D para controle da criatura. Cada comando corresponde a uma ação a ser executada pela criatura ou um atributo especifico da criatura a ser alterado. Possui funções que lidam com leaflets, então pode ser interessante revisitar esta classe para a realização da Atividade 2. A classe CommandExecException é uma exceção que é lançada quando o server responde com um código de erro. A classe World contém os atributos e funções do ambiente virtual conhecido pela criatura, como número e posição de obstáculos, gemas, alimentos e criaturas. A classe Creature possui atributos das criaturas, como a posição, sensores, atributos, indice, bem como funções referentes a elas, como atualizações de estados, posições e inventario e instruções para guardar itens no inventario, comer ou se mover.

 

Observando o funcionamento do WorldServer3D por meio do command prompt do Linux (Konsole):

  A respeito do funcionamento do ambiente virtual, em conversa com o Professor, foi entendido que o funcionamento da tarefa deveria se dar da seguinte forma:

  1) Cria-se inicialmente uma criatura no ambiente virtual;

  2) Uma função de criação de Leaflet é chamada (provavelmente, a função sendGenLeaflet, da classe CommandUtility);

  3) A Leaflet (um HashMap) deve ser acessada pela função myLeaflets, disponível na classe CreatureState;

  4) As informações da Leaflet devem ser enviadas para o SOAR por meio da função SetupStackHolder, disponível na classe SOARBridge.

  A observação do WorldServer3D pode ser feita também por meio do acesso ao jogo por meio do Konsole. Para isto, deve-se iniciar o ambiente virtual, criar uma nova criatura (clicar com o botão direito no tabuleiro) e então digitar no prompt os seguintes comandos:

- para conectar:
  telnet localhost 4011

- para obter ajuda:
  help

- para obter o ID da criatura:
  getall

- para obter o estado da criatura cujo ID foi obtido acima, inclusive o leaflet dela:
  getcreaturestate + creatureID

- para criar um novo leaflet (que não é gerado automaticamente com a criação da criatura):
  leaflet

 

/////////////////////////////////////////////////////////////////////////////////

Atividade 2)

 

Execução do projeto

  O objetivo do trabalho é fazer com que o agente SOAR leve em conta o leaflet da criatura do ambiente WorldServer3D. Em princípio, o meu plano de execução da tarefa consistiu em duas etapas distintas:

1 - Enviar ao SOAR informações sobre as cores das Jewels requeridas no Leaflet (uma lista de quantas unidades de cada cor);

2 - Criar, no agente, preferências que priorizem o operador Move para as Jewels presentes na lista dos itens da Leaflet.

 

Estrutura da Leaflet no SOAR

  A informação da Leaflet sobre as jewels a serem obtidas deverá estruturada no SOAR conforme o seguinte objeto:

s1 ^io i1 ^input-link i2 ^creature c1 ^leaflet L1
L1 ^leaflet-item.item-color Color
 

Modificações no SimulationTask e no SoarBridge

   Para informar o agente virtual sobre a leaflet, foram feitas modificações nas classes SimulationTask e SoarBridge. Na SimulationTask, foi modificada a função runSimulation, de modo que ela realizasse a soma das três leaflets exigidas e gerasse um vetor de inteiros contendo o resultado de tudo. Abaixo está o código responsável por isto:

public void runSimulation() throws SoarBridgeException, NullPointerException, IllegalAccessException, CommandExecException
    {
        if (soarBridge != null)
        {
            c.updateState();
            //Status currentStatus = c.getState();
            List<Thing> v = c.getThingsInVision();
            logger.info("Objetos no Ambiente: "+v.size());
            System.out.println("Objetos no Ambiente: "+v.size());
            for (Thing t : v) {
                logger.info(t.toString());
            }
            
            
        // O código abaixo soma as três leaflets, armazenando os valores em um vetor de inteiros de tamanho 6 e imprime depois.
        List leafletList = new ArrayList<Leaflet>();
        leafletList = c.getLeaflets();
        int howManyLeaflets = leafletList.size();
        Leaflet LeafletVector[] = new Leaflet[howManyLeaflets];
        for (int auxcounter = 0; auxcounter<howManyLeaflets; auxcounter++){
            LeafletVector[auxcounter] = (Leaflet) leafletList.get(auxcounter);
        }
                
        HashMap<String, Integer> itemsMap1 = new HashMap<String, Integer>();
        itemsMap1 = LeafletVector[0].getWhatToCollect();
        Set setItems1 = itemsMap1.entrySet();
        Iterator iteratorItems1 = setItems1.iterator();
        
        HashMap<String, Integer> itemsMap2 = new HashMap<String, Integer>();
        itemsMap2 = LeafletVector[1].getWhatToCollect();
        Set setItems2 = itemsMap2.entrySet();
        Iterator iteratorItems2 = setItems2.iterator();
        
        HashMap<String, Integer> itemsMap3 = new HashMap<String, Integer>();
        itemsMap3 = LeafletVector[2].getWhatToCollect();
        Set setItems3 = itemsMap3.entrySet();
        Iterator iteratorItems3 = setItems3.iterator();       

        String valorSTR = "0";
        
        if((LeafletSum[0]+LeafletSum[1]+LeafletSum[2]+LeafletSum[3]+LeafletSum[4]+LeafletSum[5])==0){
            while(iteratorItems1.hasNext()){

                Map.Entry mentryItem1 = (Map.Entry)iteratorItems1.next();

                    if("Red".equals(mentryItem1.getKey().toString())){
                        valorSTR = mentryItem1.getValue().toString();
                        LeafletSum[0] = LeafletSum[0] + Integer.parseInt(valorSTR);}
                    if("Green".equals(mentryItem1.getKey().toString())){
                        valorSTR = mentryItem1.getValue().toString();
                        LeafletSum[1] = LeafletSum[1] + Integer.parseInt(valorSTR);}
                    if("Blue".equals(mentryItem1.getKey().toString())){
                        valorSTR = mentryItem1.getValue().toString();
                        LeafletSum[2] = LeafletSum[2] + Integer.parseInt(valorSTR);}
                    if("Yellow".equals(mentryItem1.getKey().toString())){
                        valorSTR = mentryItem1.getValue().toString();
                        LeafletSum[3] = LeafletSum[3] + Integer.parseInt(valorSTR);}
                    if("Magenta".equals(mentryItem1.getKey().toString())){
                        valorSTR = mentryItem1.getValue().toString();
                        LeafletSum[4] = LeafletSum[4] + Integer.parseInt(valorSTR);}
                    if("White".equals(mentryItem1.getKey().toString())){
                        valorSTR = mentryItem1.getValue().toString();
                         LeafletSum[5] = LeafletSum[5] + Integer.parseInt(valorSTR);}
                }                       
          
            while(iteratorItems2.hasNext()){
            
                Map.Entry mentryItem2 = (Map.Entry)iteratorItems2.next();
          
                    if("Red".equals(mentryItem2.getKey().toString())){
                        valorSTR = mentryItem2.getValue().toString();
                        LeafletSum[0] = LeafletSum[0] + Integer.parseInt(valorSTR);}
                    if("Green".equals(mentryItem2.getKey().toString())){
                        valorSTR = mentryItem2.getValue().toString();
                        LeafletSum[1] = LeafletSum[1] + Integer.parseInt(valorSTR);}
                    if("Blue".equals(mentryItem2.getKey().toString())){
                        valorSTR = mentryItem2.getValue().toString();
                        LeafletSum[2] = LeafletSum[2] + Integer.parseInt(valorSTR);}
                    if("Yellow".equals(mentryItem2.getKey().toString())){
                        valorSTR = mentryItem2.getValue().toString();
                        LeafletSum[3] = LeafletSum[3] + Integer.parseInt(valorSTR);}
                    if("Magenta".equals(mentryItem2.getKey().toString())){
                        valorSTR = mentryItem2.getValue().toString();
                        LeafletSum[4] = LeafletSum[4] + Integer.parseInt(valorSTR);}
                    if("White".equals(mentryItem2.getKey().toString())){
                        valorSTR = mentryItem2.getValue().toString();
                        LeafletSum[5] = LeafletSum[5] + Integer.parseInt(valorSTR);}
                }
          
            while(iteratorItems3.hasNext()){       
            
                Map.Entry mentryItem3 = (Map.Entry)iteratorItems3.next();
                    if("Red".equals(mentryItem3.getKey().toString())){
                        valorSTR = mentryItem3.getValue().toString();
                        LeafletSum[0] = LeafletSum[0] + Integer.parseInt(valorSTR);}
                    if("Green".equals(mentryItem3.getKey().toString())){
                        valorSTR = mentryItem3.getValue().toString();
                        LeafletSum[1] = LeafletSum[1] + Integer.parseInt(valorSTR);}
                    if("Blue".equals(mentryItem3.getKey().toString())){
                        valorSTR = mentryItem3.getValue().toString();
                        LeafletSum[2] = LeafletSum[2] + Integer.parseInt(valorSTR);}
                    if("Yellow".equals(mentryItem3.getKey().toString())){
                        valorSTR = mentryItem3.getValue().toString();
                        LeafletSum[3] = LeafletSum[3] + Integer.parseInt(valorSTR);}
                    if("Magenta".equals(mentryItem3.getKey().toString())){
                        valorSTR = mentryItem3.getValue().toString();
                        LeafletSum[4] = LeafletSum[4] + Integer.parseInt(valorSTR);}
                    if("White".equals(mentryItem3.getKey().toString())){
                        valorSTR = mentryItem3.getValue().toString();
                        LeafletSum[5] = LeafletSum[5] + Integer.parseInt(valorSTR);}
            }
        }
        
        for(int contador = 0; contador < 6; contador++){
            System.out.print(LeafletSum[contador]);
        }
        System.out.print("\n");

        

    /*    // O código abaixo apenas imprime as três leaflets
        
        HashMap<String, Integer[]> itemsMap1 = new HashMap<String, Integer[]>();
        itemsMap1 = LeafletVector[0].getWhatToCollect();
        Set setItems1 = itemsMap1.entrySet();
        Iterator iteratorItems1 = setItems1.iterator();
        while(iteratorItems1.hasNext()){
          Map.Entry mentryItem1 = (Map.Entry)iteratorItems1.next();
          System.out.print("Jewel color: " + mentryItem1.getKey() + ", Quantity: " + mentryItem1.getValue() + "\n");  
        }
        
        System.out.print("............................................\n");  
        
        HashMap<String, Integer[]> itemsMap2 = new HashMap<String, Integer[]>();
        itemsMap2 = LeafletVector[1].getWhatToCollect();
        Set setItems2 = itemsMap2.entrySet();
        Iterator iteratorItems2 = setItems2.iterator();
        while(iteratorItems2.hasNext()){
          Map.Entry mentryItem2 = (Map.Entry)iteratorItems2.next();
          System.out.print("Jewel color: " + mentryItem2.getKey() + ", Quantity: " + mentryItem2.getValue() + "\n");  
        }

        System.out.print("............................................\n");  
        
        HashMap<String, Integer[]> itemsMap3 = new HashMap<String, Integer[]>();
        itemsMap3 = LeafletVector[2].getWhatToCollect();
        Set setItems3 = itemsMap3.entrySet();
        Iterator iteratorItems3 = setItems3.iterator();
        while(iteratorItems3.hasNext()){
          Map.Entry mentryItem3 = (Map.Entry)iteratorItems3.next();
          System.out.print("Jewel color: " + mentryItem3.getKey() + ", Quantity: " + mentryItem3.getValue() + "\n");  
        }
        
        System.out.print("............................................\n");  

      //  for (Leaflet l : leafletList) {
       //     ;
       // }
        //Leaflet l1 = (Leaflet) leafletList.get(0);
        //HashMap<String, Integer[]> itemsMap = new HashMap<String, Integer[]>();
        //itemsMap = l1.getItems();//getTotalNumberOfType(String type)
        
         
*/
            if (c != null)
            {
                // Prepare Creature To Simulation
                prepareAndSetupCreatureToSimulation(c, v);

                // Run simulation
                soarBridge.runSimulation();

                // Process Responde Commands
                processResponseCommands();
            }
            else
            {
                throw new NullPointerException("There are no creatures in simulation");
            }
        }
        else
        {
            throw new NullPointerException("soarBrige is null. Please, invoke initializeEnviroment");
        }
    }

   Este vetor seria então passado por parametro para a função SetupStackHolder, da classe SoarBridge. Esta função foi modificada com as seguintes linhas de código, para gerar uma estrutura na WME do SOAR, correspondente à soma das leaflets:

 // Send Leaflet to agent!
                        if(creatureLeaflet == null){
                            creatureLeaflet = agent.CreateIdWME(creature, "leaflet");
                            for(int colorIndex = 0; colorIndex < 6; colorIndex++){
                                for(int eachJewel = LeafletSum[colorIndex].intValue(); eachJewel > 0; eachJewel--){
                                    
                                    if(colorIndex == 0){agent.CreateStringWME(agent.CreateIdWME(creatureLeaflet, "leaflet-item"), "item-color", "Red");}
                                    if(colorIndex == 1){agent.CreateStringWME(agent.CreateIdWME(creatureLeaflet, "leaflet-item"), "item-color", "Green");}
                                    if(colorIndex == 2){agent.CreateStringWME(agent.CreateIdWME(creatureLeaflet, "leaflet-item"), "item-color", "Blue");}
                                    if(colorIndex == 3){agent.CreateStringWME(agent.CreateIdWME(creatureLeaflet, "leaflet-item"), "item-color", "Yellow");}
                                    if(colorIndex == 4){agent.CreateStringWME(agent.CreateIdWME(creatureLeaflet, "leaflet-item"), "item-color", "Magenta");}
                                    if(colorIndex == 5){agent.CreateStringWME(agent.CreateIdWME(creatureLeaflet, "leaflet-item"), "item-color", "White");}
                                    System.out.print("\nENTROU?\n\n" + colorIndex + "; " + eachJewel);
                                    System.out.print("\n");
                                }
                            }
                        }                       
                      

 

Modificações no SOAR

   Uma vez realizado o envio das informações das leaflets para o agente SOAR, foram feitas algumas modificações simples no código inicialmente fornecido. Foram realizadas também tentativas de criação de códigos mais complexos, porém quando isto foi feito, o java retornou um erro no log4j-1.2.15, que não pôde ser resolvido (buscas na internet pela solução deste problema se mostraram infrutiferas...). Isto limitou o tamanho e a complexidade das regras SOAR.

   Essencialmente, as modificações implementadas fazem com que o agente virtual ignore entidades não incluidas na soma das leaflets (Compara-se a cor do que o agente vê e as cores que estão nos nós da estrutura Leaflet. Se nenhum der match, então o agente ignora o que ele vê.). Inicialmente, era planejado um código que eliminasse (ou que marcasse como obtidos) os nós da estrutura leaflet no Working Memory, porém isto não foi possível, em função do erro descrito acima. Assim, mesmo depois de atingida a meta, a criatura virtual continua a capturar jewels cujas cores pertencem a leaflet.

   Apesar de não realizar a comparação do que foi capturado e do que ainda não foi, o funcionamento do código pode ser atestado pelo fato de o agente ignorar qualquer jewel que tenha soma zero nas três leaflets. Abaixo se encontram as regras SOAR. Poucas coisas foram modificadas, mas elas foram suficientes para fazer com que o agente mudasse sua estratégia.

################################  CONFIGURATION ################################
watch 5
learn --off
epmem --set learning off

###################################  WANDER  ###################################
# This operator will make the agent to walk ahead at the enviroment
# Propose*wander:
sp {propose*wander
   (state <s> ^attribute state
              ^impasse no-change                           
              ^superstate <ss>)
   (<ss> ^io.input-link <il>)
   (<ss> ^superstate nil)
   (<il> ^CREATURE <creature>)
   (<creature> ^SENSOR.VISUAL <visual>)
-->
   (<ss> ^operator <o> +)
   (<o> ^name wander)}
   
# Apply*wander:
# If the wander operator is selected, then generate an output command to it
sp {apply*wander
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^output-link <ol>)
   (<o> ^name wander)
-->
   (<ol> ^MOVE <command>)
   (<command> ^Vel 0)
   (<command> ^VelR 2)
   (<command> ^VelL 0)}
    
# If the wander operator is selected,
# and there is a completed move command on the output link,
# then remove that command.   
sp {apply*wander*remove*move
(state <s> ^operator.name wander
           ^io.output-link <out>)
(<out> ^MOVE <move>)
(<move> ^status complete)
-->
(<out> ^MOVE <move> -)}   

################ SEE ENTITY WITH MEMORY COUNT #####################
# This operator will make the agent hold some entities in memory if the agent already has some entities in memory

# Propose*see*entity*with*memory*count:
sp {propose*see*entity*with*memory*count
   (state <s> ^io.input-link <il>)
   (<il> ^CREATURE <creature>)
   (<creature> ^SENSOR.VISUAL.ENTITY <entity>)     
   (<entity> ^TYPE <type> << JEWEL FOOD >>)   
   (<creature> ^leaflet.leaflet-item.item-color <Color>)
   (<entity> ^COLOR <Color>)
   (<entity> ^X <x>)
   (<entity> ^Y <y>)
   (<entity> ^NAME <name>)
   (<creature> ^MEMORY <memory>)   
   -(<memory> ^ENTITY.NAME <name>)
   (<memory> ^COUNT <quantity> < 7)
-->
   (<s> ^operator <o> +)
   (<o> ^name seeEntityWithMemoryCount)
   (<o> ^parameterEntity <newEntity>)
   (<newEntity> ^Name <name>)
   (<newEntity> ^Type <type>)
   (<newEntity> ^X <x>)
   (<newEntity> ^Y <y>)
   (<newEntity> ^Color <Color>)}
         
# Apply*see*entity*with*memory*count:
# If the see operator is selected, then generate an output command to it
sp {apply*see*entity*with*memory*count
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)
   (<io> ^output-link <ol>)
   (<il> ^CREATURE <creature>)
   (<creature> ^MEMORY <memory>)
   (<memory> ^COUNT <quantity>)   
   (<o> ^name seeEntityWithMemoryCount)
   (<o> ^parameterEntity <newEntity>)
   (<newEntity> ^X <x>)
   (<newEntity> ^Y <y>)
   (<newEntity> ^Name <name>)
   (<newEntity> ^Type <type>)
   (<newEntity> ^Color <color>)
-->
   (<memory> ^ENTITY <memoryEntity>)
   (<memoryEntity> ^X <x>)
   (<memoryEntity> ^Y <y>)
   (<memoryEntity> ^NAME <name>)
   (<memoryEntity> ^TYPE <type>)
   (<memoryEntity> ^COLOR <color>)
   (<memory> ^COUNT <quantity> -)
   (<memory> ^COUNT (+ 1 <quantity>))}
   
################  SEE ENTITY WITHOUT MEMORY COUNT #################
# This operator will make the agent hold some entities in memory if the agent has not some entities in memory

# Propose*see*entity*without*memory*count:
sp {propose*see*entity*without*memory*count
   (state <s> ^io.input-link <il>)
   (<il> ^CREATURE <creature>)
   (<creature> ^SENSOR.VISUAL.ENTITY <entity>)
   (<entity> ^TYPE <type> << JEWEL FOOD >>)
   (<entity> ^X <x>)
   (<entity> ^Y <y>)
   (<entity> ^NAME <name>)
   (<creature> ^leaflet.leaflet-item.item-color <Color>)
   (<entity> ^COLOR <Color>)
   (<creature> ^MEMORY <memory>)   
   -(<memory> ^ENTITY.NAME <name>)
   -(<memory> ^COUNT <quantity>)
-->
   (<s> ^operator <o> +)
   (<o> ^name seeEntityWithoutMemoryCount)
   (<o> ^parameterEntity <newEntity>)
   (<newEntity> ^Name <name>)
   (<newEntity> ^Type <type>)
   (<newEntity> ^X <x>)
   (<newEntity> ^Y <y>)
   (<newEntity> ^Color <Color>)}
   
# Apply*see*entity*without*memory*count:
# If the see operator is selected, then generate an output command to it
sp {apply*see*entity*without*memory*count
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)
   (<io> ^output-link <ol>)
   (<il> ^CREATURE <creature>)
   (<creature> ^MEMORY <memory>)  
   (<o> ^name seeEntityWithoutMemoryCount)
   (<o> ^parameterEntity <newEntity>)
   (<newEntity> ^X <x>)
   (<newEntity> ^Y <y>)
   (<newEntity> ^Name <name>)
   (<newEntity> ^Type <type>)
   (<newEntity> ^Color <color>)
-->
   (<memory> ^ENTITY <memoryEntity>)
   (<memoryEntity> ^X <x>)
   (<memoryEntity> ^Y <y>)
   (<memoryEntity> ^NAME <name>)
   (<memoryEntity> ^TYPE <type>)
   (<memoryEntity> ^COLOR <color>)
   (<memory> ^COUNT 1)}
 

##############################  MOVE FOOD  #####################################
# This operator will make the agent go straight to the food

# Propose*move*food:
sp {propose*move*food
   (state <s> ^io.input-link <il>)
   (<il> ^CREATURE <creature>)
   (<creature> ^MEMORY <memory>)
   (<memory> ^ENTITY <entityInMemory>)
   (<creature> ^POSITION <creaturePosition>)
   (<creaturePosition> ^X <creaturePositionX>)
   (<creaturePosition> ^Y <creaturePositionY>)
   (<entityInMemory> ^TYPE FOOD)
   (<entityInMemory> ^X <entityInMemoryPositionX>)
   (<entityInMemory> ^Y <entityInMemoryPositionY>)
   (<entityInMemory> ^NAME <entityInMemoryName>)
   (<creature> ^PARAMETERS.MINFUEL <minFuel>)
-->
   (<s> ^operator <o> +)
   (<o> ^name moveFood)
   (<o> ^parameter <food>)
   (<food> ^distance (sqrt (+ (* (- <creaturePositionX> <entityInMemoryPositionX>) (- <creaturePositionX> <entityInMemoryPositionX>)) (* (- <creaturePositionY> <entityInMemoryPositionY>) (- <creaturePositionY> <entityInMemoryPositionY>)))))
   (<food> ^X <entityInMemoryPositionX>)
   (<food> ^Y <entityInMemoryPositionY>)
   (<food> ^NAME <entityInMemoryName>)
   (<o> ^parameterFuel <minFuel>)}
   
# Apply*move*food:
# If the move operator is selected, then generate an output command to it
sp {apply*move*food
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)             
   (<io> ^output-link <ol>)
   (<o> ^name moveFood)
   (<o> ^parameter <food>)
   (<food> ^X <x>)
   (<food> ^Y <y>)
   (<food> ^NAME <entityInMemoryName>)
   (<il> ^CREATURE <creature>)
   (<creature> ^MEMORY <memory>)
   (<memory> ^ENTITY <entityInMemory>)
   (<entityInMemory> ^NAME <entityInMemoryName>)
-->
   (<ol> ^MOVE <command>)
   (<command> ^Vel 1)
   (<command> ^VelR 1)
   (<command> ^VelL 1)
   (<command> ^X <x>)
   (<command> ^Y <y>)}
 
# Apply*moveFood*remove-move:
# If the moveFood operator is selected,
# and there is a completed move command on the output link,
# then remove that command.   
sp {apply*moveFood*remove-move
(state <s> ^operator.name moveFood
           ^io.output-link <out>)
(<out> ^MOVE <move>)
(<move> ^status complete)
-->
(<out> ^MOVE <move> -)}   

#Remove the food from memory because it is not there anymore
sp {apply*moveFood*remove*food
(state <s> ^operator <o>
           ^io.input-link <il>)
(<o> ^name moveFood)
(<o> ^parameter <food>)
(<food> ^X <x>)
(<food> ^Y <y>)
(<il> ^CREATURE <creature>)
(<creature> ^MEMORY <memory>)
(<memory> ^ENTITY <entityInMemory>)
(<memory> ^COUNT <quantity>)
(<entityInMemory> ^X <x>)
(<entityInMemory> ^Y <y>)      
-(<creature> ^SENSOR.VISUAL.ENTITY.X <entityX> <x>)
-(<creature> ^SENSOR.VISUAL.ENTITY.Y <entityY> <y>)
-->
(<memory> ^ENTITY <entityInMemory> -)
(<memory> ^COUNT <quantity> -
          ^COUNT (- <quantity> 1))}   

###############################  EAT FOOD  #####################################
# This operator will make the agent eat the food

# Propose*eat*food:
sp {propose*eat*food
   (state <s> ^io.input-link <il>)
   (<il> ^CREATURE <creature>)
   (<creature> ^SENSOR.VISUAL.ENTITY <entity>)
   (<entity> ^TYPE FOOD)
   (<entity> ^DISTANCE <foodDistance> < 30)
   (<entity> ^NAME <foodName>)
   (<creature> ^MEMORY.ENTITY.NAME <memoryItemName> <foodName>)     
-->
   (<s> ^operator <o> +)
   (<o> ^name eatFood)
   (<o> ^parameter <food>)
   (<food> ^NAME <foodName>)
   (<food> ^DISTANCE <foodDistance>)}
   
# Apply*eat*food:
# If the move operator is selected, then generate an output command to it
sp {apply*eat*food
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)      
   (<io> ^output-link <ol>)
   (<o> ^name eatFood)
   (<o> ^parameter.NAME <foodName>)
   (<il> ^CREATURE <creature>)
   (<creature> ^MEMORY <memory>)
   (<memory> ^COUNT <quantity>)  
   (<memory> ^ENTITY <memoryEntity>)
   (<memoryEntity> ^NAME <memoryEntityName> <foodName>)
-->
   (<ol> ^EAT <command>)
   (<command> ^Name <foodName>)
   (<memory> ^COUNT <quantity> -
             ^COUNT (- <quantity> 1))
   (<memory> ^ENTITY <memoryEntity> -)}
 
# Apply*eat*remove-move:
# If the eatFood operator is selected,
# and there is a completed move command on the output link,
# then remove that command.   
sp {apply*eatFood*remove-eat
(state <s> ^operator <o>            
           ^io.output-link <out>)
(<o> ^name eatFood)
(<o> ^parameter.name <foodName>)
(<out> ^EAT <eat>)
(<eat> ^status complete)
-->
(<out> ^EAT <eat> -)}

#############################  MOVE JEWEL  #####################################
# This operator will make the agent go straight to the jewel

# Propose*move*jewel:
sp {propose*move*jewel
   (state <s> ^io.input-link <il>)
   (<il> ^CREATURE <creature>)
   (<creature> ^MEMORY <memory>)
   (<memory> ^ENTITY <entityInMemory>)
   (<creature> ^POSITION <creaturePosition>)
   (<creaturePosition> ^X <creaturePositionX>)
   (<creaturePosition> ^Y <creaturePositionY>)
   (<entityInMemory> ^TYPE JEWEL)
   (<entityInMemory> ^X <entityInMemoryPositionX>)
   (<entityInMemory> ^Y <entityInMemoryPositionY>)
   (<entityInMemory> ^NAME <entityInMemoryName>)
   (<entityInMemory> ^COLOR <entityInMemoryColor>)
-->
   (<s> ^operator <o> +)
   (<o> ^name moveJewel)
   (<o> ^parameter <jewel>)
   (<jewel> ^distance (sqrt (+ (* (- <creaturePositionX> <entityInMemoryPositionX>) (- <creaturePositionX> <entityInMemoryPositionX>)) (* (- <creaturePositionY> <entityInMemoryPositionY>) (- <creaturePositionY> <entityInMemoryPositionY>)))))
   (<jewel> ^X <entityInMemoryPositionX>)
   (<jewel> ^Y <entityInMemoryPositionY>)
   (<jewel> ^NAME <entityInMemoryName>)
   (<jewel> ^COLOR <entityInMemoryColor>)}
   
# Apply*move*jewel:
# If the move operator is selected, then generate an output command to it
sp {apply*move*jewel
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)           
   (<io> ^output-link <ol>)
   (<o> ^name moveJewel)
   (<o> ^parameter <jewel>)
   (<jewel> ^X <x>)
   (<jewel> ^Y <y>)
   (<jewel> ^NAME <entityInMemoryName>)
   (<il> ^CREATURE <creature>)
   (<creature> ^MEMORY <memory>)
   (<memory> ^ENTITY <entityInMemory>)
   (<creature> ^leaflet.leaflet-item.item-color <Color>)
   (<entityInMemory> ^NAME <entityInMemoryName>
              ^COLOR <Color>)
-->
   (<ol> ^MOVE <command>)
   (<command> ^Vel 1)
   (<command> ^VelR 1)
   (<command> ^VelL 1)
   (<command> ^X <x>)
   (<command> ^Y <y>)}
 
# Apply*moveJewel*remove-move:
# If the moveJewel operator is selected,
# and there is a completed move command on the output link,
# then remove that command.   
sp {apply*moveJewel*remove-move
(state <s> ^operator.name moveJewel
           ^io.output-link <out>)
(<out> ^MOVE <move>)
(<move> ^status complete)
-->
(<out> ^MOVE <move> -)}   

#Remove the jewel From memory because de jewel is not there.
sp {apply*moveJewel*remove*jewel
(state <s> ^operator <o>
           ^io.input-link <il>)
(<o> ^name moveJewel
     ^parameter <jewel>)
(<jewel> ^X <x>
         ^Y <y>)
(<il> ^CREATURE <creature>)
(<creature> ^MEMORY <memory>)
(<memory> ^ENTITY <entityInMemory>)
(<memory> ^COUNT <quantity>)
(<entityInMemory> ^X <x>)
(<entityInMemory> ^Y <y>)      
-(<creature> ^SENSOR.VISUAL.ENTITY.X <entityX> <x>)
-(<creature> ^SENSOR.VISUAL.ENTITY.Y <entityY> <y>)

(<creature> ^leaflet.leaflet-item.item-color <Color>)
(<entityInMemory> ^COLOR <Color>)
-(<Color> ^captured OK)
## tem que ser igual a cor, e sem ser captured
-->
(<Color> ^captured OK)
(<memory> ^ENTITY <entityInMemory> -)
(<memory> ^COUNT <quantity> -
          ^COUNT (- <quantity> 1))
}    

##############################  GET JEWEL  #####################################
# This operator will make the agent get the jewel

# Propose*get*jewel:
sp {propose*get*jewel
   (state <s> ^io.input-link <il>)
   (<il> ^CREATURE <creature>)
   (<creature> ^SENSOR.VISUAL.ENTITY <entity>)
   (<entity> ^TYPE JEWEL)
   (<entity> ^DISTANCE <jewelDistance> < 30)
   (<entity> ^NAME <jewelName>)
   (<creature> ^MEMORY.ENTITY.NAME <memoryItemName> <jewelName>)     
-->
   (<s> ^operator <o> +)
   (<o> ^name getJewel)
   (<o> ^parameter <jewel>)
   (<jewel> ^NAME <jewelName>)
   (<jewel> ^DISTANCE <jewelDistance>)}
   
# Apply*get*jewel:
# If the move operator is selected, then generate an output command to it
sp {apply*get*jewel
   (state <s> ^operator <o>
              ^io <io>
              ^io.input-link.CREATURE.leaflet <Leaflet>)
   (<io> ^input-link <il>)      
   (<io> ^output-link <ol>)
   (<o> ^name getJewel)
   (<o> ^parameter.NAME <jewelName>)
   (<il> ^CREATURE <creature>)
   (<creature> ^MEMORY <memory>)
   (<memory> ^COUNT <quantity>)  
   (<memory> ^ENTITY <memoryEntity>)
   (<memoryEntity> ^NAME <memoryEntityName> <jewelName>)
-->
   (<ol> ^GET <command>)
   (<command> ^Name <jewelName>)
   (<memory> ^COUNT <quantity> -
             ^COUNT (- <quantity> 1))
   (<memory> ^ENTITY <memoryEntity> -)
}
 
# Apply*get*remove-move:
# If the getJewel operator is selected,
# and there is a completed move command on the output link,
# then remove that command.   
sp {apply*getJewel*remove-get
(state <s> ^operator <o>            
           ^io.output-link <out>)
(<o> ^name getJewel)
(<o> ^parameter.name <jewelName>)
(<out> ^GET <move>)
(<move> ^status complete)
-->
(<out> ^GET <move> -)}   

#############################  AVOID BRICK  ####################################
# This operator will make the agent avoid the brick
# Propose*avoid*brick:
sp {propose*avoidBrick
   (state <s> ^io.input-link <il>)
   (<il> ^CREATURE <creature>)
   (<creature> ^SENSOR.VISUAL.ENTITY <entity>)
   (<entity> ^TYPE BRICK)
   (<entity> ^DISTANCE <distance> <= 61)      
-->
   (<s> ^operator <o> +)     
   (<o> ^name avoidBrick)
   (<o> ^parameter <distance>)}
      
     
# Apply*avoidBrick:
# If the move operator is selected, then generate an output command to it
sp {apply*avoidBrick
   (state <s> ^operator <o>
              ^io <io>)
   (<o> ^name avoidBrick)
   (<o> ^parameter <distance>)              
   (<io> ^output-link <ol>)
-->
   (<ol> ^MOVE <command>)
   (<command> ^Vel  0)
   (<command> ^VelR (* 55 (/ <distance>)))
   (<command> ^VelL 0)}

#Remove the entity from memory
sp {apply*avoidBrick*remove*entity*memory
(state <s> ^operator <o>
           ^io.input-link <il>)
(<o> ^name avoidBrick)
(<o> ^entityName <entityName>)
(<il> ^CREATURE <creature>)
(<creature> ^MEMORY <memory>)
(<memory> ^COUNT <quantity>)
(<memory> ^ENTITY <entityInMemory>)           
(<entityInMemory> ^NAME <name> <entityName>)
-->
(<memory> ^ENTITY <entityInMemory> -)
(<memory> ^COUNT <quantity> -
          ^COUNT (- <quantity> 1))}             
                      
# Apply*avoidBrick*remove-move:
# If the avoidBrick operator is selected,
# and there is a completed move command on the output link,
# then remove that command.   
sp {apply*avoidBrick*remove-move
(state <s> ^operator.name avoidBrick
           ^io.output-link <out>)
(<out> ^MOVE <move>)
(<move> ^status complete)
-->
(<out> ^MOVE <move> -)}  

##################  OPERATORS PREFERENCES AND IMPASSE SOLVE  ###################

#SEE AND PROCESS ENTITY

# Move Jewel or Move Food vs See Entity
sp {moveJewel*seeEntity*preferences
(state <s> ^operator <o> +
                     <o2> +)
(<o> ^name << seeEntityWithMemoryCount seeEntityWithoutMemoryCount >>)
(<o2> ^name << moveJewel moveFood >>)
-->
(<s> ^operator <o> > <o2>)}

# See Entity With Memory vs Avoid Brick
sp {avoidBrick*seeEntityWithMemory*preferences
(state <s> ^operator <o> +
                     <o2> +)
(<o> ^name avoidBrick)
(<o2> ^name << seeEntityWithMemoryCount seeEntityWithoutMemoryCount >>)
-->
(<s> ^operator <o> > <o2>)}

# See Ententy Without Memory Preferences
sp {seeEntity*without*memory*preferences
(state <s> ^operator <o> +)
(<o> ^name << seeEntityWithMemoryCount seeEntityWithoutMemoryCount >>)
-->
(<s> ^operator <o> =)}


#JEWEL

# Move Jewel vs Get Jewel
sp {moveJewel*getJewel*preferences
(state <s> ^operator <o> +
                     <o2> +)
(<o> ^name getJewel)
(<o2> ^name << moveJewel moveFood >>)
-->
(<s> ^operator <o> > <o2>)}

# Get Jewel vs Avoid Brick
sp {getJewel*avoidBrick*preferences
(state <s> ^operator <o> +
                     <o2> +)
(<o> ^name getJewel)
(<o2> ^name avoidBrick)
-->
(<s> ^operator <o> > <o2>)}

# Move Jewel vs Move Jewel Preferences
sp {moveJewel*moveJewel*less*distance
(state <s> ^attribute operator
           ^impasse tie
           ^item <o> {<> <o> <o2>}
           ^superstate <ss>)
(<ss> ^io.input-link <il>)
(<il> ^CREATURE <creature>)                 
(<o> ^name moveJewel)
(<o2> ^name moveJewel)
(<o2> ^parameter.distance <distance2>)
(<o>  ^parameter.distance <distance> <= <distance2>)
-->
(<ss> ^operator <o> > <o2>)}

# Get Jewel vs Get Jewel Preferences
sp {getJewel*getJewel*preferences
(state <s> ^attribute operator
           ^impasse tie
           ^item <o> {<> <o> <o2>}
           ^superstate <ss>)        
(<o> ^name getJewel)
(<o2> ^name getJewel)
(<o2> ^parameter.distance <distance2>)
(<o>  ^parameter.distance <distance> <= <distance2>)
-->
(<ss> ^operator <o> > <o2>)}

# FOOD

# Move Food vs Eat Food
sp {moveFood*eatFood*preferences
(state <s> ^operator <o> +
                     <o2> +)
(<o> ^name eatFood)
(<o2> ^name << moveFood moveJewel >>)
-->
(<s> ^operator <o> > <o2>)}

# Eat Food vs Avoid Brick
sp {eatFood*avoidBrick*preferences
(state <s> ^operator <o> +
                     <o2> +)
(<o> ^name eatFood)
(<o2> ^name avoidBrick)
-->
(<s> ^operator <o> > <o2>)}

# Move Food vs Move Food Preferences
sp {moveFood*moveFood*preferences
(state <s> ^attribute operator
           ^impasse tie
           ^item <o> {<> <o> <o2>}
           ^superstate <ss>)        
(<o> ^name moveFood)
(<o2> ^name moveFood)
(<o2> ^parameter.distance <distance2>)
(<o>  ^parameter.distance <distance> <= <distance2>)
-->
(<ss> ^operator <o> > <o2>)}

# Eat Food vs Eat Food Preferences
sp {eatFood*eatFood*preferences
(state <s> ^attribute operator
           ^impasse tie
           ^item <o> {<> <o> <o2>}
           ^superstate <ss>)        
(<o> ^name eatFood)
(<o2> ^name eatFood)
(<o2> ^parameter.distance <distance2>)
(<o>  ^parameter.distance <distance> <= <distance2>)
-->
(<ss> ^operator <o> > <o2>)}

# FOOD vs JEWEL

# Move Food vs Move Jewel Preferences - Move Food Wins
sp {moveFood*moveJewel*preferences*moveFoodWins
(state <s> ^attribute operator
           ^impasse tie
           ^item <o> {<> <o> <o2>}
           ^superstate <ss>)
(<ss> ^io.input-link <il>)
(<o> ^name moveFood)
(<o> ^parameterFuel <threshold>)
(<o2> ^name moveJewel)
(<il> ^CREATURE.SENSOR.FUEL <fuel>)
(<fuel> ^VALUE <value> <= <threshold>)        
-->
(<ss> ^operator <o> > <o2>)}

# Move Food vs Move Jewel Preferences - Move Jewel Wins
sp {moveFood*moveJewel*preferences*moveJewelWins
(state <s> ^attribute operator
           ^impasse tie
           ^item <o> {<> <o> <o2>}
           ^superstate <ss>)
(<ss> ^io.input-link <il>)
(<o> ^name moveFood)
(<o> ^parameterFuel <threshold>)
(<o2> ^name moveJewel)
(<il> ^CREATURE.SENSOR.FUEL <fuel>)
(<fuel> ^VALUE <value> > <threshold>)        
-->
(<ss> ^operator <o2> > <o>)}


#BRICK  

# Avoid Brick vs Avoid Brick Preferences
sp {avoidBrick*avoidBrick*without*move*jewel*preferences
(state <s> ^attribute operator
           ^impasse tie
           ^item <o> {<> <o> <o2>}
           ^item-count <itemCount>
           ^superstate <ss>)        
(<o> ^name avoidBrick)
(<o2> ^name avoidBrick)
(<o2> ^parameter <distance2>)
(<o>  ^parameter <distance> <= <distance2>)
-->
(<ss> ^operator <o> > <o2>)}

# Avoid Brick vs Move Jewel vs Move Food Preferences with element in memory
sp {avoidBrick*moveJewel*moveFood*preferences
(state <s> ^attribute operator
           ^impasse tie
           ^item <o> {<> <o> <o2>}
           ^item-count <itemCount> 2
           ^superstate <ss>)        
(<o> ^name avoidBrick)
(<o2> ^name << moveJewel moveFood >>)
(<o2> ^parameter <entity>)
(<entity> ^NAME <entityName>)
(<ss> ^io.input-link <il>)
(<il> ^CREATURE <creature>)
(<creature> ^MEMORY <memory>)
(<memory> ^ENTITY <entityInMemory>)
(<entityInMemory> ^NAME <entityName>)
-->
(<o> ^entityName <entityName>)
(<ss> ^operator <o> > <o2>)}

# WANDER

# Wander Preferences
sp {wander*preferences
(state <s> ^operator <o> +)
(<o> ^name wander)
-->
(<s> ^operator <o> <)}


   A seguir, temos os links para acesso aos executáveis do projeto:

      WS3D

      DEMOSoar

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer