You are here

Relatório 2 - SOAR: Controlando o WorldServer3D - Atividade 2

Atividade 2

 

Objetivo

O objetivo da simulação no WorldServer é capturar os cristais e ganhar pontos. A criatura deve capturar os critais que estão especificados no seu leaftlet (Figura 1) e fazer a entrega no Delivery Spot. Ou seja, a criatura deve colocar em sua sacola apenas os cristais da cor e quantidade especificada, dirigir-se ao ponto de entrega e fazer a entrega.


Figura 1 - Leaflet da criatura no WorldServer3D

 

Modificações no DemoSOAR

Foi necessário modificar o DemoSOAR para que ele pudesse trazer o leaflet do WorldServer e evia-lo ao SOAR de uma forma que fosse possível a execução das regras.

Para fazer a leitura do leaflet, foi utilizado o WS3DProxy alterando o método prepareAndSetupCreatureToSimulation() da classe SimulationTask

simulationCreature.setLeafletList(creature.getLeaflets());

Para montar a estrutura do leaflet e envia-lo ao SOAR foi utilizada a classe SoarBridge, alterando o método setupStackHolder():

if (!creatureParameter.getLeafletList().isEmpty() && creatureLeaflet == null){
    creatureLeaflet = agent.CreateIdWME(creature, "LEAFLET");
    Map<String, Integer> colors = new HashMap<String, Integer>();
 
    for(Leaflet leaflet: creatureParameter.getLeafletList()){
 
        HashMap collect = leaflet.getWhatToCollect();
        Iterator it = collect.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pair = (Map.Entry)it.next();
            if (colors.get((String)pair.getKey()) == null){
                colors.put((String)pair.getKey(), (Integer)pair.getValue());
            }else{
                colors.put((String)pair.getKey(), colors.get((String)pair.getKey()) + (Integer)pair.getValue());
            }
        }
    }
                            
    Iterator it2 = colors.entrySet().iterator();
    while (it2.hasNext()) {
        Map.Entry pair = (Map.Entry)it2.next();
        System.out.println(pair.getKey() + ":"+ pair.getValue());
        Identifier entity = agent.CreateIdWME(creatureLeaflet, "ITEM");
        agent.CreateStringWME(entity, "COLOR", (String)pair.getKey());
        agent.CreateIntWME(entity, "QTY", (Integer)pair.getValue());
    }
}

Para que a criatura pudesse ralizar a entrega do leaflet, é necessário incluir o tratamento para o comando DELIVER.

No método processResponseCommands da classe SimulationTask, foi incluido um novo token de retorno, para que quando o SOAR retornar este comando, o mesmo possa ser enviado ao WorldServer:

case DELIVER:
    processDeliverCommand((SoarCommandDeliver)command.getCommandArgument());
    break;
 
 O comando DELIVER e o Id do leaflet a ser entregue, será passado para o WorldServer através do WS3DProxy.
 
private void processDeliverCommand(SoarCommandDeliver soarCommandDeliver) throws CommandExecException
{
    if (soarCommandDeliver != null)
    {
        c.deliverLeaflet(soarCommandDeliver.getLeafletId());
    }
    else
    {
        throw new NullPointerException("soarCommand is null");
    }
}

Também é necessário modificar o SoarBridge para montar o parâmetro do comando DELIVER:

case DELIVER:
    String leafletId = null;
 
    command = new SoarCommand(SoarCommand.CommandType.DELIVER);
    SoarCommandDeliver commandDeliver = (SoarCommandDeliver)command.getCommandArgument();
 
    if (commandDeliver != null)
    {
        leafletId = pCommand.GetParameterValue("LeafletID");
 
        if (leafletId != null)
        {
            commandDeliver.setLeafletId(leafletId);
        }
 
        commandList.add(command);
    }
 
    break;

Também é necessário modificar as regras (soar-rules.soar) para que ele leve em consideração as cores e quantidades dos cristais especificados no leaftlet da criatura ao decidir qual cristal capturar.

Regra para propor mover-se pela primeira vez a um cristal que esteja no leaflet, ou seja, quando o atributo GOT não existir para um item do leaflet.
 
sp {propose*move*jewel*firsttime
   (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>)       
   (<creature> ^LEAFLET <leaflet>)           
   (<leaflet> ^ITEM <item>)                  
   (<item> ^COLOR <colorItem>)               
   (<item> ^QTY <jewelQty> > 0)              
   -(<item> ^GOT <gotQty>)                   
   (<entityInMemory> ^COLOR <colorItem>)     
-->
   (<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>)}
 
Regra para propor mover-se a um cristal que esteja no leaflet e o número de elementos capturados (GOT) daquela cor não ultrapassar a quantidade especificada no leaflet (QTY).
 
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>)       
   (<creature> ^LEAFLET <leaflet>)          
   (<leaflet> ^ITEM <item>)                 
   (<item> ^COLOR <colorItem>)              
   (<item> ^QTY <jewelQty>)                 
   (<item> ^GOT <gotQty> < <jewelQty>)      
   (<entityInMemory> ^COLOR <colorItem>)    
-->
   (<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>)}
 
Regra para capturar um cristal que esteja no leaflet e ainda nao tenha sido capturado nenhum daquela cor, ou seja, o atributo GOT nao existe.
 
sp {apply*get*jewel*firsttime
   (state <s> ^operator <o>
              ^io <io>)
   (<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>)
   (<creature> ^LEAFLET <leaflet>)         
   (<leaflet> ^ITEM <item>)                
   (<item> ^COLOR <colorItem>)             
   -(<item> ^GOT <gotQty>)                 
   (<memoryEntity> ^COLOR <colorItem>)     
 
-->
   (<ol> ^GET <command>)
   (<command> ^Name <jewelName>)
   (<memory> ^COUNT <quantity> -
             ^COUNT (- <quantity> 1))
   (<memory> ^ENTITY <memoryEntity> -)
   (<item> ^GOT 1)}                        -> Inicializa o atributo GOT
 
Regra para capturar o cristal que esteja no leaflet e o número de elementos capturados (GOT) daquela cor não ultrapassar a quantidade especificada no leaflet (QTY).
 
sp {apply*get*jewel
   (state <s> ^operator <o>
              ^io <io>)
   (<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>)
   (<creature> ^LEAFLET <leaflet>)         
   (<leaflet> ^ITEM <item>)                
   (<item> ^COLOR <colorItem>)             
   (<item> ^GOT <gotQty>)                  
   (<memoryEntity> ^COLOR <colorItem>)     
 
-->
   (<ol> ^GET <command>)
   (<command> ^Name <jewelName>)
   (<memory> ^COUNT <quantity> -
             ^COUNT (- <quantity> 1))
   (<memory> ^ENTITY <memoryEntity> -)
   (<item> ^GOT <gotQty> -                
                (+ <gotQty> 1))          -> Incrementa o atributo GOT
   } 

Para evitar que a criatura fique bloqueada por um cristal indesejado, a regra abaixo permite a captura de cristais que estao no leaflet, apenas se estiverem proximas:

sp {apply*get*jewel*noleaflet
   (state <s> ^operator <o>
              ^io <io>)
   (<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>)
   (<creature> ^LEAFLET <leaflet>)         
   (<leaflet> ^ITEM <item>)                
   -(<item> ^COLOR <colorItem>)            
   (<memoryEntity> ^COLOR <colorItem>)     

* Estas regras ainda não permitem que o SOAR decida quando e onde entregar o leaflet. Ainda não foi possível:
Identificar qual leaflet ja está completo;
Neste estado, dirigir a criatura até o ponto de entrega;
Efetivamente realizar a entrega.

 

Código fonte

Download do codigo fonte do DemoSOAR modificado e o projeto para NetNeans.
As alterações feitas estão comentadas com a palavra "IA006"

DemoSOAR.tar.gz

 

Webstart para o DemoSOAR

WorldServer3D WebStart

DemoSOAR WebStart

 

Simulação

Na Figura 2 é possível ver a execução do DemoSOAR modificado, onde apenas os cristais contidos no leaflet são capturados. Perceba também que a quantidade de cada cristal é respeitado. Na imagem, o cristal da cor verde não foi capturado pois não está no leaflet.


Figura 2 - Finalização da simulação com a captura apenas dos cristais especificados no leaflet

Ao finalizar a captura de todos os cristais desejados, a criatura ficara no operador WANDER, pois não há mais o que ser feito.

No SoarDebugger, a estrutura dos leaflets (Figura 3) é representado como um elemento ITEM e os atributos COLOR, GOT e QTY. Onde COLOR é a cor do cristal no leaflet, QTY é a quantidade desejada e GOT é a quantidade já capturada.


Figura 3 - Estrutura do Leaflet no Input do Soar, visto através do SoarDebugger

OBS: Pode ocorrer uma captura indesejada de um cristal que não está no leaflet, caso este cristal esteja no caminho da criatura. Este comportamento é útil pois evita que a criatura fique bloqueada e continue seu percurso.

 

Utilização de 2 criaturas competindo em um mesmo ambiente

Não foi possivel realizar esta atividade. O DemoSoar finaliza de forma inexperada ao ser executado mais de uma vez tentando conectar-se a um mesmo WorldServer. Será ainda necessário investigar as causas.

 

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer