You are here

Atividade 2 - Alteração para coleta e entrega de LEAFLETS

Esta atividade consiste em modificar todo o sistema de integração WorldServer3D e SOAR, para que as criaturas passem a perseguir o seu "leaflet".
 
 
 
 

1. Análises iniciais

 
As primeiras dúvidas que surgiram foi a respeito dos leaflets: o que são? Como são definidos? O que exatamente consiste a tarefa requisitada?
 
Foi estudado o código do WorldServer3D e também feita uma investigação a partir do uso da sua interface via comando telnet. A partir desse estudo, concluiu-se o seguinte:
 
  • Um leaflet é uma lista que indica o tipo (cor) e quantidade de jóias que devem ser coletadas para renderem uma determinada pontuação.
  • Cada criatura pode ter uma conjunto de leaflets definidos; na solução desenvolvida, todas as criaturas criadas a partir do proxy já tem uma lista de leaflets definida.
  • Para conseguir os pontos definidos por um leaflet a criatura precisa entregar as jóias correspondentes no delivery spot existente no tabuleiro.
 
 
O conjunto de leaflets de uma criatura é fornecido pela interface através do comando getcreaturestate, como apresentado a seguir:
 
 
getcreaturestate Creature_1367191801082
 
Creature_1367191801082 0 100.0 100.0 20.0 0.0 2 0.0 0.0 1000 Yellow 1  3  1367191811095 2  White  2 0 Yellow  1 0 6   1367191811093 3  Blue  1 0 Green  1 0 Yellow  1 0 18   1367191811091 2  Blue  2 0 Yellow  1 0 16  0
 
 
O formato do comando, como já indicado durante a atividade 1 dessa aula, é o seguinte:
 
getcreaturestate <nome-criatura>
 
<nome> <index> <x> <y> <size> <pitch> <motor> <whell-spped> <speed> <fuel> <color> <has-active-leaflet> <leaflet-pool> <visual-sys>
 
 
No caso da lista de leaflets, temos a seguinte estrutura:
 
<leaft-pool>
 
<number-of-leaflets>
{
    {
        <leaflet-id>
        <number-of-item-types>
        <item-color-1>
            <item-quantity>
            <item-current-count>
                    .
                    .
        .
        <item-color-n>
            <item-quantity>
            <item-current-count>
   
        <leaflet-score>
    }
    .
    .
    . 
}
 
 
 
Ainda durante a investigação foram identificadas as seguintes características da implementação atual:
 
  • Na saída do <leaflet-pool>, o campo <item-current-count> não é atualizado corretamente, não sendo possível saber se já foi coletada uma das jóias do leaflet.
  • Não existe um comando na interface do WorldServer3D para apresentar o score ou o que uma criatura está carregando; dessa maneira, será necessário manter no lado cliente - ambiente de simulação - a lista das jóias que a criatura for coletando.
  • No WorldServer3D apenas a janela "Knapsack and Score" apresenta o que cada criatura está carregando e a sua pontuação, obtida a partir da entrega de leaflets.
  • O WorldServer3D não valida o comando "deliver": mesmo que a criatura tente entregar um leaflet que ela não tem completo, ela ganha a pontuação correspondente.
  • O comando "deliver" exige que seja indicado o "leaflet ID" como segundo parâmetro, além de receber o nome da criatura; o método CommandUtility.sendDeliverLeaflet implementa apenas o primeiro parâmetro, estando faltando o parâmetro "Leaflet ID"; esse método terá que ser modificado.
 
 

2. Sequência de operação para solução do problema

 
Considerando o problema proposto, a seguinte sequência de operação alto-nível pode ser adotada como abordagem de solução:
 
  1. A criatura mantém continuamente o registro de cada jóia que coleta;
  2. A criatura verifica continuamente se completou algum dos seus leaflets;
  3. Ao detectar um leaflet completo, a criatura vai até o "delivery spot";
  4. Ao chegar no "delivery spot" a criatura entrega o leaflet completo;
 
As etapas acima pressupõe uma série de alterações tanto na parte JAVA quanto nas regras SOAR da solução; essas alterações são descritas a seguir.
 
 
 

3. Alterações parte JAVA

 

Externalização para o SOAR dos leaflets da criatura

 
É preciso alterar o código JAVA para que seja passado para o SOAR a lista de leaflets da criatura. Será criada dentro do "input-link" a seguinte estrutura,  já abaixo da extensão já existente "^CREATURE":
 
<creature> ^LEAFLETS <ll>
<ll> ^COUNT HOW-MANY-LEAFLETS-m
 
<ll> ^LEAFLET <l-1>
<l-1> ^ID LEAFLET-1-ID
<l-1> ^PAYMENT LEAFLET-1-PAYMENT
 
<l-1> ^<COLOR-1> <ljc-1>
<ljc-1> ^TARGET HOW-MANY-TO-GET-1
        ^COUNT HOW-MANY-ALREADY-HAVE-1
.
.
.
<l-1> ^<COLOR-n> <ljc-n>
<ljc-n> ^TARGET HOW-MANY-TO-GET-n
        ^COUNT HOW-MANY-ALREADY-HAVE-n
 
<ll> ^LEAFLET <l-2>
<l-1> ^ID LEAFLET-2-ID
<l-1> ^PAYMENT LEAFLET-2-PAYMENT
.
.
.
 
 
É também preciso altearar o código JAVA para ocorrer a externalização para o SOAR do "delivery spot"; será criada a seguinte estrutura no input-link, também abaixo da extensão "^CREATURE":
 
<creature> ^DELIVERY-SPOT <ds>
<ds> ^X X-COORD
     ^Y Y-COORD
 
Para simplificar as interfaces e também garantir a atualização, ambas extensões - "^LEAFLETS" e "^DELIVERY-SPOT" - serão renovadas a cada ciclo de INPUT do SOAR.
 
 
Para realizar as externalizações acima foram feitas as seguintes alterações em arquivos do projeto DemoSOAR:
 
  1. Alterar classe "SimulationRobot" para receber e externalizar a lista de leaflets, com os novos métodos "setLeafletList()" e "getLeafletList()".
  1. Alterar class "SimulationRobot" para ter também um parâmetro "deliverySpot", também com métodos "setDeliverySpot()" e "getDeliverySpot()".
  1. Alterar método "SimulationTask.prepareAndSetupCreatureToSimulation()" para incluir no objeto "SimulationRobot" a lista de leaflets - obtida a partir do método "Creature.getLeaflets()" - e o deliverySpot - obtido a partir do método "World.getDeliverySpot()".
  1. Alterar método "SoarBridge.setupStackHolder()" para criar no agente o elemento "^LEAFLETS" e toda a sua árvore de informação, conforme descrita anteriormente.
  1. Alterar método "SoarBridge.setupStackHolder()" para criar elemento "^DELIVERY-SPOT", conforme estrutura anteriormente descrita.
  1. Alterar método "SoarBridge.clearEntitiesToNextSimulation()" para apagar elementos "^LEAFLETS" e "^DELIVERY-SPOT" da memória de trabalho, depois que o agente já consultou, garantindo a sua atualização a cada ciclo de INPUT do SOAR.
 

Comando de entrega dos leaflets

 
Ainda no código JAVA é preciso realizar as alterações para o uso do comando de entrega dos leaflets, uma vez que a criatura chegar no delivery spot. Como a implementação do CommandUtility.sendDeliverLeaflet precisará ser alterada, conforme indicado anteriormente, será necessário também alterar o projeto WS3DProxy:
 
  1. Criar a classe "SoarCommandDeliver" para representar o comando DELIVER, e que deverá ter um atributo "leafletID" e funções "getLeafletID()" e "setLeafletID()".
  1. Alterar classe "SoarCommand" para acrescentar comando DELIVER como um possível parâmetro.
  1. Alterando "SoarBridge.java" para tratar o comando DELIVER no método "SoarBridge.getReceivedCommands()", criando um objeto da classe "SoarCommandDeliver".
  1. Alterar "SimulationTask.java" para tratar comando DELIVER, criando um método "processDeliverCommand()" - onde o método "Creature.deliverLeaflet()" deverá ser chamado - e alterando "processResponseCommands()" para chamar o método anterior no caso do comando DELIVER.
  1. Alterar método "CommandUtility.sendDeliverLeaflet()" para receber parâmetro "leafletID" e compor o comando "deliver" como segundo parâmetro.
 
public static synchronized StringTokenizer sendDeliverLeaflet(String robotID, String leafletID) throws CommandExecException {
    //randomly generates a new leaflet:
    String controlMessage = "deliver " + robotID + " " + leafletID;
    return sendCmdAndGetResponse(controlMessage);
}
 
  1. Alterar método "Creature.deliverLeaflet()" para receber parâmetro "leafletID" e passá-lo para chamada de "CommandUtility.sendDeliverLeaflet()".
 
 
O diagrama a seguir apresenta o resultado final, indicando as classes que foram alteradas em vermelho:
 
 
 
 
 

4. Alterações nas regras SOAR

 

Regras para totalização por cor das jóias avistadas

 
Para facilitar a verificação de quais leaflets estão completos foram criadas regras que realizassem a totalização por cor de todas as jóias avistadas; essa totalização ficará armazenada na seguinte estrutura abaixo da extensão "^MEMORY", que permanece entre os ciclos de execução:
 
^MEMORY
 ^jewel-counters
  ^red NUM-OF-RED-JEWELS
  ^white NUM-OF-WHIITE-JEWELS
  .
  .
 .
 
Foram criadas as regras abaixo, variantes de aplicação dos operadores seeEntityWithMemoryCount e seeEntityWithoutMemoryCount:
 
#
# Jewel colors counters
#
 
sp {apply*see*entity*with-without*memory*count*update-jewel-counters*new-1
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)
   (<io> ^output-link <ol>)
   (<il> ^CREATURE <creature>)
   (<creature> ^MEMORY <memory>)  
   (<o> ^name << seeEntityWithMemoryCount seeEntityWithoutMemoryCount >>)
   (<o> ^parameterEntity <newEntity>)
   (<newEntity> ^X <x>)
   (<newEntity> ^Y <y>)
   (<newEntity> ^Name <name>)
   (<newEntity> ^Type JEWEL)
   (<newEntity> ^Color <color>)
  -(<memory> ^jewels-counters)
-->
   (<memory> ^jewels-counters.<color> 1)
   (write (crlf) | Creating | <color> | jewels counter. First counter.|)
}
 
 
sp {apply*see*entity*with-without*memory*count*update-jewel-counters*new-2
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)
   (<io> ^output-link <ol>)
   (<il> ^CREATURE <creature>)
   (<creature> ^MEMORY <memory>)  
   (<o> ^name << seeEntityWithMemoryCount seeEntityWithoutMemoryCount >>)
   (<o> ^parameterEntity <newEntity>)
   (<newEntity> ^X <x>)
   (<newEntity> ^Y <y>)
   (<newEntity> ^Name <name>)
   (<newEntity> ^Type JEWEL)
   (<newEntity> ^Color <color>)
   (<memory> ^jewels-counters <jc>)
  -(<jc> ^<color>)
-->
   (<jc> ^<color> 1)
   (write (crlf) | Creating | <color> | jewels counter. |)
}
 
 
sp {apply*see*entity*with-without*memory*count*update-jewel-counters*add
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)
   (<io> ^output-link <ol>)
   (<il> ^CREATURE <creature>)
   (<creature> ^MEMORY <memory>)  
   (<o> ^name << seeEntityWithMemoryCount seeEntityWithoutMemoryCount >>)
   (<o> ^parameterEntity <newEntity>)
   (<newEntity> ^X <x>)
   (<newEntity> ^Y <y>)
   (<newEntity> ^Name <name>)
   (<newEntity> ^Type JEWEL)
   (<newEntity> ^Color <color>)
   (<memory> ^jewels-counters <jc>)
   (<jc> ^<color> <old-value>)
-->
   (<jc> ^<color> <old-value> -
                  (+ <old-value> 1))
   (write (crlf) | Increasing | <color> | jewels counter. Value: | (+ <old-value> 1))
}
 
 
 
Além dessas regras é necessária uma outra para diminuir um contador quando a criatura pegar uma das jóias, uma vez que estão totalizadas as jóias no ambiente; essa regra foi criada como uma variante da aplicação do operador getJewel:
 
#
# Decrease the environment counter of total jewels of a given color
#
 
sp {apply*get*jewel*decrease-jewel-counter
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)      
   (<o> ^name getJewel)
   (<o> ^parameter.NAME <jewelName>)
   (<il> ^CREATURE <creature>) 
   (<creature> ^MEMORY <memory>)
   (<memory> ^jewels-counters <jc>)
   (<jc> ^<jewelColor> <jewel-color-quantity>)
   (<memory> ^ENTITY <memoryEntity>)
   (<memoryEntity> ^NAME <jewelName>
                   ^COLOR <jewelColor>)
-->
   (<jc> ^<jewelColor> <jewel-color-quantity> -
                       (- <jewel-color-quantity> 1))
   (write (crlf) | Decreasing | <jewelColor> | jewels counter. Value: | (- <jewel-color-quantity> 1))
}            
 
 

Regras para totalização das jóias coletadas - controle do sack da criatura

 
Para manter o controle de quais jóias foram coletadas e, assim, ser possível verificar quais leaflets estão completos, foi adicionada a seguinte estrutura, também abaixo da extensão "^MEMORY":
 
^MEMORY
 ^jewels-sack
  ^red NUM-OF-RED-JEWELS-IN-SACK
  .
  .
  .
 
 
As seguintes regras, também variantes da aplicação do operador getJewel,  fazem a atualização dessa estrutura:
 
#
# Increment the jewels-sack counter for the given color 
#
 
sp {apply*get*jewel*increase-jewels-sack-new-1
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)      
   (<o> ^name getJewel)
   (<o> ^parameter.NAME <jewelName>)
   (<il> ^CREATURE <creature>) 
   (<creature> ^MEMORY <memory>)
  -(<memory> ^jewels-sack)
   (<memory> ^ENTITY <memoryEntity>)
   (<memoryEntity> ^NAME <jewelName>
                   ^COLOR <jewelColor>)
-->
   (<memory> ^jewels-sack.<jewelColor> 1)
   (write (crlf) | Put the first | <jewelColor> | jewel in the sack. First of all.|)
}
 
 
sp {apply*get*jewel*increase-jewels-sack-new-2
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)      
   (<o> ^name getJewel)
   (<o> ^parameter.NAME <jewelName>)
   (<il> ^CREATURE <creature>) 
   (<creature> ^MEMORY <memory>)
   (<memory> ^jewels-sack <js>)
  -(<js> ^<jewelColor>)
   (<memory> ^ENTITY <memoryEntity>)
   (<memoryEntity> ^NAME <jewelName>
                   ^COLOR <jewelColor>)
-->
   (<js> ^<jewelColor> 1)
   (write (crlf) | Put the first | <jewelColor> | jewel in the sack.|)
}
 
 
sp {apply*get*jewel*increase-jewels-sack-new-add
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link <il>)      
   (<o> ^name getJewel)
   (<o> ^parameter.NAME <jewelName>)
   (<il> ^CREATURE <creature>) 
   (<creature> ^MEMORY <memory>)
   (<memory> ^jewels-sack <js>)
   (<js> ^<jewelColor> <quantity>)
   (<memory> ^ENTITY <memoryEntity>)
   (<memoryEntity> ^NAME <jewelName>
                   ^COLOR <jewelColor>)
-->
   (<js> ^<jewelColor> <quantity> -
                       (+ <quantity> 1))
   (write (crlf) | Put another | <jewelColor> | jewel in the sack. Color total: | (+ <quantity> 1))
}
 
 

Operador para ir até o delivery spot quando tiver um leaflet completo

 
Para criar um operador que comande o agente ir até o delivery spot, no caso de ter um leaflet completo, foi considerada a seguinte abordagem:
 
  1. Verifica se já tem todas as jóias de um determinardo leaflet e não está a menos de 30 de distância do delivery spot (nessa distância pode entregar o leaflet); propõe ir até o delivery spot, passando no operador qual a distância a ser percorrida até lá e qual o pagamento do leaflet (ambas informações serão utilizadas para definir preferência).
  2. Executa o operador de movimento para leaflet com maior pagamento.
  3. Se estiver buscando uma jóia (moveJewel) e a distância desse movimento for menor que a do delivery spot vai buscar a jóia. Caso contrário, vai para o delivery spot.
 
O primeiro trabalho é criar regras que permitam a identificação de um leaflet completo; para permitir que sejam criadas regras genéricas, que avaliem cada cor de jóia de um leaflet, foi criado o operador "updateLeaflets", cujas regras de proposição e aplicação estão a seguir:
 
#
# Elaborate the current leaflets with the counter of already get jewels
#
 
sp {propose*update-leaflets-with-jewels-in-sack
   (state <s> ^io.input-link.CREATURE.LEAFLETS <lls>)
  -(<lls> ^leaflets-done *yes*)
-->
   (<s> ^operator <o> +, >)
   (<o> ^name updateLeaflets)
   (write (crlf) | Proposing to update the leaflets list |)
}
 
 
sp {apply*update-leaflets-enough-jewels-in-sack
   (state <s> ^operator.name updateLeaflets
              ^io.input-link.CREATURE <creature>)
   (<creature> ^MEMORY.jewels-sack <js>
               ^LEAFLETS <lls>)
   (<lls> ^LEAFLET <ll>)
   (<ll> ^{<color> << Blue Green Magenta Yellow Red White >>} <ll-color>)
   (<ll-color> ^TARGET <color-target-num>)
   (<js> ^<color> <color-count-sack> >= <color-target-num>)
-->
   (<ll-color> ^in-sack <color-count-sack>)
   (<lls> ^leaflets-done *yes*)
}
 
 
sp {apply*update-leaflets-less-jewels-in-sack
   (state <s> ^operator.name updateLeaflets
              ^io.input-link.CREATURE <creature>)
   (<creature> ^MEMORY.jewels-sack <js>
               ^LEAFLETS <lls>)
   (<lls> ^LEAFLET <ll>)
   (<ll> ^{<color> << Blue Green Magenta Yellow Red White >>} <ll-color>)
   (<ll-color> ^TARGET <color-target-num>)
   (<js> ^<color> <color-count-sack> < <color-target-num>)
-->
   (<ll> ^incomplete *yes*)
   (<ll-color> ^in-sack <color-count-sack>)
   (<lls> ^leaflets-done *yes*)
}
 
 
 
sp {apply*update-leaflets-no-jewels-in-sack
   (state <s> ^operator.name updateLeaflets
              ^io.input-link.CREATURE <creature>)
   (<creature> ^LEAFLETS <lls>)
   (<lls> ^LEAFLET <ll>)
   (<ll> ^{<color> << Blue Green Magenta Yellow Red White >>} <ll-color>)
 -{(<creature> ^MEMORY.jewels-sack <js>)
   (<js> ^<color> <color-count-sack> > 0)}
-->
   (<ll> ^incomplete *yes*)
   (<ll-color> ^in-sack 0)
   (<lls> ^leaflets-done *yes*)
}
 
 
Essas regras criam uma extensão "^in-sack" para cada cor de jóia de cada leaflet; essa extensão mantém o número de jóias daquela cor que foram coletadas. Caso esse número seja menor que o número da extensão "^TARGET" da jóia - extensão que indica quantas jóias devem ser coletadas para aquele leaflet - já é criada uma extensão "^incomplete *yes*" no elemento do leaflet.
 
Dessa maneira, a identificação de um leaflet completo para a proposição do operador de ir até o delivery spot fica simplificada:
 
sp {propose*moveDeliverySpot*complete-leaflet
   (state <s> ^io.input-link.CREATURE <creature>)
   (<creature> ^DELIVERY-SPOT <ds>
               ^LEAFLETS <lls>
               ^POSITION <creaturePosition>)
   (<creaturePosition> ^X <c-x>
                       ^Y <c-y>)
   (<ds> ^X <ds-x>
         ^Y <ds-y>
         ^distance <ds-distance> > 30)
   (<lls> ^LEAFLET <ll>
          ^leaflets-done *yes*)
   (<ll> ^PAYMENT <ll-payment>
         ^ID <ll-id>
        -^incomplete *yes*)
-->
   (<s> ^operator <o> +)
   (<o> ^name moveDeliverySpot
        ^distance <ds-distance>
        ^id <ll-id>
        ^payment <ll-payment>)
   (write (crlf) | Proposing go to delivery spot for leaflet | <ll-id> | of payment | <ll-payment> | and distance | <ds-distance>)
}
 
 
Ainda para auxiliar o processo foram criadas duas regras para pré-calcular a distância do agente até o delivery spot:
 
sp {elaborate*deliverySpot*distance
   (state <s> ^io.input-link.CREATURE <creature>)
   (<creature> ^DELIVERY-SPOT <ds>
               ^LEAFLETS <lls>
               ^POSITION <creaturePosition>)
   (<creaturePosition> ^X <c-x>
                       ^Y <c-y>)
   (<ds> ^X <ds-x>
         ^Y <ds-y>)
-->
  (<ds> ^distance (sqrt (+ (* (- <c-x> <ds-x>) (- <c-x> <ds-x>)) (* (- <c-y> <ds-y>) (- <c-y> <ds-y>)))))
}
 
 
 
sp {monitor*deliverySpot*distance
   (state <s> ^io.input-link.CREATURE <creature>)
   (<creature> ^DELIVERY-SPOT.distance <ds-distance>)
-->
   (write (crlf) | Current distance to delivery spot | <ds-distance>)
}   
 
 
 
Por fim, foram criadas regras para determinar a preferência caso vários operadores para ir até o delivery spot sejam propostos, seguindo a abordagem indicada:
 
#
# moveDeliverySpot preference rules
#
 
sp {deliver-higher-payment-leaflet*moveDeliverySpot*preferences
   (state <s> ^operator <o1> +
                        <o2> +)
   (<o1> ^name moveDeliverySpot
         ^id <ll-id-1>
         ^payment <ll-payment-1>)
   (<o2> ^name moveDeliverySpot
         ^id <ll-id-2> <> <ll-id-1>
         ^payment <ll-payment-2> <= <ll-payment-1>)
-->
   (<s> ^operator <o1> > <o2>)
   (write (crlf) | Selecting to go deliver leaflet | <ll-id-1> | (| <ll-payment-1> |) instead of | <ll-id-2> | (| <ll-payment-2> |)|)
}
 
 
 
sp {moveDeliverySpot*moveJewel*preference-1
   (state <s> ^operator <o1> +
                        <o2> +
              ^io.input-link.CREATURE.DELIVERY-SPOT <ds>)
   (<ds> ^distance <distance-ds>)
   (<o1> ^name moveDeliverySpot
         ^id <ll-id-1>
         ^payment <ll-payment-1>)
   (<o2> ^name moveJewel)
   (<o2> ^parameter.distance <distance-jewel> >= <distance-ds>)
-->
   (<s> ^operator <o1> > <o2>)
   (write (crlf) | Selecting to go deliver leaflet | <ll-id-1> | (| <ll-payment-1> |, distance | 
                   <distance-ds> |) instead of moveJewel (distance | <distance-jewel> |)|)
}
 
 
sp {moveDeliverySpot*moveJewel*preference-2
   (state <s> ^operator <o1> +
                        <o2> +
              ^io.input-link.CREATURE.DELIVERY-SPOT <ds>)
   (<ds> ^distance <distance-ds>)
   (<o1> ^name moveDeliverySpot
         ^id <ll-id-1>
         ^payment <ll-payment-1>)
   (<o2> ^name moveJewel)
   (<o2> ^parameter.distance <distance-jewel> < <distance-ds>)
-->
   (<s> ^operator <o1> < <o2>)
   (write (crlf) | Selecting to moveJewel (distance | <distance-jewel> |) instead of go deliver leaflet | <ll-id-1> | (| 
                 <ll-payment-1> |, distance | <distance-ds> |) |)
}
 
 
 

Operador para realizar a entrega do leaflet

 
Uma vez que a criatura estiver no delivery spot é necessário um operador que execute o comando de entrega dos leaflets completos. Para tanto será adotada a seguinte abordagem:
 
  • Verifica se já tem todas as jóias de um determinado leaflet e está a menos de 30 de distância do delivery spot; propõe entregar o leaflet - operador deliverLeaflet - passando no operador o ID do leaflet completo e o valor de pagamento do leaflet
  • Executa preferencialmente a entrega de maior valor.
  • Este operador deliverLeaflet terá maior preferência que todos os demais.
  • Quando realizar a entrega do leaflet precisa diminuir os contadores de jóias em "^jewels-sack".
 
Seguindo essa abordagem, foram criadas as seguintes regras:
 
 
sp {propose*deliverLeaflet
   (state <s> ^io.input-link.CREATURE <creature>)
   (<creature> ^DELIVERY-SPOT <ds>
               ^LEAFLETS <lls>
               ^POSITION <creaturePosition>)
   (<creaturePosition> ^X <c-x>
                       ^Y <c-y>)
   (<ds> ^X <ds-x>
         ^Y <ds-y>
         ^distance <ds-distance> <= 30)
   (<lls> ^LEAFLET <ll>
          ^leaflets-done *yes*)
   (<ll> ^PAYMENT <ll-payment>
         ^ID <ll-id>
        -^incomplete *yes*)
-->
   (<s> ^operator <o> +, >)
   (<o> ^name deliverLeaflet
        ^id <ll-id>
        ^payment <ll-payment>)
   (write (crlf) | Proposing to deliver leaflet | <ll-id> | of payment | <ll-payment>)
}
 
 
 
sp {apply*deliverLeaflet
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^output-link <ol>)
   (<o> ^name deliverLeaflet
        ^id <ll-id>
        ^payment <ll-payment>)
-->
   (<ol> ^DELIVER <command>)
   (<command> ^id <ll-id>)
   (write (crlf) | Deliver leaflet | <ll-id> | of payment | <ll-payment>)
}
 
 
 
 
sp {apply*deliverLeaflet*decrease-jewels-sack
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^input-link.CREATURE <creature>)           
   (<io> ^output-link <ol>)
   (<o> ^name deliverLeaflet
        ^id <ll-id>)
   (<creature> ^LEAFLETS <lls>)
   (<lls> ^LEAFLET <ll>)
   (<ll> ^ID <ll-id>
         ^{<color> << Blue Green Magenta Yellow Red White >>} <ll-color>)
   (<ll-color> ^TARGET <ll-color-count>
              -^already-decreased-from-sack *yes*)
   (<creature> ^MEMORY.jewels-sack <js>)
   (<js> ^<color> <js-color-count>)
-->
   (<js> ^<color> <js-color-count> -
                  (- <js-color-count> <ll-color-count>))
   (<ll-color> ^already-decreased-from-sack *yes*)
   (write (crlf) | Leaflet | <ll-id> | delivered. Now has  | (- <js-color-count> <ll-color-count>) | | <color> | jewels in sack.|)
}
 
 
 
sp {apply*deliverLeaflet*remove-move
    (state <s> ^operator.name deliverLeaflet
           ^io.output-link <ol>)
    (<ol> ^{<cmd> << EAT GET MOVE DELIVER >>} <command>)
    (<command> ^status complete)
-->
    (<ol> ^<cmd> <command> -)
}   
 
 
 

5. Observações gerais

 
  1. A regra "apply*moveJewel*remove*jewel" está removendo uma jóia do ambiente quando não deveria, uma vez que não necessariamente a criatura está virada para a jóia quando decide se mover até ela. Essa regra foi removida aparentemente apenas com melhoria do funcionamento.
  1. Não está claro porque em "propose*see*entity*with*memory*count" ao invés de testar simplesmente a existência da extensão "^COUNT" é testado se ela tem o valor menor que 7. Esse teste foi removido aparentemente sem prejuízo ao funcionamento.
  1. Está faltando uma regra para indicar operadores "getJewel" e "eatFood" com maior preferência do que "seeEntityWithMemoryCount" e "seeEntityWithoutMemoryCount"; nessas condições o agente estava entrando em "tie-impasse" e ficava travado. Foi acrescentada a seguinte regra:
 
sp {eatFood*getJewel*preferences*over*seeEntity
(state <s> ^operator <o1> + 
                     <o2> +)
(<o1> ^name << getJewel eatFood >>)
(<o2> ^name << seeEntityWithMemoryCount seeEntityWithoutMemoryCount >>)
-->
(<s> ^operator <o1> > <o2>)
}
 
  1. De dentro do SOAR não consegue remover uma extensão que veio do INPUT-LINK; por esse motivo não pode ser utilizada a extensão "^COUNT" - criada dentro de cada cor dos leaflets a partir do JAVA - para indicar o total de jóias já coletadas. Por conta disso foi criada a extensão "^in-sack" como indicado anteriormente.
  1. Os atributos do SOAR são sensíveis à caixa alta/baixa.
  1. As regras de remoção de comandos já executados não funcionavam quando o próximo comando executado não era igual ao anterior, já que checavam o nome do operador:

 

sp {apply*wander*remove*move
(state <s> ^operator.name wander
           ^io.output-link <out>)
(<out> ^MOVE <move>)
(<move> ^status complete)
-->
(<out> ^MOVE <move> -)} 

 

Para evitar que os comandos se acumulassem no OUTPUT-LINK essas regras foram modificadas da seguinte forma:
 
sp {apply*moveFood*remove-move
(state <s> ^operator.name moveFood
           ^io.output-link <out>)
(<out> ^{<cmd> << EAT GET MOVE DELIVER >>} <move>)
(<move> ^status complete)
-->
(<out> ^<cmd> <move> -)}   
 
As regras também poderiam ter sido modificadas para que, com apenas uma, todos os comandos já executados fossem removidos.

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer