/*
     * Completely erases the current state of the Simulation
     */
    public void reset() {
      e.purgeAgents();
      paint.clearHistory();
      children.clear();
      fillWithAgents();

      Agent a = new Agent();
      a.setName("My Agent");
      a.setChrome("000 000 000 000 000 000 000 011 011 011 011 011 100 101 101 101");
      children.add(a);

      cur_gen = 0;
      current_elite = null;
      prev_elite_total = 0;
      running = true;
    }
 public void die() {
   score += (int) diescore;
   remove();
   if (dieaction.equals("die")) {
   } else if (dieaction.equals("create1")) {
     Agent agt = newAgent(1);
     agt.setPos(x, y);
   } else if (dieaction.equals("create2")) {
     Agent agt = newAgent(2);
     agt.setPos(x, y);
   } else if (dieaction.equals("create3")) {
     Agent agt = newAgent(3);
     agt.setPos(x, y);
   } else if (dieaction.equals("create4")) {
     Agent agt = newAgent(4);
     agt.setPos(x, y);
   } else if (dieaction.equals("create5")) {
     Agent agt = newAgent(5);
     agt.setPos(x, y);
   }
 }
    public void run() {

      // keep the thread alive
      while (true) {

        // wait for a signal to re-continue processing agents
        if (!running) {
          synchronized (this) {
            try {
              wait();
            } catch (InterruptedException ie) {
              System.err.println("ERROR: wait() call failed" + ie);
            }
          }
        }

        // run for the number of generations specified
        while (cur_gen < generations && running) {

          // create our list of agents
          e.purgeAgents();
          e.addAgents(children);

          // Process 100-days
          for (int i = 0; i < day_count; i++) {
            e.simulateDay();
          }

          // record this generation
          history.addGeneration(children);

          // sort the results by money, descending
          Collections.sort(children);
          Collections.reverse(children);

          // if the elite total changed, alert the main class
          int elite_most_money = children.get(0).getMoney();
          if (elite_most_money > prev_elite_total) {

            // cache the new elite total
            prev_elite_total = elite_most_money;
            current_elite = children.get(0);

            ep.setNewElite(current_elite);
            ep.repaint();

            // fire an event to the main class
            listener.actionPerformed(
                new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "elite_total"));
          }

          // now we need to select agents for crossover, mutation,
          // and elites for elites, keep the first x%
          List<Agent> elites = children.subList(0, (int) (children.size() * elite_percent));

          // for parents to keep, simply choose the top y%
          // (including the elites)
          List<Agent> parents = children.subList(0, (int) (children.size() * parent_percent));

          // create some children, and perform mutations
          children = evo.performCrossover(parents);
          children = evo.performMutation(children);

          // add the elite agents into the pool
          children.addAll(elites);

          // System.out.println(elites.get(0) + ": " + elites.get(0).getMoney());

          // reset the elites for the next generation
          for (Agent elitea : elites) elitea.reset();

          // repopulate the next generation with new Agents
          fillWithAgents();

          cur_gen++;
        }
        running = false;
      }
    }
  public void actionPerformed(ActionEvent e) {

    // dump ActionEvent information
    Object src = e.getSource();
    String msg = e.getActionCommand();

    if (src == start_stop) {

      // tell all threads to continue/resume operation
      for (ProcessSimulator ps : species)
        if (ps.toggleRunning())
          synchronized (ps) {
            ps.notify();
          }
      System.out.println("Started/Stopped Simulator...");
    } else if (src == reset) {
      for (ProcessSimulator ps : species) {
        if (!ps.isRunning()) {
          ps.reset();
          synchronized (ps) {
            ps.notify();
          }
        }
      }

      // clear the Elite Agent data
      cur_elite_genome.setText("");
      cur_elite_total.setText("");

      System.out.println("Simulation Reset...");
    } else if (src == reconfigure) {

      // create a new environment with the new parameters
      Environment environment = new Environment();

      // override existing values
      environment.setHQSale(Integer.parseInt(high_sale.getText()));
      environment.setHQRate(Integer.parseInt(high_rate.getText()));
      environment.setMQRate(Integer.parseInt(med_rate.getText()));
      environment.setMQSale(Integer.parseInt(med_sale.getText()));
      environment.setLQRate(Integer.parseInt(low_rate.getText()));
      environment.setLQSale(Integer.parseInt(low_sale.getText()));
      environment.setIncomeRatioThreshold(Double.parseDouble(agent_performance.getText()));

      for (ProcessSimulator ps : species) {
        if (!ps.isRunning()) {
          ps.replaceEnvironment(environment);

          // replace simulation values
          ps.setAgentCount(Integer.parseInt(agent_count.getText()));
          ps.setDayCount(Integer.parseInt(day_count.getText()));
          ps.setElitePercent(Double.parseDouble(elite_percent.getText()));
          ps.setGenerationCount(Integer.parseInt(generation_count.getText()));
          ps.setParentPercent(Double.parseDouble(parent_percent.getText()));
        }
      }
      System.out.println("Species Reconfigured...");
    } else if (msg == "elite_total") {

      // one of the threads has a new elite
      // TODO: Later, we are going to want to differentiate between the
      // TODO: different threads
      current_elite = ((ProcessSimulator) src).getCurrentElite();

      // update our GUI
      cur_elite_total.setText("$" + current_elite.getMoney());
      cur_elite_genome.setText(current_elite.toString());
    }
  }