@Override
  public boolean act(Agent agent, Action action) {
    String act = action.getCode();
    Termite t = (Termite) agent;
    t.setRound(t.getRound() + 1);
    StateProps box = getVal(t.getX(), t.getY());
    t.sleep(15);

    // Agent Die and dissapears from the world
    if (act.equals("die")) {
      t.die();
      this.getVal((int) (t.getX()), (int) (t.getY())).type = StateProps.NEUTRAL;
      this.getVal((int) (t.getX()), (int) (t.getY())).value = (float) 0.5;
      increaseAgentsDie();
      updateSandC();
      return false;
    }

    // Read data in current location
    float temp = getTemperaturePercept(agent);
    String loc = t.getX() + "-" + t.getY();

    if (!((Hashtable) t.getAttribute("inf_i")).containsKey(loc)) {
      t.incExploredTerrain();
      if (t.getStatus() == Termite.SEEKING) {
        t.setPheromone((float) 0);
      }
      if (t.getStatus() == Termite.CARRYING) {
        t.setPheromone((float) 1);
      }
      ((Hashtable) t.getAttribute("inf_i")).put(loc, temp);
    }

    // sense other and send its information
    String idOther = getIdNeighborPercept(agent);

    // If there is another neighbor send its current information
    if (idOther != null) {
      if (!((Hashtable) t.getAttribute("inf_i")).isEmpty()) {
        String[] msg = new String[2]; // msg: [from|msg]
        msg[0] = (String) t.getAttribute("ID");
        msg[1] = StringSerializer.serialize(((Hashtable) t.getAttribute("inf_i")));
        NetworkMessageBuffer.getInstance().putMessage(idOther, msg);
      }
      t.incMsgSend();
    }

    String myID = (String) t.getAttribute("ID");
    String[] inbox = NetworkMessageBuffer.getInstance().getMessage(myID);

    // inbox: id | infi
    if (inbox != null) {
      t.incMsgRecv();
      boolean gotNewInf = false;
      Hashtable senderInf = (Hashtable) StringSerializer.deserialize(inbox[1]);
      Hashtable inf_i = ((Hashtable) t.getAttribute("inf_i"));

      int oldsize = inf_i.size();
      inf_i = HashtableOperations.JoinSets(inf_i, senderInf);

      t.setAttribute("inf_i", inf_i);
      if (inf_i.size() > oldsize) {
        gotNewInf = true;
      }

      // Evaluates Differences
      if (!gotNewInf) {
        t.setPheromone((float) 1.0);
        t.setStatus(Termite.CARRYING);
      } else {
        t.setPheromone((float) 0);
        t.setStatus(Termite.SEEKING);
      }
    }

    // Verifies its information is complete
    boolean complete = false;
    int aminfo = ((Hashtable) t.getAttribute("inf_i")).size();
    // System.out.println("aminfo:" + aminfo + ", size:" + width * height);
    if (completeInfo(aminfo)) {
      complete = true;
    }

    if (getRoundGetInfo() == -1 && complete) {
      System.out.println("complete! round" + t.getRound());
      setRoundGetInfo(t.getRound());
      setIdBest(t.getId());
      updateSandC();
    }

    // adjust ant's pheromone (via learning rule; goes down to 0.5)
    t.setPheromone((float) (t.getPheromone() + 0.01f * (0.5f - t.getPheromone())));

    // by now I store the pheromone in all until get the best.
    // I know it's hardcoded but is experimental.
    /*if (getRoundGetInfo() == -1) {
    t.getPhHistory().put(t.getRound(), t.getPheromone());
    t.getInfHistory().put(t.getRound(), aminfo);
    }*/
    box.pherovalue =
        (float) (box.pherovalue + 0.01 * (((Termite) t).getPheromone() - box.pherovalue));
    boolean executed;
    if (AppMain.walls.equals("wallsoff")) {
      executed = updatePiecesInWorld(t, this.getActionIndex(act));
    } else {
      executed = updatePiecesInWorldNotToroidal(t, this.getActionIndex(act));
    }
    DrawPieceInWorld(t);
    return executed;
  }