/*
  UNIVERSIDAD NACIONAL EXPERIMENTAL DEL TÁCHIRA
  Laboratorio de Computación de Alto Rendimiento (LCAR).
  
  Example: Wumpus World.
   Create a 3APL-M agent for resolution of Wumpus World.
  
 
  Author   Alfredo Enmanuel Rico Moros. Computing engineering student.
  
  Co-author, review and comment by Fernando Luiz Koch.
      
  Project: 3APL-M: Platform for lightweight BDI agents
           Institute of Information and Computer Sciences
           University of Utrecht
 
          
 */

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import mTripleApl.*;
import java.util.*;
import java.io.*;

public class ww3APLM  extends MIDlet  implements CommandListener {

  BlockWorld blockWorld;
public void startApp() {

 //------------ WUMPUS WORLD -------------
  
  // create BlockWorld    
  this.blockWorld = new BlockWorld(5, 1 ,1 );
  this.blockWorld.setCommandListener(this);
  this.blockWorld.addCommand(new Command("Exit", Command.EXIT, 1));
  Display.getDisplay(this).setCurrent(this.blockWorld);
  this.blockWorld.repaint();     
  
  
    
   Agent ag = new Agent("Wumpus");     
   ag.addActuator("MarkPerception(Action,X,Y)", new MarkPerceptionsActuator(this.blockWorld));
   ag.addActuator("AgentAction(X)", new AgentActionsActuator(this.blockWorld));
   ag.addActuator("PaintTo(WhoPaint,X,Y,Counter)", new PaintWorldActuator(this.blockWorld));
   
   //ag.setTrace(4);  //In order to print out tracing, remove comments to setTrace() method.
   ag.setGCLevel(Agent.GC_AGGRESSIVE);
   
   InputStream AgentCode = getClass().getResourceAsStream("/WumpusWorld.txt");
   ag.consult(AgentCode);
   
   InputStream PrologCode = getClass().getResourceAsStream("/WorldConfigurations.pl");
   ag.consultProlog(PrologCode);
  
   // deliberate
   ag.deliberate();
   System.out.println("-- SYSTEM STATISTICS --");
   System.out.println(ag.getStatistics());
   System.out.println("-- AGENT STATUS --");
   System.out.println(ag.toString());     
  }

  
  public void pauseApp() {
  }

  
  public void destroyApp(boolean unconditional) {
    notifyDestroyed();
  }

  
  public void commandAction(Command command, Displayable displayable) {
    if (command.getCommandType() == Command.EXIT) {
      destroyApp(true);
    }
  }
}


class AgentActionsActuator implements ActuatorInterface
     {
  BlockWorld blockWorld;

  // create: associate to world
  public AgentActionsActuator(BlockWorld blockWorld)
  {
    this.blockWorld = blockWorld;
  }

  // open: nothing to do in this case
  public void open() {}

  // close: nothing to do in this case
  public void close() {}
  // called from Deliberation engine

 // register
  public void register(String agentName) {}

  // reset
  public void reset() {}
  public boolean actuator(java.util.Hashtable hashtable) {
       Enumeration enumeration = hashtable.elements();      
       
       String command = (String)enumeration.nextElement();
       System.out.println("Order to go "+ command);

      if (command.startsWith("west")) {
        this.blockWorld.moveX( -1);
      }
      else if (command.startsWith("east")) {
        this.blockWorld.moveX(1);
      }
      else if (command.startsWith("north")) {
        this.blockWorld.moveY(1);
      }
      else if (command.startsWith("south")) {
        this.blockWorld.moveY( -1);
      }
      else if (command.startsWith("killtowumpus")) {
          this.blockWorld.KillToWumpus();
      }
      else if (command.startsWith("takegold")) {
          this.blockWorld.TakeGold();
      }
      else if (command.startsWith("TurnToNorth")) {
          this.blockWorld.SeeAtNorth();
      }
      else if (command.startsWith("TurnToSouth")) {
          this.blockWorld.SeeAtSouth();
      }
      else if (command.startsWith("TurnToEast")) {
          this.blockWorld.SeeAtEast();
      }
      else if (command.startsWith("TurnToWest")) {
          this.blockWorld.SeeAtWest();
      }      
      else if (command.startsWith("agentdied")) {
          this.blockWorld.AgentDied();
      }      
       
    return true;
  }
  
  
}
/**
 * PERCEPTION ACTUATOR TO BLOCK WORLD
 */
class MarkPerceptionsActuator implements ActuatorInterface
{
  BlockWorld blockWorld;

  // create: associate to world
  public MarkPerceptionsActuator(BlockWorld blockWorld)
  {
    this.blockWorld = blockWorld;
  }

  // open: nothing to do in this case
  public void open() {}

  // close: nothing to do in this case
  public void close() {}
  // called from Deliberation engine

 // register
  public void register(String agentName) {}

  // reset
  public void reset() {}
  public boolean actuator(java.util.Hashtable hashtable) {
       Enumeration enumeration = hashtable.elements();      
       
       String command = enumeration.nextElement().toString();
       System.out.println("Order to go "+ command);
       int X = Integer.parseInt(enumeration.nextElement().toString());  
       int Y = Integer.parseInt(enumeration.nextElement().toString());  
      
      if (command.startsWith("possiblepit")) {        
        this.blockWorld.MarkPossiblePit(X,Y);
        
      }else
       if(command.startsWith("isapit") ){         
         this.blockWorld.MarkPit(X,Y);       
       }else           
       if(command.startsWith("oknotpit") ){         
         this.blockWorld.MarkokNotPit(X,Y);       
       }    
       else
       if(command.startsWith("oknotwumpus") ){         
         this.blockWorld.MarkokNotWumpus(X,Y);       
       }else
       if(command.startsWith("ok") ){         
         this.blockWorld.ok(X,Y);       
       }else
       if(command.startsWith("possiblewumpus") ){         
         this.blockWorld.MarkPossibleWumpus(X,Y);       
       }else
       if(command.startsWith("isawumpus") ){         
         this.blockWorld.MarkWumpus(X,Y);       
       }      
          
    return true;
  } 
} 

//ACTUATOR FOR PAINT THE WORLD.
/**
 * PERCEPTION ACTUATOR TO BLOCK WORLD
 */
class PaintWorldActuator implements ActuatorInterface
{
  BlockWorld blockWorld;

  // create: associate to world
  public PaintWorldActuator(BlockWorld blockWorld)
  {
    this.blockWorld = blockWorld;
  }
  // open: nothing to do in this case
  public void open() {}

  // close: nothing to do in this case
  public void close() {}
  // called from Deliberation engine

 // register
  public void register(String agentName) {}

  public void reset() {}
  public boolean actuator(java.util.Hashtable hashtable) {
       Enumeration enumeration = hashtable.elements(); 
       String command = enumeration.nextElement().toString();
       
       if(command.startsWith("pits") )
       {          
         int Y = Integer.parseInt(enumeration.nextElement().toString());  
         int X = Integer.parseInt(enumeration.nextElement().toString());  
         int I = Integer.parseInt(enumeration.nextElement().toString());  
         this.blockWorld.PaintPits(X,Y,I);                        
       }            
        if(command.startsWith("wumpus") )   
        {
         int Y = Integer.parseInt(enumeration.nextElement().toString());  
         int X = Integer.parseInt(enumeration.nextElement().toString());              
         this.blockWorld.PaintWumpus(X,Y);                        
        }else
         if(command.startsWith("gold") )
         {
           int Y = Integer.parseInt(enumeration.nextElement().toString());  
           int X = Integer.parseInt(enumeration.nextElement().toString());              
           this.blockWorld.PaintGold(X,Y);                         
             
         }
       
          
    return true;
  } 
} 

