[Avida-SVN] r2644 - in development/source: actions analyze cpu main

connel42 at myxo.css.msu.edu connel42 at myxo.css.msu.edu
Fri Jun 13 07:34:24 PDT 2008


Author: connel42
Date: 2008-06-13 10:34:23 -0400 (Fri, 13 Jun 2008)
New Revision: 2644

Added:
   development/source/main/cOrgMovementPredicate.h
Modified:
   development/source/actions/EnvironmentActions.cc
   development/source/actions/PopulationActions.cc
   development/source/analyze/cAnalyzeJobQueue.cc
   development/source/cpu/cHardwareCPU.cc
   development/source/cpu/cHardwareCPU.h
   development/source/cpu/cTestCPUInterface.h
   development/source/main/cAvidaConfig.h
   development/source/main/cDeme.cc
   development/source/main/cDeme.h
   development/source/main/cDemeCellEvent.cc
   development/source/main/cDemeCellEvent.h
   development/source/main/cOrgInterface.h
   development/source/main/cOrgMessagePredicate.h
   development/source/main/cOrganism.cc
   development/source/main/cOrganism.h
   development/source/main/cPopulation.cc
   development/source/main/cPopulation.h
   development/source/main/cPopulationCell.cc
   development/source/main/cPopulationInterface.h
   development/source/main/cStats.cc
   development/source/main/cStats.h
   development/source/main/cTaskContext.h
   development/source/main/cTaskLib.cc
   development/source/main/cTaskLib.h
Log:
* added deme movement and message replication predicates
* added some movement tasks
* added a few fields to organism to facilitate movement tasks



Modified: development/source/actions/EnvironmentActions.cc
===================================================================
--- development/source/actions/EnvironmentActions.cc	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/actions/EnvironmentActions.cc	2008-06-13 14:34:23 UTC (rev 2644)
@@ -726,15 +726,19 @@
   }
 };
 
+
 class cActionDelayedDemeEvent : public cAction
 {
 private:
   int m_x1, m_y1, m_x2, m_y2; // bounding box of event in deme
   int m_delay; // deme age when event occurs
   int m_duration; // length of event; subverted when deme is reset
+  bool m_static_pos;
+  int m_time_to_live; // update when event no longer exists
+  int m_id;
   
 public:
-  cActionDelayedDemeEvent(cWorld* world, const cString& args) : cAction(world, args), m_x1(-1), m_y1(-1), m_x2(-1), m_y2(-1), m_delay(-1), m_duration(-1)
+  cActionDelayedDemeEvent(cWorld* world, const cString& args) : cAction(world, args), m_x1(-1), m_y1(-1), m_x2(-1), m_y2(-1), m_delay(-1), m_duration(-1), m_static_pos(1), m_time_to_live(-1), m_id(-1)
   {
     cString largs(args);
     if (largs.GetSize()) m_x1 = largs.PopWord().AsInt();
@@ -743,16 +747,19 @@
     if (largs.GetSize()) m_y2 = largs.PopWord().AsInt();
     if (largs.GetSize()) m_delay = largs.PopWord().AsInt();
     if (largs.GetSize()) m_duration = largs.PopWord().AsInt();
+    if (largs.GetSize()) m_static_pos = largs.PopWord().AsInt();
+    if (largs.GetSize()) m_time_to_live = largs.PopWord().AsInt();
+    if (largs.GetSize()) m_id = largs.PopWord().AsInt();
   }
   
-  static const cString GetDescription() { return "Arguments: <int x1> <int y1> <int x2> <int y2> <int delay> <int duraion>"; }
+  static const cString GetDescription() { return "Arguments: <int x1> <int y1> <int x2> <int y2> <int delay> <int duraion> <int static_position> <int time_to_live> <event ID>"; }
   
   void Process(cAvidaContext& ctx)
   {
     cPopulation& pop = m_world->GetPopulation();
     int numDemes = pop.GetNumDemes();
     for(int i = 0; i < numDemes; i++) {
-      pop.GetDeme(i).SetCellEvent(m_x1, m_y1, m_x2, m_y2, m_delay, m_duration);
+      pop.GetDeme(i).SetCellEvent(m_x1, m_y1, m_x2, m_y2, m_delay, m_duration, m_static_pos, m_time_to_live, m_id);
     }
   }
 };

Modified: development/source/actions/PopulationActions.cc
===================================================================
--- development/source/actions/PopulationActions.cc	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/actions/PopulationActions.cc	2008-06-13 14:34:23 UTC (rev 2644)
@@ -565,6 +565,7 @@
         m_world->GetPopulation().Inject(genome,
                                         m_world->GetPopulation().GetDeme(i).GetCellID(0),
                                         m_merit, m_lineage_label, m_neutral_metric);
+        m_world->GetPopulation().GetDeme(i).IncInjectedCount();
       }
     } else {
       for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
@@ -573,12 +574,167 @@
         m_world->GetPopulation().Inject(genome,
                                         m_world->GetPopulation().GetDeme(i).GetCellID(0),
                                         m_merit, m_lineage_label, m_neutral_metric);
+        m_world->GetPopulation().GetDeme(i).IncInjectedCount();
+        
       }
     }
   }
 };
 
 
+/*! Injects one or more organisms into all demes in the population at a specified cell.
+ *  Note: This gets the genotype from the germline, so germline use is required
+ *  Note: one organism is inserted each time this is called, and it will stop
+ *        when the given number of organisms has been injected.
+
+  Parameters:
+    - number of orgs (int): number of organisms to inject into each deme - default 1
+    - nest cell (int): relative cell id into which organism is injected - default 0
+    - merit (double): The initial merit of the organism. If set to -1, this is ignored - default -1
+    - lineage label (integer): An integer that marks all descendants of this organism  - default 0
+    - neutral metric (double):  A double value that randomly drifts over time - default 0
+
+*/
+
+class cActionInjectDemesFromNest : public cAction
+{
+private:
+  int m_num_orgs;
+  int m_nest_cellid;
+  double m_merit;
+  int m_lineage_label;
+  double m_neutral_metric;
+  
+public:
+  cActionInjectDemesFromNest(cWorld* world, const cString& args):
+    cAction(world, args),
+    m_num_orgs(1),
+    m_nest_cellid(0),
+    m_merit(-1),
+    m_lineage_label(0),
+    m_neutral_metric(0)
+  {
+    cString largs(args);
+    if (largs.GetSize()) m_num_orgs = largs.PopWord().AsInt();
+    if (largs.GetSize()) m_nest_cellid = largs.PopWord().AsInt();
+    if (largs.GetSize()) m_merit = largs.PopWord().AsDouble();
+    if (largs.GetSize()) m_lineage_label = largs.PopWord().AsInt();
+    if (largs.GetSize()) m_neutral_metric = largs.PopWord().AsDouble();
+  } //End cActionInjectDemesFromNest constructor
+
+  static const cString GetDescription() { return "Arguments: [int num_orgs=1] [int nest_cellid=0] [double merit=-1] [int lineage_label=0] [double neutral_metric=0]"; }
+
+  void Process(cAvidaContext& ctx)
+  {
+    for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+
+      // The first deme will have initially had one organism injected.  If this
+      // is the first injection and energy is used, increment the injected
+      // count (the initial injection wasn't counted) and skip the first deme
+      // so that the energies don't get messed up.
+      if( (i==0) && (m_world->GetConfig().ENERGY_ENABLED.Get() == 1) &&
+          (m_world->GetPopulation().GetDeme(i).GetInjectedCount() == 0) ) {
+        m_world->GetPopulation().GetDeme(i).IncInjectedCount();
+        continue;
+      }
+
+      if(m_world->GetPopulation().GetDeme(i).GetInjectedCount() < m_num_orgs) {
+        m_world->GetPopulation().Inject(m_world->GetPopulation().GetDeme(i).GetGermline().GetLatest(),
+                                        m_world->GetPopulation().GetDeme(i).GetCellID(m_nest_cellid),
+                                        m_merit, m_lineage_label, m_neutral_metric);
+        m_world->GetPopulation().GetDeme(i).IncInjectedCount();
+      }
+
+    } //End iterating through demes
+
+  } //End Process()
+
+}; //End cActionInjectDemesFromNest
+
+
+
+/*! Injects one or more organisms into all demes in a randomly-chosen cell.
+ *  Note: This gets the genotype from the germline, so germline use is required
+ *  Note: one organism is inserted each time this is called, and it will stop
+ *        when the given number of organisms has been injected.
+
+  Parameters:
+    - number of orgs (int): number of organisms to inject into each deme - default 1
+    - merit (double): The initial merit of the organism. If set to -1, this is ignored - default -1
+    - lineage label (integer): An integer that marks all descendants of this organism  - default 0
+    - neutral metric (double):  A double value that randomly drifts over time - default 0
+
+*/
+
+class cActionInjectDemesRandom : public cAction
+{
+private:
+  int m_num_orgs;
+  double m_merit;
+  int m_lineage_label;
+  double m_neutral_metric;
+  
+public:
+  cActionInjectDemesRandom(cWorld* world, const cString& args):
+    cAction(world, args),
+    m_num_orgs(1),
+    m_merit(-1),
+    m_lineage_label(0),
+    m_neutral_metric(0)
+  {
+    cString largs(args);
+    if (largs.GetSize()) m_num_orgs = largs.PopWord().AsInt();
+    if (largs.GetSize()) m_merit = largs.PopWord().AsDouble();
+    if (largs.GetSize()) m_lineage_label = largs.PopWord().AsInt();
+    if (largs.GetSize()) m_neutral_metric = largs.PopWord().AsDouble();
+  } //End cActionInjectDemesRandom constructor
+
+  static const cString GetDescription() { return "Arguments: [int num_orgs=1] [double merit=-1] [int lineage_label=0] [double neutral_metric=0]"; }
+
+  void Process(cAvidaContext& ctx)
+  {
+    int target_cell, target_cellr;
+    int deme_size;
+
+    for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+
+      // The first deme will have initially had one organism injected.  If this
+      // is the first injection and energy is used, increment the injected
+      // count (the initial injection wasn't counted) and skip the first deme
+      // so that the energies don't get messed up.
+      if( (i==0) && (m_world->GetConfig().ENERGY_ENABLED.Get() == 1) &&
+          (m_world->GetPopulation().GetDeme(i).GetInjectedCount() == 0) ) {
+        m_world->GetPopulation().GetDeme(i).IncInjectedCount();
+        continue;
+      }
+
+      target_cell = -1;
+      target_cellr = -1;
+      deme_size = m_world->GetPopulation().GetDeme(i).GetSize();
+
+      // Find a random, unoccupied cell to use. Assumes one exists.
+      do {
+        target_cellr = m_world->GetRandom().GetInt(0, deme_size-1);
+        target_cell = m_world->GetPopulation().GetDeme(i).GetCellID(target_cellr);
+      } while (m_world->GetPopulation().GetCell(target_cell).IsOccupied());
+
+      assert(target_cell > -1);
+      assert(target_cell < m_world->GetPopulation().GetSize());
+
+      if(m_world->GetPopulation().GetDeme(i).GetInjectedCount() < m_num_orgs) {
+        m_world->GetPopulation().Inject(m_world->GetPopulation().GetDeme(i).GetGermline().GetLatest(), target_cell, m_merit,
+                                        m_lineage_label, m_neutral_metric);
+        m_world->GetPopulation().GetDeme(i).IncInjectedCount();
+      }
+
+    } //End iterating through demes
+
+  } //End Process()
+
+}; //End cActionInjectDemesRandom
+
+
+
 /*
  Randomly removes a certain proportion of the population.
  
@@ -1111,6 +1267,7 @@
     'corners'   - ...demes with upper left and lower right corners filled.
     'deme-age'  - ...demes that are a certain age
     'birth-count' ...demes that have had a certain number of births.
+    'sat-mov-pred'  - ...demes whose movement predicate was previously satisfied
 */
 
 class cActionReplicateDemes : public cAction
@@ -1129,6 +1286,7 @@
     else if (in_trigger == "corners") m_rep_trigger = 2;
     else if (in_trigger == "deme-age") m_rep_trigger = 3;
     else if (in_trigger == "birth-count") m_rep_trigger = 4;
+    else if (in_trigger == "sat-mov-pred") m_rep_trigger = 5;
     else {
       cString err("Unknown replication trigger '");
       err += in_trigger;
@@ -1680,7 +1838,78 @@
   }
 };
 
+/*
+ Added predicate to all demes that is satisified when an organism reaches the center of an event
+*/
+class cActionPred_DemeEventMoveCenter : public cAction
+{
+private:
+  int m_times;
 
+public:
+  cActionPred_DemeEventMoveCenter(cWorld* world, const cString& args) : cAction(world, args), m_times(1) {
+    cString largs(args);
+    if (largs.GetSize()) m_times = largs.PopWord().AsInt();
+  }
+  
+  static const cString GetDescription() { return "Arguments: [int times=1]"; }
+  
+  void Process(cAvidaContext& ctx)
+  {
+    m_world->GetPopulation().AddDemePred("EventMovedIntoCenter", m_times);
+  }
+};
+
+
+/*
+ Added predicate to all demes that is satisified when an organism reaches a target cell
+ modified cActionPred_DemeEventMoveCenter
+*/
+class cActionPred_DemeEventMoveBetweenTargets : public cAction
+{
+private:
+  int m_times;
+
+public:
+  cActionPred_DemeEventMoveBetweenTargets(cWorld* world, const cString& args) : cAction(world, args), m_times(1) {
+    cString largs(args);
+    if (largs.GetSize()) m_times = largs.PopWord().AsInt();
+  }
+  
+  static const cString GetDescription() { return "Arguments: [int times=1]"; }
+  
+  void Process(cAvidaContext& ctx)
+  {
+    m_world->GetPopulation().AddDemePred("EventMovedBetweenTargets", m_times);
+  }
+};
+
+
+/*
+ Added predicate to all demes that is satisified when a number of organisms
+ reach a target cell
+*/
+class cActionPred_DemeEventEventNUniqueIndividualsMovedIntoTarget : public cAction
+{
+private:
+  int m_numorgs;
+
+public:
+  cActionPred_DemeEventEventNUniqueIndividualsMovedIntoTarget(cWorld* world, const cString& args) : cAction(world, args), m_numorgs(1) {
+    cString largs(args);
+    if (largs.GetSize()) m_numorgs = largs.PopWord().AsInt();
+  }
+  
+  static const cString GetDescription() { return "Arguments: [int numorgs=1]"; }
+  
+  void Process(cAvidaContext& ctx)
+  {
+    m_world->GetPopulation().AddDemePred("EventNUniqueIndividualsMovedIntoTarget", m_numorgs);
+  }
+};
+
+
+
 void RegisterPopulationActions(cActionLibrary* action_lib)
 {
   action_lib->Register<cActionInject>("Inject");
@@ -1691,6 +1920,8 @@
   action_lib->Register<cActionInjectSequence>("InjectSequence");
   action_lib->Register<cActionInjectSequenceWithDivMutRate>("InjectSequenceWDivMutRate");
   action_lib->Register<cActionInjectDemes>("InjectDemes");
+  action_lib->Register<cActionInjectDemesFromNest>("InjectDemesFromNest");
+  action_lib->Register<cActionInjectDemesRandom>("InjectDemesRandom");
 
   action_lib->Register<cActionInjectParasite>("InjectParasite");
   action_lib->Register<cActionInjectParasitePair>("InjectParasitePair");
@@ -1756,4 +1987,8 @@
   action_lib->Register<cActionConnectCells>("connect_cells");
   action_lib->Register<cActionDisconnectCells>("disconnect_cells");
   action_lib->Register<cActionSwapCells>("swap_cells");
+
+  action_lib->Register<cActionPred_DemeEventMoveCenter>("Pred_DemeEventMoveCenter");
+  action_lib->Register<cActionPred_DemeEventMoveBetweenTargets>("Pred_DemeEventMoveBetweenTargets");
+  action_lib->Register<cActionPred_DemeEventEventNUniqueIndividualsMovedIntoTarget>("Pred_DemeEventNUniqueIndividualsMovedIntoTarget");
 }

Modified: development/source/analyze/cAnalyzeJobQueue.cc
===================================================================
--- development/source/analyze/cAnalyzeJobQueue.cc	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/analyze/cAnalyzeJobQueue.cc	2008-06-13 14:34:23 UTC (rev 2644)
@@ -134,4 +134,5 @@
   ctx.SetRandom(GetRandom(job->GetID()));
   job->Run(ctx);
   delete job;
-}
\ No newline at end of file
+}
+

Modified: development/source/cpu/cHardwareCPU.cc
===================================================================
--- development/source/cpu/cHardwareCPU.cc	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/cpu/cHardwareCPU.cc	2008-06-13 14:34:23 UTC (rev 2644)
@@ -394,6 +394,31 @@
     // Placebo instructions
     tInstLibEntry<tMethod>("skip", &cHardwareCPU::Inst_Skip),
 
+    // @BDC additions for pheromones
+    tInstLibEntry<tMethod>("phero-on", &cHardwareCPU::Inst_PheroOn),
+    tInstLibEntry<tMethod>("phero-off", &cHardwareCPU::Inst_PheroOff),
+    tInstLibEntry<tMethod>("pherotoggle", &cHardwareCPU::Inst_PheroToggle),
+    tInstLibEntry<tMethod>("sense-target", &cHardwareCPU::Inst_SenseTarget),
+    tInstLibEntry<tMethod>("sense-target-faced", &cHardwareCPU::Inst_SenseTargetFaced),
+    tInstLibEntry<tMethod>("sensef", &cHardwareCPU::Inst_SenseLog2Facing),
+    tInstLibEntry<tMethod>("sensef-unit", &cHardwareCPU::Inst_SenseUnitFacing),
+    tInstLibEntry<tMethod>("sensef-m100", &cHardwareCPU::Inst_SenseMult100Facing),
+    tInstLibEntry<tMethod>("sense-pheromone", &cHardwareCPU::Inst_SensePheromone),
+    tInstLibEntry<tMethod>("sense-pheromone-faced", &cHardwareCPU::Inst_SensePheromoneFaced),
+    tInstLibEntry<tMethod>("exploit", &cHardwareCPU::Inst_Exploit),
+    tInstLibEntry<tMethod>("exploit-forward5", &cHardwareCPU::Inst_ExploitForward5),
+    tInstLibEntry<tMethod>("exploit-forward3", &cHardwareCPU::Inst_ExploitForward3),
+    tInstLibEntry<tMethod>("explore", &cHardwareCPU::Inst_Explore),
+    tInstLibEntry<tMethod>("movetarget", &cHardwareCPU::Inst_MoveTarget),
+    tInstLibEntry<tMethod>("movetarget-forward5", &cHardwareCPU::Inst_MoveTargetForward5),
+    tInstLibEntry<tMethod>("movetarget-forward3", &cHardwareCPU::Inst_MoveTargetForward3),
+    tInstLibEntry<tMethod>("supermove", &cHardwareCPU::Inst_SuperMove),
+    tInstLibEntry<tMethod>("if-target", &cHardwareCPU::Inst_IfTarget),
+    tInstLibEntry<tMethod>("if-not-target", &cHardwareCPU::Inst_IfNotTarget),
+    tInstLibEntry<tMethod>("if-pheromone", &cHardwareCPU::Inst_IfPheromone),
+    tInstLibEntry<tMethod>("if-not-pheromone", &cHardwareCPU::Inst_IfNotPheromone),
+    tInstLibEntry<tMethod>("drop-pheromone", &cHardwareCPU::Inst_DropPheromone),
+
     // Must always be the last instruction in the array
     tInstLibEntry<tMethod>("NULL", &cHardwareCPU::Inst_Nop, 0, "True no-operation instruction: does nothing"),
   };
@@ -552,8 +577,7 @@
     organism->SetRunning(false);
     return false;
   }
-  
-  
+
   cPhenotype& phenotype = organism->GetPhenotype();
   
   // First instruction - check whether we should be starting at a promoter, when enabled.
@@ -3919,11 +3943,16 @@
 
   // Get population
   cPopulation& pop = m_world->GetPopulation();
-
+  cDeme &deme = pop.GetDeme(pop.GetCell(organism->GetCellID()).GetDemeID());
+  
   // Get stepsize. Currently, all moves are one cell regardless of stepsize.
   // This could be changed in the future.
   const int stepsize = m_world->GetConfig().BIOMIMETIC_MOVEMENT_STEP.Get();
-  
+
+  // Pheromone stuff
+  double pher_amount = 0;
+  int drop_mode = -1;
+
   // Code
   if (0 < stepsize) {
     // Current cell
@@ -3932,12 +3961,70 @@
     if (-1  == fromcellID) return false;
     // Destination cell
     destcellID = pop.GetCell(fromcellID).GetCellFaced().GetID();
+    
+    /*********************/
+    // TEMP.  Remove once movement tasks are implemented.
+    if(pop.GetCell(fromcellID).GetCellData() < pop.GetCell(destcellID).GetCellData()) { // move up gradient
+      organism->SetGradientMovement(1.0);
+    } else if(pop.GetCell(fromcellID).GetCellData() == pop.GetCell(destcellID).GetCellData()) {
+      organism->SetGradientMovement(0.0);
+    } else { // move down gradient
+      organism->SetGradientMovement(-1.0);    
+    }
+    /*********************/    
+    
     // Actually perform the move using SwapCells
-    //cout << "SwapCells: " << fromcellID << " to " << destcellID << endl;
     pop.SwapCells(pop.GetCell(fromcellID),pop.GetCell(destcellID));
     // Swap inputs and facings between cells using helper function
     pop.MoveOrganisms(ctx, pop.GetCell(fromcellID), pop.GetCell(destcellID));
+    
+    // updates movement predicates
+    m_world->GetStats().Move(*organism);
 
+    // If organism is dropping pheromones, mark the appropriate cell(s)
+    if( (m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1) &&
+        (organism->GetPheromoneStatus() == true) ) {
+
+        pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
+	drop_mode = m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
+	
+	if(drop_mode == 0) {
+          deme.AddPheromone(fromcellID, pher_amount/2);
+          deme.AddPheromone(destcellID, pher_amount/2);
+	} else if(drop_mode == 1) {
+          deme.AddPheromone(fromcellID, pher_amount);
+	}
+	else if(drop_mode == 2) {
+          deme.AddPheromone(destcellID, pher_amount);
+	}
+
+       // Old CellData-based version
+       //const int newval = pop.GetCell(destcellID).GetCellData() + 1;
+       //pop.GetCell(destcellID).SetCellData(newval);
+
+    } //End laying pheromone
+
+    // Write some logging information if LOG_PHEROMONE is set.  This is done
+    // out here so that non-pheromone moves are recorded.
+    if( (m_world->GetConfig().LOG_PHEROMONE.Get() == 1) &&
+        (m_world->GetStats().GetUpdate() >= m_world->GetConfig().MOVETARGET_LOG_START.Get()) ) {
+      cString tmpfilename = cStringUtil::Stringf("movelog.dat");
+      cDataFile& df = m_world->GetDataFile(tmpfilename);
+
+      int rel_srcid = deme.GetRelativeCellID(fromcellID);
+      int rel_destid = deme.GetRelativeCellID(destcellID);
+
+      cString UpdateStr = cStringUtil::Stringf("%d,%d,%d,%d,%d,%f,%d,5",  m_world->GetStats().GetUpdate(), organism->GetID(), deme.GetDemeID(), rel_srcid, rel_destid, pher_amount, drop_mode);
+      df.WriteRaw(UpdateStr);
+    }
+
+
+    // check tasks.  general movement tasks are not yet supported.
+    //organism->DoOutput(ctx);
+
+    // Brian movement
+    organism->Move(ctx);
+
     return true;
   } else {
     return false;
@@ -4798,3 +4885,1455 @@
   IP().Advance();
   return true;
 }
+
+// @BDC Pheromone-related instructions
+bool cHardwareCPU::Inst_PheroOn(cAvidaContext& ctx)
+{
+  organism->SetPheromone(true);
+  return true;
+} //End Inst_PheroOn()
+
+bool cHardwareCPU::Inst_PheroOff(cAvidaContext& ctx)
+{
+  organism->SetPheromone(false);
+  return true;
+} //End Inst_PheroOff()
+
+bool cHardwareCPU::Inst_PheroToggle(cAvidaContext& ctx)
+{
+  organism->TogglePheromone();
+  return true;
+} //End Inst_PheroToggle()
+
+// BDC: same as DoSense, but uses senses from cell that org is facing
+bool cHardwareCPU::DoSenseFacing(cAvidaContext& ctx, int conversion_method, double base)
+{
+  cPopulationCell& mycell = m_world->GetPopulation().GetCell(organism->GetCellID());
+
+  int faced_id = mycell.GetCellFaced().GetID();
+
+  // Returns the amount of a resource or resources 
+  // specified by modifying NOPs into register BX
+  const tArray<double> & res_count = m_world->GetPopulation().GetCellResources(faced_id); 
+  
+  // Arbitrarily set to BX since the conditional instructions use this directly.
+  int reg_to_set = REG_BX;
+  
+  // There are no resources, return
+  if (res_count.GetSize() == 0) return false;
+  
+  // Only recalculate logs if these values have changed
+  static int last_num_resources = 0;
+  static int max_label_length = 0;
+  int num_nops = GetInstSet().GetNumNops();
+  
+  if ((last_num_resources != res_count.GetSize()))
+  {
+    max_label_length = (int) ceil(log((double)res_count.GetSize())/log((double)num_nops));
+    last_num_resources = res_count.GetSize();
+  }
+  
+  // Convert modifying NOPs to the index of the resource.
+  // If there are fewer than the number of NOPs required
+  // to uniquely specify a resource, then add together
+  // a subset of resources (motivation: regulation can evolve
+  // to be more specific if there is an advantage)
+  
+  // Find the maximum number of NOPs needed to specify this number of resources
+  // Note: It's a bit wasteful to recalculate this every time and organisms will
+  // definitely be confused if the number of resources changes during a run
+  // because their mapping to resources will be disrupted
+  
+  // Attempt to read a label with this maximum length
+  ReadLabel(max_label_length);
+  
+  // Find the length of the label that we actually obtained (max is max_reg_needed)
+  int real_label_length = GetLabel().GetSize();
+  
+  // Start and end labels to define the start and end indices of  
+  // resources that we need to add together
+  cCodeLabel start_label = cCodeLabel(GetLabel());
+  cCodeLabel   end_label = cCodeLabel(GetLabel());
+  
+  for (int i = 0; i < max_label_length - real_label_length; i++)
+  {
+    start_label.AddNop(0);
+    end_label.AddNop(num_nops-1);
+  }
+  
+  int start_index = start_label.AsInt(num_nops);
+  int   end_index =   end_label.AsInt(num_nops);
+  
+  // If the label refers to ONLY resources that 
+  // do not exist, then the operation fails
+  if (start_index >= res_count.GetSize()) return false;
+  
+  // Otherwise sum all valid resources that it might refer to
+  // (this will only be ONE if the label was of the maximum length).
+  int resource_result = 0;
+  double dresource_result = 0;
+  for (int i = start_index; i <= end_index; i++)
+  {
+    // if it's a valid resource
+    if (i < res_count.GetSize())
+    {
+      if (conversion_method == 0) // Log
+      {
+        // for log, add together and then take log
+        dresource_result += (double) res_count[i];
+      }
+      else if (conversion_method == 1) // Addition of multiplied resource amount
+      {
+        int add_amount = (int) (res_count[i] * base);
+        // Do some range checking to make sure we don't overflow
+        resource_result = (INT_MAX - resource_result <= add_amount) ? INT_MAX : resource_result + add_amount;
+      }
+    } 
+  }
+  
+  // Take the log after adding resource amounts together! This way a zero can be assigned to INT_MIN
+  if (conversion_method == 0) // Log2
+  {
+    // You really shouldn't be using the log method if you can get to zero resources
+    if(dresource_result == 0.0)
+    {
+      resource_result = INT_MIN;
+    }
+    else
+    {
+      resource_result = (int)(log(dresource_result)/log(base));
+    }
+  }
+  
+  //Dump this value into an arbitrary register: BX
+  GetRegister(reg_to_set) = resource_result;
+  
+  //We have to convert this to a different index that includes all degenerate labels possible: shortest to longest
+  int sensed_index = 0;
+  int on = 1;
+  for (int i = 0; i < real_label_length; i++)
+  {
+    sensed_index += on;
+    on *= num_nops;
+  }
+  sensed_index+= GetLabel().AsInt(num_nops);
+  organism->GetPhenotype().IncSenseCount(sensed_index);
+  
+  return true; 
+  
+  // Note that we are converting <double> resources to <int> register values
+} //End DoSenseFacing()
+
+bool cHardwareCPU::Inst_SenseLog2Facing(cAvidaContext& ctx)
+{
+  return DoSenseFacing(ctx, 0, 2);
+}
+
+bool cHardwareCPU::Inst_SenseUnitFacing(cAvidaContext& ctx)
+{
+  return DoSenseFacing(ctx, 1, 1);
+}
+
+bool cHardwareCPU::Inst_SenseMult100Facing(cAvidaContext& ctx)
+{
+  return DoSenseFacing(ctx, 1, 100);
+}
+
+// Sense if the organism is on a target -- put 1 in reg is so, 0 otherwise
+bool cHardwareCPU::Inst_SenseTarget(cAvidaContext& ctx) {
+  int reg_to_set = FindModifiedRegister(REG_CX);
+  int cell_data = m_world->GetPopulation().GetCell(organism->GetCellID()).GetCellData();
+  int val = 0;
+
+  if(cell_data > 0) {
+    val = 1;
+  }
+
+  GetRegister(reg_to_set) = val;
+  return true;
+} //End Inst_SenseTarget()
+
+// Sense if the cell faced is a target -- put 1 in reg is so, 0 otherwise
+bool cHardwareCPU::Inst_SenseTargetFaced(cAvidaContext& ctx) {
+  int reg_to_set = FindModifiedRegister(REG_CX);
+
+  cPopulation& pop = m_world->GetPopulation();
+  cPopulationCell& mycell = pop.GetCell(organism->GetCellID());
+
+  int cell_data = mycell.GetCellFaced().GetCellData(); //absolute id of faced cell
+  int val = 0;
+
+  if(cell_data > 0) {
+    val = 1;
+  }
+
+  GetRegister(reg_to_set) = val;
+  return true;
+} //End Inst_SenseTargetFaced()
+
+// DoSensePheromone -- modified version of DoSense to only sense from
+// pheromone resource in given cell
+bool cHardwareCPU::DoSensePheromone(cAvidaContext& ctx, int cellid)
+{
+  int reg_to_set = FindModifiedRegister(REG_BX);
+
+  cPopulation& pop = m_world->GetPopulation();
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+  int relative_cell_id = deme.GetRelativeCellID(cellid);
+
+  cResourceCount deme_resource_count = deme.GetDemeResourceCount();
+  tArray<double> cell_resources = deme_resource_count.GetCellResources(relative_cell_id);
+  double pher_amount = 0;
+
+  if(deme_resource_count.GetSize() == 0) return false;
+  
+  for (int i = 0; i < deme_resource_count.GetSize(); i++) {
+    if(strncmp(deme_resource_count.GetResName(i), "pheromone", 9) == 0) {
+      pher_amount += cell_resources[i];
+    }
+  }
+
+  GetRegister(reg_to_set) = (int)round(pher_amount);
+
+  return true;
+
+} //End DoSensePheromone()
+
+bool cHardwareCPU::Inst_SensePheromone(cAvidaContext& ctx)
+{
+  int cellid = organism->GetCellID(); //absolute id of current cell
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  return DoSensePheromone(ctx, cellid);
+} //End Inst_SensePheromone()
+
+bool cHardwareCPU::Inst_SensePheromoneFaced(cAvidaContext& ctx)
+{
+  int cellid = organism->GetCellID(); //absolute id of current cell
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cPopulation& pop = m_world->GetPopulation();
+  cPopulationCell& mycell = pop.GetCell(cellid);
+
+  int fcellid = mycell.GetCellFaced().GetID(); //absolute id of faced cell
+
+  return DoSensePheromone(ctx, fcellid);
+} //End Inst_SensePheromoneFacing()
+
+bool cHardwareCPU::Inst_Exploit(cAvidaContext& ctx)
+{
+  int num_rotations = 0;
+  double phero_amount = 0;
+  double max_pheromone = 0;
+
+  cPopulation& pop = m_world->GetPopulation();
+  int cellid = organism->GetCellID();
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cPopulationCell& mycell = pop.GetCell(cellid);
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+  cResourceCount deme_resource_count = deme.GetDemeResourceCount();
+  int relative_cell_id = deme.GetRelativeCellID(cellid);
+  //tArray<double> cell_resources = deme_resource_count.GetCellResources(relative_cell_id);
+  tArray<double> cell_resources;
+
+  int fromcellID, destcellID;
+  
+  // Get stepsize. Currently, all moves are one cell regardless of stepsize.
+  // This could be changed in the future.
+  const int stepsize = m_world->GetConfig().BIOMIMETIC_MOVEMENT_STEP.Get();
+
+  // Pheromone drop stuff
+  double pher_amount = 0; // this is used in the logging
+  int drop_mode = -1;
+
+  if( (m_world->GetConfig().EXPLOIT_EXPLORE_PROB.Get() >= 0) &&
+      (m_world->GetRandom().P(m_world->GetConfig().EXPLOIT_EXPLORE_PROB.Get())) ) {
+    num_rotations = ctx.GetRandom().GetUInt(organism->GetNeighborhoodSize());
+  } else {
+    // Find which neighbor has the strongest pheromone
+    for(int i = 0; i < mycell.ConnectionList().GetSize(); i++) {
+
+      phero_amount = 0;
+      cell_resources = deme_resource_count.GetCellResources(deme.GetRelativeCellID(mycell.GetCellFaced().GetID()));
+
+      for (int j = 0; j < deme_resource_count.GetSize(); j++) {
+        if(strncmp(deme_resource_count.GetResName(j), "pheromone", 9) == 0) {
+          phero_amount += cell_resources[j];
+        }
+      }
+
+      if(phero_amount > max_pheromone) {
+        num_rotations = i;
+        max_pheromone = phero_amount;
+      }
+
+      mycell.ConnectionList().CircNext();
+    }
+  }
+
+  // Rotate until we face the neighbor with the strongest pheromone.
+  // If there was no winner, just move forward.
+  for(int i = 0; i < num_rotations; i++) {
+    mycell.ConnectionList().CircNext();
+  }
+
+  // Move to the faced cell
+  if(stepsize > 0) {
+    fromcellID = organism->GetCellID();
+
+    if(fromcellID == -1) {
+      return false;
+    }
+
+    destcellID = pop.GetCell(fromcellID).GetCellFaced().GetID();
+
+    /*********************/
+    // TEMP.  Remove once movement tasks are implemented.
+    if(pop.GetCell(fromcellID).GetCellData() < pop.GetCell(destcellID).GetCellData()) { // move up gradient
+      organism->SetGradientMovement(1.0);
+    } else if(pop.GetCell(fromcellID).GetCellData() == pop.GetCell(destcellID).GetCellData()) {
+      organism->SetGradientMovement(0.0);
+    } else { // move down gradient
+      organism->SetGradientMovement(-1.0);    
+    }
+    /*********************/ 
+
+    pop.SwapCells(pop.GetCell(fromcellID),pop.GetCell(destcellID));
+    pop.MoveOrganisms(ctx, pop.GetCell(fromcellID), pop.GetCell(destcellID));
+    
+    m_world->GetStats().Move(*organism);
+
+    // If organism is dropping pheromones, mark the appropriate cell(s)
+    if( (m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1) &&
+        (organism->GetPheromoneStatus() == true) ) {
+
+        pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
+	drop_mode = m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
+	
+	if(drop_mode == 0) {
+          deme.AddPheromone(fromcellID, pher_amount/2);
+          deme.AddPheromone(destcellID, pher_amount/2);
+	} else if(drop_mode == 1) {
+          deme.AddPheromone(fromcellID, pher_amount);
+	}
+	else if(drop_mode == 2) {
+          deme.AddPheromone(destcellID, pher_amount);
+	}
+
+    } //End laying pheromone
+
+
+    // Write some logging information if LOG_PHEROMONE is set.  This is done
+    // out here so that non-pheromone moves are recorded.
+    if( (m_world->GetConfig().LOG_PHEROMONE.Get() == 1) &&
+        (m_world->GetStats().GetUpdate() >= m_world->GetConfig().EXPLOIT_LOG_START.Get()) ) {
+      cString tmpfilename = cStringUtil::Stringf("movelog.dat");
+      cDataFile& df = m_world->GetDataFile(tmpfilename);
+
+      int rel_srcid = deme.GetRelativeCellID(fromcellID);
+      int rel_destid = deme.GetRelativeCellID(destcellID);
+
+      cString UpdateStr = cStringUtil::Stringf("%d,%d,%d,%d,%d,%f,%d,3",  m_world->GetStats().GetUpdate(), organism->GetID(), deme.GetDemeID(), rel_srcid, rel_destid, pher_amount, drop_mode);
+      df.WriteRaw(UpdateStr);
+    }
+
+    organism->Move(ctx);
+
+    return true;
+  } else {
+    return false;
+  }
+
+  return true;
+
+} //End Inst_Exploit()
+
+
+
+// Sense neighboring cells, and rotate and move to the neighbor with the
+// strongest pheromone.  If there is no winner, just move forward.
+// This instruction doesn't sense the three cells behind the organism,
+// i.e. the one directly behind, and behind and to the left and right.
+bool cHardwareCPU::Inst_ExploitForward5(cAvidaContext& ctx)
+{
+  int num_rotations = 0;
+  double phero_amount = 0;
+  double max_pheromone = 0;
+
+  cPopulation& pop = m_world->GetPopulation();
+  int cellid = organism->GetCellID();
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cPopulationCell& mycell = pop.GetCell(cellid);
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+  cResourceCount deme_resource_count = deme.GetDemeResourceCount();
+  int relative_cell_id = deme.GetRelativeCellID(cellid);
+  //tArray<double> cell_resources = deme_resource_count.GetCellResources(relative_cell_id);
+  tArray<double> cell_resources;
+
+  int fromcellID, destcellID;
+  
+  // Get stepsize. Currently, all moves are one cell regardless of stepsize.
+  // This could be changed in the future.
+  const int stepsize = m_world->GetConfig().BIOMIMETIC_MOVEMENT_STEP.Get();
+
+  // Pheromone drop stuff
+  double pher_amount = 0; // this is used in the logging.
+  int drop_mode = -1;
+
+
+  if( (m_world->GetConfig().EXPLOIT_EXPLORE_PROB.Get() >= 0) &&
+      (m_world->GetRandom().P(m_world->GetConfig().EXPLOIT_EXPLORE_PROB.Get())) ) {
+    num_rotations = ctx.GetRandom().GetUInt(organism->GetNeighborhoodSize());
+  } else {
+    // Find which neighbor has the strongest pheromone
+    for(int i = 0; i < mycell.ConnectionList().GetSize(); i++) {
+
+      // Skip the cells in the back
+      if(i == 3 || i == 4 || i == 5) {
+        mycell.ConnectionList().CircNext();
+        continue;
+      }
+
+      phero_amount = 0;
+      cell_resources = deme_resource_count.GetCellResources(deme.GetRelativeCellID(mycell.GetCellFaced().GetID()));
+
+      for (int j = 0; j < deme_resource_count.GetSize(); j++) {
+        if(strncmp(deme_resource_count.GetResName(j), "pheromone", 9) == 0) {
+          phero_amount += cell_resources[j];
+        }
+      }
+ 
+      if(phero_amount > max_pheromone) {
+        num_rotations = i;
+        max_pheromone = phero_amount;
+      }
+
+      mycell.ConnectionList().CircNext();
+    }
+  }
+
+  // Rotate until we face the neighbor with the strongest pheromone.
+  // If there was no winner, just move forward.
+  for(int i = 0; i < num_rotations; i++) {
+    mycell.ConnectionList().CircNext();
+  }
+
+  // Move to the faced cell
+  if(stepsize > 0) {
+    fromcellID = organism->GetCellID();
+
+    if(fromcellID == -1) {
+      return false;
+    }
+
+    destcellID = pop.GetCell(fromcellID).GetCellFaced().GetID();
+
+    /*********************/
+    // TEMP.  Remove once movement tasks are implemented.
+    if(pop.GetCell(fromcellID).GetCellData() < pop.GetCell(destcellID).GetCellData()) { // move up gradient
+      organism->SetGradientMovement(1.0);
+    } else if(pop.GetCell(fromcellID).GetCellData() == pop.GetCell(destcellID).GetCellData()) {
+      organism->SetGradientMovement(0.0);
+    } else { // move down gradient
+      organism->SetGradientMovement(-1.0);    
+    }
+    /*********************/ 
+
+    pop.SwapCells(pop.GetCell(fromcellID),pop.GetCell(destcellID));
+    pop.MoveOrganisms(ctx, pop.GetCell(fromcellID), pop.GetCell(destcellID));
+    
+    m_world->GetStats().Move(*organism);
+
+    // If organism is dropping pheromones, mark the appropriate cell(s)
+    if( (m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1) &&
+        (organism->GetPheromoneStatus() == true) ) {
+
+        pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
+	drop_mode = m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
+	
+	if(drop_mode == 0) {
+          deme.AddPheromone(fromcellID, pher_amount/2);
+          deme.AddPheromone(destcellID, pher_amount/2);
+	} else if(drop_mode == 1) {
+          deme.AddPheromone(fromcellID, pher_amount);
+	}
+	else if(drop_mode == 2) {
+          deme.AddPheromone(destcellID, pher_amount);
+	}
+
+    } //End laying pheromone
+
+
+    // Write some logging information if LOG_PHEROMONE is set.  This is done
+    // out here so that non-pheromone moves are recorded.
+    if( (m_world->GetConfig().LOG_PHEROMONE.Get() == 1) &&
+        (m_world->GetStats().GetUpdate() >= m_world->GetConfig().EXPLOIT_LOG_START.Get()) ) {
+      cString tmpfilename = cStringUtil::Stringf("movelog.dat");
+      cDataFile& df = m_world->GetDataFile(tmpfilename);
+
+      int rel_srcid = deme.GetRelativeCellID(fromcellID);
+      int rel_destid = deme.GetRelativeCellID(destcellID);
+
+      cString UpdateStr = cStringUtil::Stringf("%d,%d,%d,%d,%d,%f,%d,7",  m_world->GetStats().GetUpdate(), organism->GetID(), deme.GetDemeID(), rel_srcid, rel_destid, pher_amount, drop_mode);
+      df.WriteRaw(UpdateStr);
+    }
+
+    organism->Move(ctx);
+
+    return true;
+  } else {
+    return false;
+  }
+
+  return true;
+
+} //End Inst_ExploitForward5()
+
+
+// Sense neighboring cells, and rotate and move to the neighbor with the
+// strongest pheromone.  If there is no winner, just move forward.
+// This instruction doesn't sense the three cells behind the organism,
+// or the ones to the sides.
+bool cHardwareCPU::Inst_ExploitForward3(cAvidaContext& ctx)
+{
+  int num_rotations = 0;
+  double phero_amount = 0;
+  double max_pheromone = 0;
+
+  cPopulation& pop = m_world->GetPopulation();
+  int cellid = organism->GetCellID();
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cPopulationCell& mycell = pop.GetCell(cellid);
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+  cResourceCount deme_resource_count = deme.GetDemeResourceCount();
+  int relative_cell_id = deme.GetRelativeCellID(cellid);
+  //tArray<double> cell_resources = deme_resource_count.GetCellResources(relative_cell_id);
+  tArray<double> cell_resources;
+
+  int fromcellID, destcellID;
+  
+  // Get stepsize. Currently, all moves are one cell regardless of stepsize.
+  // This could be changed in the future.
+  const int stepsize = m_world->GetConfig().BIOMIMETIC_MOVEMENT_STEP.Get();
+
+  // Pheromone drop stuff
+  double pher_amount = 0; // this is used in the logging.
+  int drop_mode = -1;
+
+  if( (m_world->GetConfig().EXPLOIT_EXPLORE_PROB.Get() >= 0) &&
+      (m_world->GetRandom().P(m_world->GetConfig().EXPLOIT_EXPLORE_PROB.Get())) ) {
+    num_rotations = ctx.GetRandom().GetUInt(organism->GetNeighborhoodSize());
+  } else {
+    // Find which neighbor has the strongest pheromone
+    for(int i = 0; i < mycell.ConnectionList().GetSize(); i++) {
+
+      // Skip the cells in the back
+      if(i == 2 || i == 3 || i == 4 || i == 5 || i == 6) {
+        mycell.ConnectionList().CircNext();
+        continue;
+      }
+
+      phero_amount = 0;
+      cell_resources = deme_resource_count.GetCellResources(deme.GetRelativeCellID(mycell.GetCellFaced().GetID()));
+
+      for (int j = 0; j < deme_resource_count.GetSize(); j++) {
+        if(strncmp(deme_resource_count.GetResName(j), "pheromone", 9) == 0) {
+          phero_amount += cell_resources[j];
+        }
+      }
+
+      if(phero_amount > max_pheromone) {
+        num_rotations = i;
+        max_pheromone = phero_amount;
+      }
+
+      mycell.ConnectionList().CircNext();
+    }
+  }
+
+  // Rotate until we face the neighbor with the strongest pheromone.
+  // If there was no winner, just move forward.
+  for(int i = 0; i < num_rotations; i++) {
+    mycell.ConnectionList().CircNext();
+  }
+
+  // Move to the faced cell
+  if(stepsize > 0) {
+    fromcellID = organism->GetCellID();
+
+    if(fromcellID == -1) {
+      return false;
+    }
+
+    destcellID = pop.GetCell(fromcellID).GetCellFaced().GetID();
+
+    /*********************/
+    // TEMP.  Remove once movement tasks are implemented.
+    if(pop.GetCell(fromcellID).GetCellData() < pop.GetCell(destcellID).GetCellData()) { // move up gradient
+      organism->SetGradientMovement(1.0);
+    } else if(pop.GetCell(fromcellID).GetCellData() == pop.GetCell(destcellID).GetCellData()) {
+      organism->SetGradientMovement(0.0);
+    } else { // move down gradient
+      organism->SetGradientMovement(-1.0);    
+    }
+    /*********************/ 
+
+    pop.SwapCells(pop.GetCell(fromcellID),pop.GetCell(destcellID));
+    pop.MoveOrganisms(ctx, pop.GetCell(fromcellID), pop.GetCell(destcellID));
+    
+    m_world->GetStats().Move(*organism);
+
+    // If organism is dropping pheromones, mark the appropriate cell(s)
+    if( (m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1) &&
+        (organism->GetPheromoneStatus() == true) ) {
+
+        pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
+	drop_mode = m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
+	
+	if(drop_mode == 0) {
+          deme.AddPheromone(fromcellID, pher_amount/2);
+          deme.AddPheromone(destcellID, pher_amount/2);
+	} else if(drop_mode == 1) {
+          deme.AddPheromone(fromcellID, pher_amount);
+	}
+	else if(drop_mode == 2) {
+          deme.AddPheromone(destcellID, pher_amount);
+	}
+
+    } //End laying pheromone
+
+
+    // Write some logging information if LOG_PHEROMONE is set.  This is done
+    // out here so that non-pheromone moves are recorded.
+    if( (m_world->GetConfig().LOG_PHEROMONE.Get() == 1) &&
+        (m_world->GetStats().GetUpdate() >= m_world->GetConfig().EXPLOIT_LOG_START.Get()) ) {
+      cString tmpfilename = cStringUtil::Stringf("movelog.dat");
+      cDataFile& df = m_world->GetDataFile(tmpfilename);
+
+      int rel_srcid = deme.GetRelativeCellID(fromcellID);
+      int rel_destid = deme.GetRelativeCellID(destcellID);
+
+      cString UpdateStr = cStringUtil::Stringf("%d,%d,%d,%d,%d,%f,%d,9",  m_world->GetStats().GetUpdate(), organism->GetID(), deme.GetDemeID(), rel_srcid, rel_destid, pher_amount, drop_mode);
+      df.WriteRaw(UpdateStr);
+    }
+
+    organism->Move(ctx);
+
+    return true;
+  } else {
+    return false;
+  }
+
+  return true;
+
+} //End Inst_ExploitForward3()
+
+bool cHardwareCPU::Inst_Explore(cAvidaContext& ctx)
+{
+  int num_rotations = 0;
+
+  cPopulation& pop = m_world->GetPopulation();
+  int cellid = organism->GetCellID();
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cPopulationCell& mycell = pop.GetCell(cellid);
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+  cResourceCount deme_resource_count = deme.GetDemeResourceCount();
+
+  int fromcellID, destcellID;
+  int cell_data;
+
+  // Pheromone drop stuff
+  double pher_amount = 0;
+  int drop_mode = -1;
+
+  // Get stepsize. Currently, all moves are one cell regardless of stepsize.
+  // This could be changed in the future.
+  const int stepsize = m_world->GetConfig().BIOMIMETIC_MOVEMENT_STEP.Get();
+
+  // Rotate randomly.  Code taken from tumble.
+  const int num_neighbors = organism->GetNeighborhoodSize();
+  for(unsigned int i = 0; i < ctx.GetRandom().GetUInt(num_neighbors); i++) {
+    organism->Rotate(1);  // Rotate doesn't rotate N times, just once.
+  }
+
+
+  // Move to the faced cell
+  if(stepsize > 0) {
+    fromcellID = organism->GetCellID();
+
+    if(fromcellID == -1) {
+      return false;
+    }
+
+    destcellID = pop.GetCell(fromcellID).GetCellFaced().GetID();
+
+    /*********************/
+    // TEMP.  Remove once movement tasks are implemented.
+    if(pop.GetCell(fromcellID).GetCellData() < pop.GetCell(destcellID).GetCellData()) { // move up gradient
+      organism->SetGradientMovement(1.0);
+    } else if(pop.GetCell(fromcellID).GetCellData() == pop.GetCell(destcellID).GetCellData()) {
+      organism->SetGradientMovement(0.0);
+    } else { // move down gradient
+      organism->SetGradientMovement(-1.0);    
+    }
+    /*********************/ 
+
+    pop.SwapCells(pop.GetCell(fromcellID),pop.GetCell(destcellID));
+    pop.MoveOrganisms(ctx, pop.GetCell(fromcellID), pop.GetCell(destcellID));
+    
+    m_world->GetStats().Move(*organism);
+
+    // If organism is dropping pheromones, mark the cells appropriately
+    if( (m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1) &&
+        (organism->GetPheromoneStatus() == true) ) {
+
+        pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
+	drop_mode = m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
+	
+	if(drop_mode == 0) {
+          deme.AddPheromone(fromcellID, pher_amount/2);
+          deme.AddPheromone(destcellID, pher_amount/2);
+	} else if(drop_mode == 1) {
+          deme.AddPheromone(fromcellID, pher_amount);
+	}
+	else if(drop_mode == 2) {
+          deme.AddPheromone(destcellID, pher_amount);
+	}
+
+    } //End laying pheromone
+
+
+    // Write some logging information if LOG_PHEROMONE is set.  This is done
+    // out here so that non-pheromone moves are recorded.
+    if( (m_world->GetConfig().LOG_PHEROMONE.Get() == 1) &&
+        (m_world->GetStats().GetUpdate() >= m_world->GetConfig().EXPLORE_LOG_START.Get()) ) {
+      cString tmpfilename = cStringUtil::Stringf("movelog.dat");
+      cDataFile& df = m_world->GetDataFile(tmpfilename);
+
+      int rel_srcid = deme.GetRelativeCellID(fromcellID);
+      int rel_destid = deme.GetRelativeCellID(destcellID);
+
+      cString UpdateStr = cStringUtil::Stringf("%d,%d,%d,%d,%d,%f,%d,2",  m_world->GetStats().GetUpdate(), organism->GetID(), deme.GetDemeID(), rel_srcid, rel_destid, pher_amount, drop_mode);
+      df.WriteRaw(UpdateStr);
+    }
+
+    organism->Move(ctx);
+
+    return true;
+  } else {
+    return false;
+  }
+
+  return true;
+
+} // End Inst_Explore()
+
+// This command should move the organism to the neighbor cell that is a
+// target.  If more than one target exists, it moves towards the last-seen
+// one.  If no target exists, the organism moves forward in its original
+// facing.
+bool cHardwareCPU::Inst_MoveTarget(cAvidaContext& ctx)
+{
+  int num_rotations = 0;
+
+  cPopulation& pop = m_world->GetPopulation();
+  int cellid = organism->GetCellID();
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cPopulationCell& mycell = pop.GetCell(cellid);
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+  cResourceCount deme_resource_count = deme.GetDemeResourceCount();
+
+  int fromcellID, destcellID;
+  int cell_data;
+  
+  // Get stepsize. Currently, all moves are one cell regardless of stepsize.
+  // This could be changed in the future.
+  const int stepsize = m_world->GetConfig().BIOMIMETIC_MOVEMENT_STEP.Get();
+
+  // Pheromone drop stuff
+  double pher_amount = 0; // this is used in logging
+  int drop_mode = -1;
+
+int smc = mycell.ConnectionList().GetSize();
+ //SingleProcess shows decent-looking cellids until the end.  maybe this is a deme replication problem (probably)
+  cPopulationCell faced = mycell.GetCellFaced();
+
+  // Find if any neighbor is a target
+  for(int i = 0; i < mycell.ConnectionList().GetSize(); i++) {
+    cell_data = mycell.GetCellFaced().GetCellData();
+
+    if(cell_data > 0) {
+      num_rotations = i;
+    }
+
+    mycell.ConnectionList().CircNext();
+  }
+
+  assert(faced == pop.GetCell(fromcellID).GetCellFaced());
+
+  // Rotate until we face the neighbor with a target.
+  // If there was no winner, just move forward.
+  for(int i = 0; i < num_rotations; i++) {
+    mycell.ConnectionList().CircNext();
+  }
+
+  // Move to the faced cell
+  if(stepsize > 0) {
+    fromcellID = organism->GetCellID();
+
+    if(fromcellID == -1) {
+      return false;
+    }
+
+    destcellID = pop.GetCell(fromcellID).GetCellFaced().GetID();
+
+    /*********************/
+    // TEMP.  Remove once movement tasks are implemented.
+    if(pop.GetCell(fromcellID).GetCellData() < pop.GetCell(destcellID).GetCellData()) { // move up gradient
+      organism->SetGradientMovement(1.0);
+    } else if(pop.GetCell(fromcellID).GetCellData() == pop.GetCell(destcellID).GetCellData()) {
+      organism->SetGradientMovement(0.0);
+    } else { // move down gradient
+      organism->SetGradientMovement(-1.0);    
+    }
+    /*********************/ 
+
+    pop.SwapCells(pop.GetCell(fromcellID),pop.GetCell(destcellID));
+    pop.MoveOrganisms(ctx, pop.GetCell(fromcellID), pop.GetCell(destcellID));
+    
+    m_world->GetStats().Move(*organism);
+
+
+    // If organism is dropping pheromones, mark the appropriate cell(s)
+    if( (m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1) &&
+        (organism->GetPheromoneStatus() == true) ) {
+
+        pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
+	drop_mode = m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
+	
+	if(drop_mode == 0) {
+          deme.AddPheromone(fromcellID, pher_amount/2);
+          deme.AddPheromone(destcellID, pher_amount/2);
+	} else if(drop_mode == 1) {
+          deme.AddPheromone(fromcellID, pher_amount);
+	}
+	else if(drop_mode == 2) {
+          deme.AddPheromone(destcellID, pher_amount);
+	}
+
+    } //End laying pheromone
+
+
+    // Write some logging information if LOG_PHEROMONE is set.  This is done
+    // out here so that non-pheromone moves are recorded.
+    if( (m_world->GetConfig().LOG_PHEROMONE.Get() == 1) &&
+        (m_world->GetStats().GetUpdate() >= m_world->GetConfig().MOVETARGET_LOG_START.Get()) ) {
+      cString tmpfilename = cStringUtil::Stringf("movelog.dat");
+      cDataFile& df = m_world->GetDataFile(tmpfilename);
+
+      int rel_srcid = deme.GetRelativeCellID(fromcellID);
+      int rel_destid = deme.GetRelativeCellID(destcellID);
+
+      cString UpdateStr = cStringUtil::Stringf("%d,%d,%d,%d,%d,%f,%d,1",  m_world->GetStats().GetUpdate(), organism->GetID(), deme.GetDemeID(), rel_srcid, rel_destid, pher_amount, drop_mode);
+      df.WriteRaw(UpdateStr);
+    }
+
+    organism->Move(ctx);
+
+    return true;
+  } else {
+    return false;
+  }
+
+  return true;
+
+} // End Inst_MoveTarget()
+
+
+
+// This command should move the organism to the neighbor cell that is a
+// target.  If more than one target exists, it moves towards the last-seen
+// one.  If no target exists, the organism moves forward in its original
+// facing.  This version ignores the neighbors beind the organism, i.e.
+// the cells directly behind and behind and to the left and right.
+bool cHardwareCPU::Inst_MoveTargetForward5(cAvidaContext& ctx)
+{
+  int num_rotations = 0;
+
+  cPopulation& pop = m_world->GetPopulation();
+  int cellid = organism->GetCellID();
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cPopulationCell& mycell = pop.GetCell(cellid);
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+  cResourceCount deme_resource_count = deme.GetDemeResourceCount();
+
+  int fromcellID, destcellID;
+  int cell_data;
+  
+  // Get stepsize. Currently, all moves are one cell regardless of stepsize.
+  // This could be changed in the future.
+  const int stepsize = m_world->GetConfig().BIOMIMETIC_MOVEMENT_STEP.Get();
+
+  // Pheromone drop stuff
+  double pher_amount = 0;
+  int drop_mode = -1;
+
+  cPopulationCell faced = mycell.GetCellFaced();
+
+  // Find if any neighbor is a target
+  for(int i = 0; i < mycell.ConnectionList().GetSize(); i++) {
+    
+    // Skip the cells behind
+    if(i == 3 || i == 4 || i == 5) {
+      mycell.ConnectionList().CircNext();
+      continue;
+    }
+
+    cell_data = mycell.GetCellFaced().GetCellData();
+
+    if(cell_data > 0) {
+      num_rotations = i;
+    }
+
+    mycell.ConnectionList().CircNext();
+  }
+
+  assert(faced == pop.GetCell(fromcellID).GetCellFaced());
+
+  // Rotate until we face the neighbor with a target.
+  // If there was no winner, just move forward.
+  for(int i = 0; i < num_rotations; i++) {
+    mycell.ConnectionList().CircNext();
+  }
+
+  // Move to the faced cell
+  if(stepsize > 0) {
+    fromcellID = organism->GetCellID();
+
+    if(fromcellID == -1) {
+      return false;
+    }
+
+    destcellID = pop.GetCell(fromcellID).GetCellFaced().GetID();
+
+    /*********************/
+    // TEMP.  Remove once movement tasks are implemented.
+    if(pop.GetCell(fromcellID).GetCellData() < pop.GetCell(destcellID).GetCellData()) { // move up gradient
+      organism->SetGradientMovement(1.0);
+    } else if(pop.GetCell(fromcellID).GetCellData() == pop.GetCell(destcellID).GetCellData()) {
+      organism->SetGradientMovement(0.0);
+    } else { // move down gradient
+      organism->SetGradientMovement(-1.0);    
+    }
+    /*********************/ 
+
+    pop.SwapCells(pop.GetCell(fromcellID),pop.GetCell(destcellID));
+    pop.MoveOrganisms(ctx, pop.GetCell(fromcellID), pop.GetCell(destcellID));
+    
+    m_world->GetStats().Move(*organism);
+
+
+    // If organism is dropping pheromones, mark the appropriate cell(s)
+    if( (m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1) &&
+        (organism->GetPheromoneStatus() == true) ) {
+
+        pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
+	drop_mode = m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
+	
+	if(drop_mode == 0) {
+          deme.AddPheromone(fromcellID, pher_amount/2);
+          deme.AddPheromone(destcellID, pher_amount/2);
+	} else if(drop_mode == 1) {
+          deme.AddPheromone(fromcellID, pher_amount);
+	}
+	else if(drop_mode == 2) {
+          deme.AddPheromone(destcellID, pher_amount);
+	}
+
+    } //End laying pheromone
+
+
+    // Write some logging information if LOG_PHEROMONE is set.  This is done
+    // out here so that non-pheromone moves are recorded.
+    if( (m_world->GetConfig().LOG_PHEROMONE.Get() == 1) &&
+        (m_world->GetStats().GetUpdate() >= m_world->GetConfig().MOVETARGET_LOG_START.Get()) ) {
+      cString tmpfilename = cStringUtil::Stringf("movelog.dat");
+      cDataFile& df = m_world->GetDataFile(tmpfilename);
+
+      int rel_srcid = deme.GetRelativeCellID(fromcellID);
+      int rel_destid = deme.GetRelativeCellID(destcellID);
+
+      cString UpdateStr = cStringUtil::Stringf("%d,%d,%d,%d,%d,%f,%d,6",  m_world->GetStats().GetUpdate(), organism->GetID(), deme.GetDemeID(), rel_srcid, rel_destid, pher_amount, drop_mode);
+      df.WriteRaw(UpdateStr);
+    }
+
+    organism->Move(ctx);
+
+    return true;
+  } else {
+    return false;
+  }
+
+  return true;
+
+} // End Inst_MoveTargetForward5()
+
+
+// This command should move the organism to the neighbor cell that is a
+// target.  If more than one target exists, it moves towards the last-seen
+// one.  If no target exists, the organism moves forward in its original
+// facing.  This version ignores the neighbors beind and to the side of
+//  the organism
+bool cHardwareCPU::Inst_MoveTargetForward3(cAvidaContext& ctx)
+{
+  int num_rotations = 0;
+
+  cPopulation& pop = m_world->GetPopulation();
+  int cellid = organism->GetCellID();
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cPopulationCell& mycell = pop.GetCell(cellid);
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+  cResourceCount deme_resource_count = deme.GetDemeResourceCount();
+
+  int fromcellID, destcellID;
+  int cell_data;
+  
+  // Get stepsize. Currently, all moves are one cell regardless of stepsize.
+  // This could be changed in the future.
+  const int stepsize = m_world->GetConfig().BIOMIMETIC_MOVEMENT_STEP.Get();
+
+  // Pheromone drop stuff
+  double pher_amount = 0;
+  int drop_mode = -1;
+
+  cPopulationCell faced = mycell.GetCellFaced();
+
+  // Find if any neighbor is a target
+  for(int i = 0; i < mycell.ConnectionList().GetSize(); i++) {
+    
+    // Skip the cells behind
+    if(i==2 || i == 3 || i == 4 || i == 5 || i == 6) {
+      mycell.ConnectionList().CircNext();
+      continue;
+    }
+
+    cell_data = mycell.GetCellFaced().GetCellData();
+
+    if(cell_data > 0) {
+      num_rotations = i;
+    }
+
+    mycell.ConnectionList().CircNext();
+  }
+
+  assert(faced == pop.GetCell(fromcellID).GetCellFaced());
+
+  // Rotate until we face the neighbor with a target.
+  // If there was no winner, just move forward.
+  for(int i = 0; i < num_rotations; i++) {
+    mycell.ConnectionList().CircNext();
+  }
+
+  // Move to the faced cell
+  if(stepsize > 0) {
+    fromcellID = organism->GetCellID();
+
+    if(fromcellID == -1) {
+      return false;
+    }
+
+    destcellID = pop.GetCell(fromcellID).GetCellFaced().GetID();
+
+    /*********************/
+    // TEMP.  Remove once movement tasks are implemented.
+    if(pop.GetCell(fromcellID).GetCellData() < pop.GetCell(destcellID).GetCellData()) { // move up gradient
+      organism->SetGradientMovement(1.0);
+    } else if(pop.GetCell(fromcellID).GetCellData() == pop.GetCell(destcellID).GetCellData()) {
+      organism->SetGradientMovement(0.0);
+    } else { // move down gradient
+      organism->SetGradientMovement(-1.0);    
+    }
+    /*********************/ 
+
+    pop.SwapCells(pop.GetCell(fromcellID),pop.GetCell(destcellID));
+    pop.MoveOrganisms(ctx, pop.GetCell(fromcellID), pop.GetCell(destcellID));
+    
+    m_world->GetStats().Move(*organism);
+
+
+    // If organism is dropping pheromones, mark the appropriate cell(s)
+    if( (m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1) &&
+        (organism->GetPheromoneStatus() == true) ) {
+
+        pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
+	drop_mode = m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
+	
+	if(drop_mode == 0) {
+          deme.AddPheromone(fromcellID, pher_amount/2);
+          deme.AddPheromone(destcellID, pher_amount/2);
+	} else if(drop_mode == 1) {
+          deme.AddPheromone(fromcellID, pher_amount);
+	}
+	else if(drop_mode == 2) {
+          deme.AddPheromone(destcellID, pher_amount);
+	}
+
+    } //End laying pheromone
+
+
+    // Write some logging information if LOG_PHEROMONE is set.  This is done
+    // out here so that non-pheromone moves are recorded.
+    if( (m_world->GetConfig().LOG_PHEROMONE.Get() == 1) &&
+        (m_world->GetStats().GetUpdate() >= m_world->GetConfig().MOVETARGET_LOG_START.Get()) ) {
+      cString tmpfilename = cStringUtil::Stringf("movelog.dat");
+      cDataFile& df = m_world->GetDataFile(tmpfilename);
+
+      int rel_srcid = deme.GetRelativeCellID(fromcellID);
+      int rel_destid = deme.GetRelativeCellID(destcellID);
+
+      cString UpdateStr = cStringUtil::Stringf("%d,%d,%d,%d,%d,%f,%d,8",  m_world->GetStats().GetUpdate(), organism->GetID(), deme.GetDemeID(), rel_srcid, rel_destid, pher_amount, drop_mode);
+      df.WriteRaw(UpdateStr);
+    }
+
+    organism->Move(ctx);
+
+    return true;
+  } else {
+    return false;
+  }
+
+  return true;
+
+} // End Inst_MoveTargetForward3()
+
+bool cHardwareCPU::Inst_SuperMove(cAvidaContext& ctx)
+{
+  int num_rotations = 0;
+  float phero_amount = 0;
+  float max_pheromone = 0;
+
+  cPopulation& pop = m_world->GetPopulation();
+  int cellid = organism->GetCellID();
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cPopulationCell& mycell = pop.GetCell(cellid);
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+  cResourceCount deme_resource_count = deme.GetDemeResourceCount();
+  int relative_cell_id = deme.GetRelativeCellID(cellid);
+  tArray<double> cell_resources = deme_resource_count.GetCellResources(relative_cell_id);
+
+  int fromcellID, destcellID;
+  int cell_data;
+  
+  // Get stepsize. Currently, all moves are one cell regardless of stepsize.
+  // This could be changed in the future.
+  const int stepsize = m_world->GetConfig().BIOMIMETIC_MOVEMENT_STEP.Get();
+
+  // Pheromone drop stuff
+  double pher_amount = 0;
+  int drop_mode = -1;
+
+  // Set num_rotations to a random number for explore -- lowest priority
+  const int num_neighbors = organism->GetNeighborhoodSize();
+  num_rotations = ctx.GetRandom().GetUInt(num_neighbors);
+
+
+  // Find the neighbor with highest pheromone -- medium priority
+  for(int i = 0; i < mycell.ConnectionList().GetSize(); i++) {
+
+    phero_amount = 0;
+    cell_resources = deme_resource_count.GetCellResources(deme.GetRelativeCellID(mycell.GetCellFaced().GetID()));
+
+    for (int j = 0; j < deme_resource_count.GetSize(); j++) {
+      if(strncmp(deme_resource_count.GetResName(j), "pheromone", 9) == 0) {
+        phero_amount += cell_resources[j];
+      }
+    }
+
+    if(phero_amount > max_pheromone) {
+      num_rotations = i;
+      max_pheromone = phero_amount;
+    }
+
+    mycell.ConnectionList().CircNext();
+  }
+
+  // Find if any neighbor is a target -- highest priority
+  for(int i = 0; i < mycell.ConnectionList().GetSize(); i++) {
+    cell_data = mycell.GetCellFaced().GetCellData();
+
+    if(cell_data > 0) {
+      num_rotations = i;
+    }
+
+    mycell.ConnectionList().CircNext();
+  }
+
+  // Rotate until we face the neighbor with a target.
+  // If there was no winner, just move forward.
+  for(int i = 0; i < num_rotations; i++) {
+    mycell.ConnectionList().CircNext();
+  }
+
+  // Move to the faced cell
+  if(stepsize > 0) {
+    fromcellID = organism->GetCellID();
+
+    if(fromcellID == -1) {
+      return false;
+    }
+
+    destcellID = pop.GetCell(fromcellID).GetCellFaced().GetID();
+
+    /*********************/
+    // TEMP.  Remove once movement tasks are implemented.
+    if(pop.GetCell(fromcellID).GetCellData() < pop.GetCell(destcellID).GetCellData()) { // move up gradient
+      organism->SetGradientMovement(1.0);
+    } else if(pop.GetCell(fromcellID).GetCellData() == pop.GetCell(destcellID).GetCellData()) {
+      organism->SetGradientMovement(0.0);
+    } else { // move down gradient
+      organism->SetGradientMovement(-1.0);    
+    }
+    /*********************/ 
+
+    pop.SwapCells(pop.GetCell(fromcellID),pop.GetCell(destcellID));
+    pop.MoveOrganisms(ctx, pop.GetCell(fromcellID), pop.GetCell(destcellID));
+    
+    m_world->GetStats().Move(*organism);
+
+    // If organism is dropping pheromones, mark the appropriate cell(s)
+    if( (m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1) &&
+        (organism->GetPheromoneStatus() == true) ) {
+
+        pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
+	drop_mode = m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
+	
+	if(drop_mode == 0) {
+          deme.AddPheromone(fromcellID, pher_amount/2);
+          deme.AddPheromone(destcellID, pher_amount/2);
+	} else if(drop_mode == 1) {
+          deme.AddPheromone(fromcellID, pher_amount);
+	}
+	else if(drop_mode == 2) {
+          deme.AddPheromone(destcellID, pher_amount);
+	}
+
+    } //End laying pheromone
+
+
+    // Write some logging information if LOG_PHEROMONE is set.  This is done
+    // out here so that non-pheromone moves are recorded.
+    if( (m_world->GetConfig().LOG_PHEROMONE.Get() == 1) &&
+        (m_world->GetStats().GetUpdate() >= m_world->GetConfig().MOVETARGET_LOG_START.Get()) ) {
+      cString tmpfilename = cStringUtil::Stringf("movelog.dat");
+      cDataFile& df = m_world->GetDataFile(tmpfilename);
+
+      int rel_srcid = deme.GetRelativeCellID(fromcellID);
+      int rel_destid = deme.GetRelativeCellID(destcellID);
+
+      cString UpdateStr = cStringUtil::Stringf("%d,%d,%d,%d,%d,%f,%d,4",  m_world->GetStats().GetUpdate(), organism->GetID(), deme.GetDemeID(), rel_srcid, rel_destid, pher_amount, drop_mode);
+      df.WriteRaw(UpdateStr);
+    }
+
+    organism->Move(ctx);
+
+    return true;
+  } else {
+    return false;
+  }
+
+  return true;
+
+} // End Inst_SuperMove()
+
+bool cHardwareCPU::Inst_IfTarget(cAvidaContext& ctx)
+{
+  int cell_data = m_world->GetPopulation().GetCell(organism->GetCellID()).GetCellData();
+
+  if(cell_data == -1) {
+    IP().Advance();
+  }
+
+  return true;
+} //End Inst_IfTarget()
+
+
+bool cHardwareCPU::Inst_IfNotTarget(cAvidaContext& ctx)
+{
+  int cell_data = m_world->GetPopulation().GetCell(organism->GetCellID()).GetCellData();
+
+  if(cell_data > 0) {
+    IP().Advance();
+  }
+
+  return true;
+} //End Inst_IfNotTarget()
+
+
+bool cHardwareCPU::Inst_IfPheromone(cAvidaContext& ctx)
+{
+  int cellid = organism->GetCellID(); //absolute id of current cell
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cPopulation& pop = m_world->GetPopulation();
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+  int relative_cell_id = deme.GetRelativeCellID(cellid);
+
+  cResourceCount deme_resource_count = deme.GetDemeResourceCount();
+  tArray<double> cell_resources = deme_resource_count.GetCellResources(relative_cell_id);
+
+  if(deme_resource_count.GetSize() == 0) return false;
+
+  double pher_amount = 0;
+  
+  for (int i = 0; i < deme_resource_count.GetSize(); i++) {
+    if(strncmp(deme_resource_count.GetResName(i), "pheromone", 9) == 0) {
+      pher_amount += cell_resources[i];
+    }
+  }
+
+  if(pher_amount == 0) {
+    IP().Advance();
+  }
+
+  return true;
+
+} //End Inst_IfPheromone()
+
+
+bool cHardwareCPU::Inst_IfNotPheromone(cAvidaContext& ctx)
+{
+  int cellid = organism->GetCellID(); //absolute id of current cell
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cPopulation& pop = m_world->GetPopulation();
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+  int relative_cell_id = deme.GetRelativeCellID(cellid);
+
+  cResourceCount deme_resource_count = deme.GetDemeResourceCount();
+  tArray<double> cell_resources = deme_resource_count.GetCellResources(relative_cell_id);
+
+  if(deme_resource_count.GetSize() == 0) return false;
+
+  double pher_amount = 0;
+  
+  for (int i = 0; i < deme_resource_count.GetSize(); i++) {
+    if(strncmp(deme_resource_count.GetResName(i), "pheromone", 9) == 0) {
+      pher_amount += cell_resources[i];
+    }
+  }
+
+  if(pher_amount > 0) {
+    IP().Advance();
+  }
+
+  return true;
+
+} //End Inst_IfNotPheromone()
+
+
+bool cHardwareCPU::Inst_DropPheromone(cAvidaContext& ctx)
+{
+  cPopulation& pop = m_world->GetPopulation();
+  int cellid = organism->GetCellID();
+
+  if(cellid == -1) {
+    return true;
+  }
+
+  cDeme &deme = pop.GetDeme(pop.GetCell(cellid).GetDemeID());
+
+  // If organism is dropping pheromones, mark the appropriate cell
+  // Note: right now, we're ignoring the organism's pheromone status and always
+  //   dropping if pheromones are enabled
+  if(m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1) {
+	
+    const double pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
+    //const int drop_mode =  m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
+
+    // We can't use the different drop modes, because we only know the cell
+    // that the organism is currently in.
+    /*
+    if(drop_mode == 0) {
+      deme.AddPheromone(fromcellID, pher_amount/2);
+      deme.AddPheromone(destcellID, pher_amount/2);
+    } else if(drop_mode == 1) {
+      deme.AddPheromone(fromcellID, pher_amount);
+    } else if(drop_mode == 2) {
+      deme.AddPheromone(destcellID, pher_amount);
+    }
+    */
+    deme.AddPheromone(cellid, pher_amount);
+    
+    // Write some logging information if LOG_PHEROMONE is set.  This is done
+    // out here so that non-pheromone moves are recorded.
+    if( (m_world->GetConfig().LOG_PHEROMONE.Get() == 1) &&
+        (m_world->GetStats().GetUpdate() >= m_world->GetConfig().PHEROMONE_LOG_START.Get()) ) {
+      cString tmpfilename = cStringUtil::Stringf("drop-pheromone-log.dat");
+      cDataFile& df = m_world->GetDataFile(tmpfilename);
+
+      int rel_cellid = deme.GetRelativeCellID(cellid);
+      double pher_amount;
+      const int drop_mode =  m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
+
+      // By columns: update ID, org ID, source cell (relative), destination cell (relative), amount dropped, drop mode
+      if( (m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1) &&
+          (organism->GetPheromoneStatus() == true) ) {
+        pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
+      } else {
+        pher_amount = 0;
+      }
+
+      cString UpdateStr = cStringUtil::Stringf("%d,%d,%d,%d,%f,%d",  m_world->GetStats().GetUpdate(), organism->GetID(), deme.GetDemeID(), rel_cellid, pher_amount, drop_mode);
+      df.WriteRaw(UpdateStr);
+    }
+
+  } //End laying pheromone
+
+  return true;
+
+} //End Inst_DropPheromone()
+

Modified: development/source/cpu/cHardwareCPU.h
===================================================================
--- development/source/cpu/cHardwareCPU.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/cpu/cHardwareCPU.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -603,6 +603,34 @@
   
   //// Placebo ////
   bool Inst_Skip(cAvidaContext& ctx);
+
+  // @BDC Additions for pheromones
+  bool Inst_PheroOn(cAvidaContext& ctx);
+  bool Inst_PheroOff(cAvidaContext& ctx);
+  bool Inst_PheroToggle(cAvidaContext& ctx);
+  bool DoSenseFacing(cAvidaContext& ctx, int conversion_method, double base);
+  bool Inst_SenseLog2Facing(cAvidaContext& ctx);
+  bool Inst_SenseUnitFacing(cAvidaContext& ctx);
+  bool Inst_SenseMult100Facing(cAvidaContext& ctx);
+  bool Inst_SenseTarget(cAvidaContext& ctx);
+  bool Inst_SenseTargetFaced(cAvidaContext& ctx);
+  bool DoSensePheromone(cAvidaContext& ctx, int cellid);
+  bool Inst_SensePheromone(cAvidaContext& ctx);
+  bool Inst_SensePheromoneFaced(cAvidaContext& ctx);
+  bool Inst_Exploit(cAvidaContext& ctx);
+  bool Inst_ExploitForward5(cAvidaContext& ctx);
+  bool Inst_ExploitForward3(cAvidaContext& ctx);
+  bool Inst_Explore(cAvidaContext& ctx);
+  bool Inst_MoveTarget(cAvidaContext& ctx);
+  bool Inst_MoveTargetForward5(cAvidaContext& ctx);
+  bool Inst_MoveTargetForward3(cAvidaContext& ctx);
+  bool Inst_SuperMove(cAvidaContext& ctx);
+  bool Inst_IfTarget(cAvidaContext& ctx);
+  bool Inst_IfNotTarget(cAvidaContext& ctx);
+  bool Inst_IfPheromone(cAvidaContext& ctx);
+  bool Inst_IfNotPheromone(cAvidaContext& ctx);
+  bool Inst_DropPheromone(cAvidaContext& ctx);
+
 };
 
 

Modified: development/source/cpu/cTestCPUInterface.h
===================================================================
--- development/source/cpu/cTestCPUInterface.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/cpu/cTestCPUInterface.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -50,6 +50,13 @@
   void SetCellID(int in_id) { ; }
   void SetDemeID(int in_id) { ; }
 
+  int GetPrevSeenCellID() { return 0; }
+  int GetPrevTaskCellID() { return 0; }
+  void AddReachedTaskCell() { }
+  int GetNumTaskCellsReached() { return 0; }
+  void SetPrevSeenCellID(int in_id) { ; }
+  void SetPrevTaskCellID(int in_id) { ; }
+
   bool Divide(cAvidaContext& ctx, cOrganism* parent, cGenome& child_genome);
   cOrganism* GetNeighbor();
   int GetNumNeighbors();

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cAvidaConfig.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -274,7 +274,7 @@
   CONFIG_ADD_VAR(ANALYZE_MODE, int, 0, "0 = Disabled\n1 = Enabled\n2 = Interactive");
   CONFIG_ADD_VAR(VIEW_MODE, int, 1, "Initial viewer screen");
   CONFIG_ADD_VAR(CLONE_FILE, cString, "-", "Clone file to load");
-  CONFIG_ADD_VAR(VERBOSITY, int, 1, "0 = No output at all\n1=Normal output\n2 = Verbose output, detailing progress\n3 = High level of details, as available\n4 = Print Debug Information, as applicable");
+  CONFIG_ADD_VAR(VERBOSITY, int, 1, "0 = No output at all\n1 = Normal output\n2 = Verbose output, detailing progress\n3 = High level of details, as available\n4 = Print Debug Information, as applicable");
   
   CONFIG_ADD_GROUP(ARCH_GROUP, "Architecture Variables");
   CONFIG_ADD_VAR(WORLD_X, int, 60, "Width of the Avida world");
@@ -321,6 +321,7 @@
   CONFIG_ADD_VAR(DEMES_DEFAULT_GERMLINE_PROPENSITY, double, 0.0, "Default germline propensity of organisms in deme.\nFor use with DEMES_DIVIDE_METHOD 2.");
   CONFIG_ADD_VAR(DEMES_FOUNDER_GERMLINE_PROPENSITY, double, -1.0, "Default germline propensity of founder organisms in deme.\nFor use with DEMES_DIVIDE_METHOD 2.\n <0 = OFF");
   CONFIG_ADD_VAR(DEMES_PREFER_EMPTY, int, 0, "Give empty demes preference as targets of deme replication?");
+  CONFIG_ADD_VAR(MAX_DEME_BIRTHS, int, 500, "The maximum number of births within a deme to be\nused for birth-based replication (default=500)."); 
 
   CONFIG_ADD_GROUP(REPRODUCTION_GROUP, "Birth and Death");
   CONFIG_ADD_VAR(BIRTH_METHOD, int, 0, "Which organism should be replaced on birth?\n0 = Random organism in neighborhood\n1 = Oldest in neighborhood\n2 = Largest Age/Merit in neighborhood\n3 = None (use only empty cells in neighborhood)\n4 = Random from population (Mass Action)\n5 = Oldest in entire population\n6 = Random within deme\n7 = Organism faced by parent\n8 = Next grid cell (id+1)\n9 = Largest energy used in entire population\n10 = Largest energy used in neighborhood");
@@ -527,6 +528,20 @@
   CONFIG_ADD_VAR(BIOMIMETIC_MOVEMENT_FACTOR, double, 1.0, "Scale merit bonus due to movement (m<1.0 applies a cost)");
   CONFIG_ADD_VAR(BIOMIMETIC_EVAL_ON_MOVEMENT, int, 0, "Force task evaluation on each movement step");
   CONFIG_ADD_VAR(BIOMIMETIC_K, int, 0, "Carrying capacity in number of organisms");
+
+  // BDC: Additions for pheromones
+  CONFIG_ADD_GROUP(PHEROMONE_GROUP, "Pheromone Settings");
+  CONFIG_ADD_VAR(PHEROMONE_ENABLED, bool, 0, "Enable pheromone usage. 0/1 (off/on)");
+  CONFIG_ADD_VAR(PHEROMONE_AMOUNT, double, 1.0, "Amount of pheromone to add per drop");
+  CONFIG_ADD_VAR(PHEROMONE_DROP_MODE, int, 0, "Where to drop pheromone\n0 = Half amount at src, half at dest\n1 = All at source\n2 = All at dest");
+  CONFIG_ADD_VAR(EXPLOIT_EXPLORE_PROB, double, 0.00, "Probability of random exploration\ninstead of pheromone trail following");
+  CONFIG_ADD_VAR(LOG_PHEROMONE, bool, 0, "Log pheromone drops.  0/1 (off/on)");
+  CONFIG_ADD_VAR(PHEROMONE_LOG_START, int, 0, "Update at which to start logging pheromone drops");
+  CONFIG_ADD_VAR(EXPLOIT_LOG_START, int, 0, "Update at which to start logging exploit moves");
+  CONFIG_ADD_VAR(EXPLORE_LOG_START, int, 0, "Update at which to start logging explore moves");
+  CONFIG_ADD_VAR(MOVETARGET_LOG_START, int, 0, "Update at which to start logging movetarget moves");
+  CONFIG_ADD_VAR(LOG_INJECT, bool, 0, "Log injection of organisms.  0/1 (off/on)");
+  CONFIG_ADD_VAR(INJECT_LOG_START, int, 0, "Update at which to start logging injection of\norganisms");
   
   CONFIG_ADD_CUSTOM_FORMAT(INST_SET_NEW, "Instruction Set Definition");
   CONFIG_ADD_FORMAT_VAR(INST, "Instruction entry in the instruction set");

Modified: development/source/main/cDeme.cc
===================================================================
--- development/source/main/cDeme.cc	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cDeme.cc	2008-06-13 14:34:23 UTC (rev 2644)
@@ -31,6 +31,8 @@
 #include "cPopulationCell.h"
 #include "cResource.h"
 #include "cWorld.h"
+#include "cOrgMessagePredicate.h"
+#include "cOrgMovementPredicate.h"
 
 void cDeme::Setup(int id, const tArray<int> & in_cells, int in_width, cWorld* world)
 {
@@ -94,8 +96,9 @@
 {
   assert(cell_ids.GetSize()>0);
   assert(GetWidth() > 0);
-  cellid -= cell_ids[0];
-  return std::make_pair(cellid % GetWidth(), cellid / GetWidth());
+//  cellid -= cell_ids[0];
+//  return std::make_pair(cellid % GetWidth(), cellid / GetWidth());
+  return std::make_pair(cellid % GetWidth(), ( cellid % cell_ids.GetSize() ) / GetWidth());
 }
 
 cPopulationCell& cDeme::GetCell(int pos)
@@ -104,14 +107,23 @@
 }
 
 void cDeme::ProcessUpdate() {
-  for(int i = 0; i < cell_events.GetSize(); i++) {
+  for(int i = 0; i < cell_events.Size(); i++) {
     cDemeCellEvent& event = cell_events[i];
     if(event.GetDelay() == _age) {
       event.ActivateEvent(m_world); //start event
       int eventCell = event.GetNextEventCellID();
       while(eventCell != -1) {
         // place event ID in cells' data
-        m_world->GetPopulation().GetCell(GetCellID(eventCell)).SetCellData(event.GetEventID());
+        if(event.IsDecayed()) {
+          m_world->GetPopulation().GetCell(GetCellID(eventCell)).SetCellData(event.GetEventIDDecay(GetCellPosition(eventCell)));
+        } else {
+          m_world->GetPopulation().GetCell(GetCellID(eventCell)).SetCellData(event.GetEventID());
+        }
+        
+        // record activation of each cell in stats
+        std::pair<int, int> pos = GetCellPosition(eventCell);
+        m_world->GetStats().IncEventCount(pos.first, pos.second);
+
         eventCell = event.GetNextEventCellID();
       }
     } else if(event.GetDelay()+event.GetDuration() == _age) {
@@ -158,11 +170,22 @@
   time_used = 0;
   cur_birth_count = 0;
   cur_normalized_time_used = 0;
+  injected_count = 0;
   
   cur_task_exe_count.SetAll(0);
   cur_reaction_count.SetAll(0);
 
   if(resetResources) deme_resource_count.ReinitializeResources();
+
+  //reset remaining message predicates
+  for(int i = 0; i < message_pred_list.Size(); i++) {
+    (*message_pred_list[i]).Reset();
+  }
+  //reset remaining message predicates
+  for(int i = 0; i < movement_pred_list.Size(); i++) {
+    (*movement_pred_list[i]).Reset();
+  }
+
 }
 
 
@@ -354,11 +377,23 @@
   deme_resource_count.ModifyCell(cell_resources, relative_cell_id);
 }
 
-void cDeme::SetCellEvent(int x1, int y1, int x2, int y2, int delay, int duration) {
-  cDemeCellEvent demeEvent = cDemeCellEvent(x1, y1, x2, y2, delay, duration, width);
-  cell_events.Push(demeEvent);
+void cDeme::SetCellEvent(int x1, int y1, int x2, int y2, int delay, int duration, bool static_pos, int time_to_live, int ID) {
+  cDemeCellEvent demeEvent = cDemeCellEvent(x1, y1, x2, y2, delay, duration, width, GetHeight(), static_pos, time_to_live, this);
+  if(ID != -1)
+    demeEvent.SetEventID(ID);
+  cell_events.Add(demeEvent);
 }
 
+void cDeme::SetCellEventGradient(int x1, int y1, int x2, int y2, int delay, int duration, bool static_pos, int time_to_live) {
+  cDemeCellEvent demeEvent = cDemeCellEvent(x1, y1, x2, y2, delay, duration, width, GetHeight(), static_pos, time_to_live, this);
+  demeEvent.DecayEventIDFromCenter();
+  cell_events.Add(demeEvent);
+}
+
+int cDeme::GetNumEvents() {
+  return cell_events.Size();
+}
+
 double cDeme::CalculateTotalEnergy() {
   assert(m_world->GetConfig().ENERGY_ENABLED.Get());
     
@@ -423,3 +458,151 @@
 
 }
 
+bool cDeme::MsgPredSatisfiedPreviously() {
+  for(int i = 0; i < message_pred_list.Size(); i++) {
+    if(message_pred_list[i]->PreviouslySatisfied()) {
+      message_pred_list[i]->UpdateStats(m_world->GetStats());
+      return true;
+    }
+  }
+  return false;
+}
+
+bool cDeme::MovPredSatisfiedPreviously() {
+  for(int i = 0; i < movement_pred_list.Size(); i++) {
+    if(movement_pred_list[i]->PreviouslySatisfied()) {
+      movement_pred_list[i]->UpdateStats(m_world->GetStats());
+      return true;
+    }
+  }
+  return false;
+}
+
+int cDeme::GetNumMessagePredicates() {
+  return message_pred_list.Size();
+}
+
+int cDeme::GetNumMovementPredicates() {
+  return movement_pred_list.Size();
+}
+
+cOrgMessagePredicate* cDeme::GetMsgPredicate(int i) {
+  assert(i < message_pred_list.Size());
+  return message_pred_list[i];
+}
+
+cOrgMovementPredicate* cDeme::GetMovPredicate(int i) {
+  assert(i < movement_pred_list.Size());
+  return movement_pred_list[i];
+}
+
+void cDeme::AddEventReceivedCenterPred(int times) {
+  if(cell_events.Size() == 0) {
+    cerr<<"Error: An EventReceivedCenterPred cannot be created until a CellEvent is added.\n";
+    exit(1);
+  }
+  for(int i = 0; i < cell_events.Size(); i++) {
+    if(!cell_events[i].IsDead()) {
+      int sink_cell = GetCellID(GetSize()/2);
+      cOrgMessagePred_EventReceivedCenter* pred = new cOrgMessagePred_EventReceivedCenter(&cell_events[i], sink_cell, times);
+      m_world->GetStats().AddMessagePredicate(pred);
+      message_pred_list.Add(pred);
+    }
+  }
+}
+
+void cDeme::AddEventReceivedLeftSidePred(int times) {
+  if(cell_events.Size() == 0) {
+    cerr<<"Error: An EventReceivedLeftSidePred cannot be created until a CellEvent is added.\n";
+    exit(1);
+  }
+  for(int i = 0; i < cell_events.Size(); i++) {
+    if(!cell_events[i].IsDead()) {
+      cOrgMessagePred_EventReceivedLeftSide* pred = new cOrgMessagePred_EventReceivedLeftSide(&cell_events[i], m_world->GetPopulation(), times);
+      m_world->GetStats().AddMessagePredicate(pred);
+      message_pred_list.Add(pred);
+    }
+  }
+}
+
+void cDeme::AddEventMoveCenterPred(int times) {
+  if(cell_events.Size() == 0) {
+    cerr<<"Error: An EventMovedIntoCenter cannot be created until a CellEvent is added.\n";
+    exit(1);
+  }
+  for(int i = 0; i < cell_events.Size(); i++) {
+    if(!cell_events[i].IsDead()) {
+      cOrgMovementPred_EventMovedIntoCenter* pred = new cOrgMovementPred_EventMovedIntoCenter(&cell_events[i], m_world->GetPopulation(), times);
+      m_world->GetStats().AddMovementPredicate(pred);
+      movement_pred_list.Add(pred);
+    }
+  }
+}
+
+
+void cDeme::AddEventMoveBetweenTargetsPred(int times) {
+  if(cell_events.Size() == 0) {
+    cerr<<"Error: An EventMoveBetweenTargets cannot be created until at least one CellEvent is added.\n";
+    exit(1);
+  }
+
+  tVector<cDemeCellEvent *> alive_events;
+
+  for(int i = 0; i < cell_events.Size(); i++) {
+    if(!cell_events[i].IsDead()) {
+      alive_events.Add(&cell_events[i]);
+    }
+  }
+
+  cOrgMovementPred_EventMovedBetweenTargets* pred = new cOrgMovementPred_EventMovedBetweenTargets(alive_events, m_world->GetPopulation(), times);
+  m_world->GetStats().AddMovementPredicate(pred);
+  movement_pred_list.Add(pred);
+}
+
+
+void cDeme::AddEventEventNUniqueIndividualsMovedIntoTargetPred(int times) {
+  if(cell_events.Size() == 0) {
+    cerr<<"Error: An EventMovedIntoCenter cannot be created until a CellEvent is added.\n";
+    exit(1);
+  }
+  for(int i = 0; i < cell_events.Size(); i++) {
+    if(!cell_events[i].IsDead()) {
+      cOrgMovementPred_EventNUniqueIndividualsMovedIntoTarget* pred = new cOrgMovementPred_EventNUniqueIndividualsMovedIntoTarget(&cell_events[i], m_world->GetPopulation(), times);
+      m_world->GetStats().AddMovementPredicate(pred);
+      movement_pred_list.Add(pred);
+    }
+  }
+}
+
+void cDeme::AddPheromone(int absolute_cell_id, double value)
+{
+  assert(cell_ids[0] <= absolute_cell_id);
+  assert(absolute_cell_id <= cell_ids[cell_ids.GetSize()-1]);
+
+  cPopulation& pop = m_world->GetPopulation();
+
+  int relative_cell_id = GetRelativeCellID(absolute_cell_id);
+  tArray<double> cell_resources = deme_resource_count.GetCellResources(relative_cell_id);
+
+  for (int i = 0; i < deme_resource_count.GetSize(); i++) {
+    if(strcmp(deme_resource_count.GetResName(i), "pheromone") == 0) {
+      // There should only be one "pheromone" resource, so no need to divvy value up
+      cell_resources[i] = value;
+    }
+    else {
+      cell_resources[i] = 0;
+    }
+  }
+
+//It appears that ModifyCell adds the amount of resources specified in the cell_resources array, so I'm just
+//settign the element to the value I want to add instead of setting the element to the current value plus the amount to add
+// Ask Ben why he does it differently in GiveBackCellEnergy()
+
+  deme_resource_count.ModifyCell(cell_resources, relative_cell_id);
+
+  // CellData-based version
+  //const int newval = pop.GetCell(absolute_cell_id).GetCellData() + (int) round(value);
+  //pop.GetCell(absolute_cell_id).SetCellData(newval);
+
+} //End AddPheromone()
+

Modified: development/source/main/cDeme.h
===================================================================
--- development/source/main/cDeme.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cDeme.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -29,6 +29,7 @@
 #include "cPhenotype.h"
 #include "cMerit.h"
 #include "tArray.h"
+#include "tVector.h"
 #include "cResourceCount.h"
 #include "cStringList.h"
 
@@ -37,6 +38,8 @@
 class cPopulationCell;
 class cGenotype;
 class cOrganism;
+class cOrgMovementPredicate;
+class cOrgMessagePredicate;
 
 /*! Demes are groups of cells in the population that are somehow bound together
 as a unit.  The deme object is used from within cPopulation to manage these 
@@ -55,6 +58,7 @@
   int last_birth_count;
   int cur_org_count; //!< Number of organisms are currently in this deme.
   int last_org_count; 
+  int injected_count; //<! Number of organisms that have been injected into this deme
 
   int _age; //!< Age of this deme, in updates.
   int generation; //!< Generation of this deme
@@ -88,7 +92,7 @@
   cResourceCount deme_resource_count; //!< Resources available to the deme
   tArray<int> energy_res_ids; //!< IDs of energy resources
   
-  tArray<cDemeCellEvent> cell_events;
+  tVector<cDemeCellEvent> cell_events;
   
   int         m_germline_genotype_id; // Genotype id of germline (if in use)
   tArray<int> m_founder_genotype_ids; // List of genotype ids used to found deme.
@@ -97,10 +101,13 @@
                                       
   cMerit _current_merit; //!< Deme merit applied to all organisms living in this deme.
   cMerit _next_merit; //!< Deme merit that will be inherited upon deme replication.
+
+  tVector<cOrgMessagePredicate*> message_pred_list; // Message Predicates
+  tVector<cOrgMovementPredicate*> movement_pred_list;  // Movement Predicates
   
 public:
   cDeme() : _id(0), width(0), cur_birth_count(0), last_birth_count(0), cur_org_count(0), last_org_count(0), 
-            _age(0), generation(0), total_org_energy(0.0),
+            injected_count(0), _age(0), generation(0), total_org_energy(0.0),
             time_used(0), gestation_time(0), cur_normalized_time_used(0.0), last_normalized_time_used(0.0), 
             avg_founder_generation(0.0), generations_per_lifetime(0.0),
             deme_resource_count(0), m_germline_genotype_id(0) { ; }
@@ -112,6 +119,7 @@
   int GetSize() const { return cell_ids.GetSize(); }
   int GetCellID(int pos) const { return cell_ids[pos]; }
   int GetCellID(int x, int y) const;
+  int GetDemeID() const { return _id; }
   //! Returns an (x,y) pair for the position of the passed-in cell ID.
   std::pair<int, int> GetCellPosition(int cellid) const;
   cPopulationCell& GetCell(int pos);
@@ -138,6 +146,9 @@
   
   int GetGeneration() const { return generation; }
 
+  int GetInjectedCount() const { return injected_count; }
+  void IncInjectedCount() { injected_count++; }
+
   bool IsEmpty() const { return cur_org_count == 0; }
   bool IsFull() const { return cur_org_count == cell_ids.GetSize(); }
   
@@ -194,7 +205,9 @@
   void Update(double time_step) { deme_resource_count.Update(time_step); }
   int GetRelativeCellID(int absolute_cell_id) { return absolute_cell_id % GetSize(); } //!< assumes all demes are the same size
 
-  void SetCellEvent(int x1, int y1, int x2, int y2, int delay, int duration);
+  void SetCellEvent(int x1, int y1, int x2, int y2, int delay, int duration, bool static_pos, int time_to_live, int ID = -1);
+  void SetCellEventGradient(int x1, int y1, int x2, int y2, int delay, int duration, bool static_pos, int time_to_live);
+  int GetNumEvents();
   
   double CalculateTotalEnergy();
   
@@ -217,6 +230,26 @@
   // --- Germline management --- //
   void ReplaceGermline(cGenotype& _in_genotype);
   int GetGermlineGenotypeID() { return m_germline_genotype_id; }
+
+  // --- Message/Movement predicates --- //
+  bool MsgPredSatisfiedPreviously();
+  bool MovPredSatisfiedPreviously();
+  int GetNumMessagePredicates();
+  int GetNumMovementPredicates();
+  cOrgMessagePredicate* GetMsgPredicate(int i);
+  cOrgMovementPredicate* GetMovPredicate(int i);
+
+  void AddEventReceivedCenterPred(int times);
+  void AddEventReceivedLeftSidePred(int times);
+  void AddEventMoveCenterPred(int times);
+  void AddEventMoveBetweenTargetsPred(int times);
+  void AddEventMigrateToTargetsPred(int times);
+  void AddEventEventNUniqueIndividualsMovedIntoTargetPred(int times);
+
+  // --- Pheromones --- //
+  void AddPheromone(int absolute_cell_id, double value);
+
+
 };
 
 #endif

Modified: development/source/main/cDemeCellEvent.cc
===================================================================
--- development/source/main/cDemeCellEvent.cc	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cDemeCellEvent.cc	2008-06-13 14:34:23 UTC (rev 2644)
@@ -1,30 +1,48 @@
 #include "cDemeCellEvent.h"
+#include "cDeme.h"
 #include "cWorld.h"
 
-cDemeCellEvent::cDemeCellEvent(int x1, int y1, int x2, int y2, int delay, int duration, int width) : 
-  m_delay(delay)
-  , m_duration(duration)
-  , m_iter(0)
-  , m_active(false)
+cDemeCellEvent::cDemeCellEvent(int x1, int y1, int x2, int y2, int delay, int duration, int deme_width, int deme_height, bool static_pos, int time_to_live, cDeme* deme) : 
+m_delay(delay)
+, m_duration(duration)
+, m_iter(0)
+, m_deme_width(deme_width)
+, m_deme_height(deme_height)
+, m_time_to_live(time_to_live)
+, m_use_gradient(false)
+, m_active(false)
+, m_static_pos(static_pos)
+, m_dead (false)
+, m_id_set(false)
+, m_deme(deme)
 {
   assert(x1 <= x2);
   assert(y1 <= y2);
-  assert(y1 < width && y2 < width);
+  assert(y1 < deme_width && y2 < deme_width);
   assert(delay >= 0);
   assert(duration >= 0);
   m_event_cells.ResizeClear((x2-x1+1) * (y2-y1+1));
+  int i = 0;
   
-  int i = 0;
-  for(int j = y1; j <= y2; j++) {
-    for(int k = x1; k <= x2; k++) {
-      m_event_cells[i] = j*width+k;
-      i++;
+  if(m_static_pos) {
+    for(int j = y1; j <= y2; j++) {
+      for(int k = x1; k <= x2; k++) {
+        m_event_cells[i] = j*m_deme_width+k;
+        i++;
+      }
     }
+    pair<int, int> centerBottomleft = make_pair((int)floor(((x2-x1)/2.0)), (int)floor(((y2-y1)/2.0)));
+    pair<int, int> centerTopRight = make_pair((int)ceil(((x2-x1)/2.0)), (int)ceil(((y2-y1)/2.0)));
+    center = make_pair(centerBottomleft, centerTopRight);
+  } else {
+    //non-static event position
+    m_event_width = x2-x1;
+    m_event_height = y2-y1;
   }
 }
 
 int cDemeCellEvent::GetNextEventCellID() {
-  if(m_active && m_iter < m_event_cells.GetSize()) {
+  if(!m_dead && m_active && m_iter < m_event_cells.GetSize()) {
     return m_event_cells[m_iter++];
   }
   m_iter = 0;
@@ -32,10 +50,110 @@
 }
 
 void cDemeCellEvent::ActivateEvent(cWorld* m_world) {
-  m_eventID = m_world->GetRandom().GetInt(0x7FFFFFFF);
+
+  if(m_dead) {
+    return;
+  }
+  
+  if(!m_id_set)
+    m_eventID = m_world->GetRandom().GetInt(0x7FFFFFFF);
+  if(!m_static_pos) {
+    //non-static event position
+    int rand_x1 = m_world->GetRandom().GetInt(m_deme_width-m_event_width);
+    int rand_y1 = m_world->GetRandom().GetInt(m_deme_height-m_event_height);
+    int i = 0;
+    for(int j = rand_y1; j <= rand_y1+m_event_height; j++) {
+      for(int k = rand_x1; k <= rand_x1+m_event_width; k++) {
+        m_event_cells[i] = j*m_deme_width+k;
+        i++;
+      }
+    }
+    pair<int, int> centerBottomleft = make_pair((int)floor((m_event_width/2.0)), (int)floor((m_event_height/2.0)));
+    pair<int, int> centerTopRight = make_pair((int)ceil((m_event_width/2.0)), (int)ceil((m_event_height/2.0)));
+    center = make_pair(centerBottomleft, centerTopRight);
+  }
   m_active = true;
 }
 
+int cDemeCellEvent::GetDelay() {
+  if(m_dead){
+    return 0;
+  }
+  return m_delay;
+}
+
+int cDemeCellEvent::GetDuration() {
+  if(m_dead){
+    return 0;
+  }
+  return m_duration;
+}
+
+int cDemeCellEvent::GetEventID() {
+  if(m_dead){
+    return -1;
+  }
+  return m_eventID;
+}
+
+int cDemeCellEvent::GetEventIDDecay(pair<int, int> pos) {
+  if(m_dead){
+    return -1;
+  }
+
+  double maxd = sqrt(pow(m_deme_width-1.0 ,2) + pow(m_deme_height-1.0 ,2));//cdistance(1,1,wx,wy);
+  double top = ceil(maxd);
+  pair<double, double> centerPoint = GetCenter(); // # dx.dy -- coordinates of peak value  
+  double cdistance = sqrt(pow(pos.first-centerPoint.first ,2) + pow(pos.second-centerPoint.second ,2));
+
+  // return decayed value
+  int decayed_value = (int)floor(linmap(cdistance,0.0,top,top*1.414,1.0));
+  return decayed_value;
+}
+
+std::pair<double, double> cDemeCellEvent::GetCenter() const { 
+  return make_pair((center.first.first+center.second.first)/2.0, (center.first.second+center.second.second)/2.0);
+}
+
+bool cDemeCellEvent::InCenter(pair<int, int> pos) const {
+  if((center.first <= pos) && (pos <= center.second)) {
+    return true;
+  }
+  return false;
+}
+
+bool cDemeCellEvent::OnEventCell(int demeRelative_cell_ID) const {
+  for(int i = 0; i < m_event_cells.GetSize(); i++) {
+    if(m_event_cells[i] == demeRelative_cell_ID)
+      return true;
+  }
+  return false;
+}
+
+int cDemeCellEvent::GetTimeToLive() {
+  if(m_dead){
+    return 0;
+  }
+  return m_time_to_live;
+}
+
+bool cDemeCellEvent::IsActive() {
+  if(m_dead){
+    return false;
+  }
+  return m_active;
+}
+
 void cDemeCellEvent::DeactivateEvent() {
   m_active = false;
 }
+
+double cDemeCellEvent::linmap(const double dp, const double ds, const double de, const double rs, const double re) const {
+  double rp;
+  if (0.0 == (de - ds)) { // Domain has zero length; exception should be taken
+    rp = 0.0;
+  } else {
+    rp = (dp - ds) * ((re - rs) / (de - ds)) + rs;
+  }
+  return rp;
+}

Modified: development/source/main/cDemeCellEvent.h
===================================================================
--- development/source/main/cDemeCellEvent.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cDemeCellEvent.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -1,24 +1,48 @@
 #ifndef cDemeCellEvent_h
 #define cDemeCellEvent_h
 
+#include <utility>
 #include "tArray.h"
+
+class cDeme;
 class cWorld;
 
 class cDemeCellEvent {
 private:
   tArray<int> m_event_cells;
-  int m_delay, m_duration, m_eventID, m_iter;
-  bool m_active;
+  int m_eventID;
+  int m_delay, m_duration, m_iter, m_deme_width, m_deme_height;
+  int m_event_width, m_event_height, m_time_to_live;
+  bool m_use_gradient, m_active, m_static_pos, m_dead, m_id_set;
+  std::pair<std::pair<int, int>, std::pair<int, int> > center;
+  cDeme* m_deme;
   
+  std::pair<double, double> GetCenter() const;
+  
 public:
-  cDemeCellEvent() { cDemeCellEvent(-1, -1, -1, -1, 0, 0, 0); }
-  cDemeCellEvent(int x1, int y1, int x2, int y2, int delay, int duration, int width);
+  cDemeCellEvent() { cDemeCellEvent(-1, -1, -1, -1, 0, 0, 0, 0, true, 0, NULL); m_id_set = false;}
+  cDemeCellEvent(int x1, int y1, int x2, int y2, int delay, int duration, int deme_width, int deme_height, bool static_pos, int time_to_live, cDeme* deme);
   int GetNextEventCellID();
-  int GetDelay() { return m_delay; }
-  int GetDuration() { return m_duration; }
-  int GetEventID() { return m_eventID; }
+  int GetDelay();
+  cDeme* GetDeme() const { return m_deme; }
+  int GetDuration();
+  int GetEventID();
+  int GetEventIDDecay(std::pair<int, int> pos);
+  int GetTimeToLive();
+  bool IsActive();
+  bool IsDead() const { return m_dead; }
+  bool IsDecayed() { return m_use_gradient; }
+  bool InCenter(std::pair<int, int> pos) const;
+  bool OnEventCell(int demeRelative_cell_ID) const;
+  
+  void SetEventID(int ID) { m_eventID = ID; m_id_set = true;}
 
+  void DecayEventIDFromCenter() { m_use_gradient = true; }
   void ActivateEvent(cWorld* m_world);
   void DeactivateEvent();
+  void Terminate() { m_dead = true; }
+  
+  // gradient generators
+  double linmap(const double dp, const double ds, const double de, const double rs, const double re) const;
 };
 #endif

Modified: development/source/main/cOrgInterface.h
===================================================================
--- development/source/main/cOrgInterface.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cOrgInterface.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -60,6 +60,13 @@
   virtual void SetCellID(int in_id) = 0;
   virtual void SetDemeID(int in_id) = 0;
 
+  virtual int GetPrevSeenCellID() = 0;
+  virtual int GetPrevTaskCellID() = 0;
+  virtual int GetNumTaskCellsReached() = 0;
+  virtual void AddReachedTaskCell() = 0;
+  virtual void SetPrevSeenCellID(int in_id) = 0;
+  virtual void SetPrevTaskCellID(int in_id) = 0;
+
   virtual bool Divide(cAvidaContext& ctx, cOrganism* parent, cGenome& child_genome) = 0;
   virtual cOrganism* GetNeighbor() = 0;
   virtual int GetNumNeighbors() = 0;

Modified: development/source/main/cOrgMessagePredicate.h
===================================================================
--- development/source/main/cOrgMessagePredicate.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cOrgMessagePredicate.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -42,6 +42,10 @@
   virtual bool operator()(const cOrgMessage& msg) = 0;
   virtual void Print(std::ostream& out) { }
   virtual void Reset() { }
+  virtual bool PreviouslySatisfied() = 0;
+  virtual cString GetName() = 0;
+  virtual void UpdateStats(cStats& stats) {}
+  virtual cDemeCellEvent* GetEvent() { return NULL; }
 };
 
 
@@ -127,4 +131,186 @@
 };
 
 
+/*! A predicate that returns true if a demeCellEvent has been received but the base station
+*/
+struct cOrgMessagePred_EventReceivedCenter : public cOrgMessagePredicate {
+  cOrgMessagePred_EventReceivedCenter(cDemeCellEvent* event, int base_station, int times) : 
+  m_base_station(base_station)
+  , m_event_received(false)
+  , m_stats_updated(false)
+  , m_event(event)
+  , m_total_times(times)
+  , m_current_times(0) { }
+  
+  ~cOrgMessagePred_EventReceivedCenter() { }
+  
+  virtual bool operator()(const cOrgMessage& msg) {
+    int deme_id = msg.GetSender()->GetOrgInterface().GetDemeID();
+    
+    if(deme_id != m_event->GetDeme()->GetDemeID() || m_event->IsDead()) {
+      return false;
+    }
+    
+    unsigned int eventID = m_event->GetEventID();
+    
+    if(m_event->IsActive() && eventID != 0 &&
+       (eventID == msg.GetData() ||
+        eventID == msg.GetLabel())) {
+      m_cell_ids.insert(msg.GetSender()->GetCellID());
+
+      if(m_base_station == msg.GetReceiver()->GetCellID()) {
+        m_current_times++;
+        if(m_current_times >= m_total_times) {
+          m_event_received = true;
+        }
+      }
+    }
+    return m_event_received;
+  }
+  
+  //need to print update!!!
+  virtual void Print(std::ostream& out) {
+    if(m_event->IsDead()) {
+      return;
+    }
+
+    out << m_event->GetEventID() << " [ ";
+    for(std::set<int>::iterator i=m_cell_ids.begin(); i!=m_cell_ids.end(); i++) {
+      out << *i << " ";
+    }
+    out << "]\n";
+    
+    m_cell_ids.clear();
+  }
+  
+  virtual void Reset() { 
+    m_event_received = false;
+    m_stats_updated = false;
+    m_current_times = 0;
+  }
+
+  virtual bool PreviouslySatisfied() {
+    return m_event_received;
+  }
+
+  virtual cString GetName() {
+    return "EventReceivedCenter";
+  }
+
+  virtual void UpdateStats(cStats& stats) {
+    if(m_event_received && !m_stats_updated) {
+      int eventCell = m_event->GetNextEventCellID();
+      while(eventCell != -1) {
+        stats.IncPredSat(eventCell);
+        eventCell = m_event->GetNextEventCellID();
+      }
+      m_stats_updated = true;
+    }
+  }
+  
+  cDemeCellEvent* GetEvent() { return m_event; }
+  
+  int m_base_station;
+  bool m_event_received;
+  bool m_stats_updated;
+  cDemeCellEvent* m_event;
+  std::set<int> m_cell_ids;
+  int m_total_times;
+  int m_current_times;
+};
+
+/*! A predicate that returns true if a demeCellEvent has been received but the base station
+*/
+struct cOrgMessagePred_EventReceivedLeftSide : public cOrgMessagePredicate {
+  cOrgMessagePred_EventReceivedLeftSide(cDemeCellEvent* event, cPopulation& population, int times) :
+  pop(population)
+  , m_event_received(false)
+  , m_stats_updated(false)
+  , m_event(event)
+  , m_total_times(times)
+  , m_current_times(0){ }
+  
+  ~cOrgMessagePred_EventReceivedLeftSide() { }
+  
+  virtual bool operator()(const cOrgMessage& msg) {
+    int deme_id = msg.GetSender()->GetOrgInterface().GetDemeID();
+    
+    if(deme_id != m_event->GetDeme()->GetDemeID() || m_event->IsDead()) {
+      return false;
+    }
+
+    if(m_event->IsActive() && 
+       ((unsigned int)m_event->GetEventID() == msg.GetData() ||
+        (unsigned int)m_event->GetEventID() == msg.GetLabel())) {
+      m_cell_ids.insert(msg.GetSender()->GetCellID());
+      
+      // find receiver coordinates
+      cOrganism* receiver = msg.GetReceiver();
+      int absolute_cell_ID = receiver->GetCellID();
+      int deme_id = receiver->GetOrgInterface().GetDemeID();
+      std::pair<int, int> pos = pop.GetDeme(deme_id).GetCellPosition(absolute_cell_ID);  
+
+      // does receiver have x cordinate of zero
+      if(pos.first == 0) {
+        m_current_times++;
+        if(m_current_times >= m_total_times) {
+          m_event_received = true;
+        }
+      }
+    }
+    return m_event_received;
+  }
+  
+  virtual void Print(std::ostream& out) {
+    if(m_event->IsDead()) {
+      return;
+    }
+
+    out << m_event->GetEventID() << " [ ";
+    for(std::set<int>::iterator i=m_cell_ids.begin(); i!=m_cell_ids.end(); i++) {
+      out << *i << " ";
+    }
+    out << "]\n";
+    
+    m_cell_ids.clear();
+  }
+  
+  virtual void Reset() { 
+    m_event_received = false;
+    m_stats_updated = false;
+    m_current_times = 0;
+    m_cell_ids.clear();
+  }
+
+  virtual bool PreviouslySatisfied() {
+    return m_event_received;
+  }
+
+  virtual cString GetName() {
+    return "EventReceivedLeftSide";
+  }
+
+  virtual void UpdateStats(cStats& stats) {
+    if(m_event_received && !m_stats_updated) {
+      int eventCell = m_event->GetNextEventCellID();
+      while(eventCell != -1) {
+        stats.IncPredSat(eventCell);
+        eventCell = m_event->GetNextEventCellID();
+      }
+      m_stats_updated = true;
+    }
+  }
+  
+  cDemeCellEvent* GetEvent() { return m_event; }
+  
+  cPopulation& pop;
+  bool m_event_received;
+  bool m_stats_updated;
+  cDemeCellEvent* m_event;
+  std::set<int> m_cell_ids;
+  int m_total_times;
+  int m_current_times;
+};
+
+
 #endif

Added: development/source/main/cOrgMovementPredicate.h
===================================================================
--- development/source/main/cOrgMovementPredicate.h	                        (rev 0)
+++ development/source/main/cOrgMovementPredicate.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -0,0 +1,375 @@
+/*
+ *  cOrgMovementPredicate.h
+ *  Avida
+ *
+ *  Created by Benjamin Beckmann on 11/6/07.
+ *  Copyright 2007 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+/*
+ *  cOrgMessagePredicate.h
+ *  Avida
+ *
+ *  Copyright 2005-2006 Michigan State University. All rights reserved.
+ *  Copyright 1993-2003 California Institute of Technology.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; version 2
+ *  of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+#ifndef cOrgMovementPredicate_h
+#define cOrgMovementPredicate_h
+
+#include <iostream>
+#include <functional>
+#include <set>
+
+#include "cDemeCellEvent.h"
+#include "cOrganism.h"
+#include "cPopulation.h"
+#include "cStats.h"
+
+
+/*! \brief An STL-compatible predicate on cOrgMessages.  The intent here is to
+provide a straightforward way to track arbitrary messages *wherever* they appear
+in the population.  The most utility can be had from message predicates if they're
+installed into cStats (since every message goes through cStats). */
+struct cOrgMovementPredicate : public std::unary_function<cOrganism, bool> 
+{
+  virtual ~cOrgMovementPredicate() { }
+  virtual bool operator()(cOrganism& org) = 0;
+  virtual void Print(std::ostream& out) { }
+  virtual void Reset() { }
+  virtual bool PreviouslySatisfied() = 0;
+  virtual cString GetName() = 0;
+  virtual void UpdateStats(cStats& stats) {}
+  virtual cDemeCellEvent* GetEvent(int i) { return NULL; }
+  virtual int GetNumEvents() { return 1; }
+};
+
+/*! A predicate that returns true if an organism has made it to the center of the gradient event
+*/
+struct cOrgMovementPred_EventMovedIntoCenter : public cOrgMovementPredicate {
+  cOrgMovementPred_EventMovedIntoCenter(cDemeCellEvent* event, cPopulation& population, int times) :
+  pop(population)
+  , m_event_received(false)
+  , m_stats_updated(false)
+  , m_event(event)
+  , m_total_times(times)
+  , m_current_times(0){ }
+  
+  ~cOrgMovementPred_EventMovedIntoCenter() { }
+
+  virtual bool operator()(cOrganism& org) {
+    int deme_id = org.GetOrgInterface().GetDemeID();
+    
+    if(deme_id != m_event->GetDeme()->GetDemeID() || m_event->IsDead()) {
+      return false;
+    }
+
+    if(m_event->IsActive()) {
+      // find organism coordinates
+      int absolute_cell_ID = org.GetCellID();
+      std::pair<int, int> pos = pop.GetDeme(deme_id).GetCellPosition(absolute_cell_ID); 
+
+      // does receiver have x cordinate of zero
+      if(m_event->InCenter(pos)) {
+        m_current_times++;
+        if(m_current_times >= m_total_times) {
+          m_event_received = true;
+        }
+      }
+    }
+    return m_event_received;
+  }
+  
+  virtual void Print(std::ostream& out) {
+    if(m_event->IsDead()) {
+      return;
+    }
+    // WHAT TO PRINT
+  }
+  
+  virtual void Reset() { 
+    m_event_received = false;
+    m_stats_updated = false;
+    m_current_times = 0;
+  }
+
+  virtual bool PreviouslySatisfied() {
+    return m_event_received;
+  }
+
+  virtual cString GetName() {
+    return "EventMovedIntoCenter";
+  }
+
+  virtual void UpdateStats(cStats& stats) {
+    if(m_event_received && !m_stats_updated) {
+/*      int eventCell = m_event->GetNextEventCellID();
+      while(eventCell != -1) {
+        stats.IncPredSat(eventCell);
+        eventCell = m_event->GetNextEventCellID();
+      }*/
+      m_stats_updated = true;
+    }
+  }
+  
+  cDemeCellEvent* GetEvent(int i) { return m_event; }
+  
+  cPopulation& pop;
+  bool m_event_received;
+  bool m_stats_updated;
+  cDemeCellEvent* m_event;
+  int m_total_times;
+  int m_current_times;
+};
+
+
+
+/*! A predicate that returns true if an organism has made it to a target cell.
+ *  Modified from cOrgMovementPred_EventMovedIntoCenter
+*/
+struct cOrgMovementPred_EventMovedBetweenTargets : public cOrgMovementPredicate {
+  cOrgMovementPred_EventMovedBetweenTargets(tVector<cDemeCellEvent *> events, cPopulation& population, unsigned int times) :
+  pop(population)
+  , m_event_received(false)
+  , m_stats_updated(false)
+  , m_events(events)
+  , m_total_orgs(1)   // TODO: eventually, want to make this a parameter.  problem is cPopulation::AddDemePred takes only 1 arg
+  , m_total_times(times) {
+
+    m_event_success.clear();
+    for(int i = 0; i < m_events.Size(); i++) {
+      set<int> p;
+      p.clear();
+      m_event_success.push_back(p);
+    }
+    m_successful_orgs.clear();
+  } //End constructor
+
+  ~cOrgMovementPred_EventMovedBetweenTargets() { }
+
+  virtual bool operator()(cOrganism& org) {
+    int deme_id = org.GetOrgInterface().GetDemeID();
+    set<int>::iterator it;
+    int other_event;    // Index of the other event
+
+    m_event_received = false;
+
+    for(int i = 0; i < m_events.Size(); i++) {
+      cDemeCellEvent *event = m_events[i];
+      other_event = (i+1) % 2;
+ 
+      if( (event->IsDead() == false) && (event->IsActive()) &&
+          (deme_id == event->GetDeme()->GetDemeID()) ) {
+
+        int absolute_cell_ID = org.GetCellID();
+        int relative_cell_ID = pop.GetDeme(deme_id).GetRelativeCellID(absolute_cell_ID);  
+
+
+        if(event->OnEventCell(relative_cell_ID)) {
+
+          int org_id = -1;
+          org_id = ((cOrganism&) org).GetID();
+	  
+	  m_event_success[i].insert(org_id);
+
+          it = m_event_success[other_event].find(org_id);
+
+          if(it != m_event_success[other_event].end())
+          {
+             // See how many times this org has gone back and forth.  If it has
+             // done it enough times, it is considered successful
+             unsigned int num_backforth = (int) floor(org.GetNumTaskCellsReached()/2);
+
+             if(num_backforth >= m_total_times) {
+               m_successful_orgs.insert(org_id);
+
+               //---- do some logging ----------------------------------------------------------------------
+               ofstream predlog;
+               predlog.open("data/predlog.dat", ios::app);
+               predlog << "Organism " << org_id << " in deme " << deme_id ;
+               predlog << " has touched both targets " << num_backforth << " times. " << m_successful_orgs.size();
+               predlog << " orgs have done this out of " << m_total_orgs << endl;
+
+               set<int>::iterator it;
+               for(unsigned int q = 0; q < m_event_success.size(); q++) {
+                 predlog << "ORGS FOR EVENT " << q;
+                   for ( it=m_event_success[q].begin() ; it != m_event_success[q].end(); it++ )
+                     predlog << " " << *it;
+                 predlog << endl;
+               }
+
+               predlog.close();
+               //---- end of logging -----------------------------------------------------------------------
+
+               // If enough organisms have touched both targets, predicate is satisfied.
+               if(m_successful_orgs.size() >= m_total_orgs) {
+                 m_event_received = true;
+                 return m_event_received;
+               }
+             }
+
+
+          } //End if this organism has gone to the other target as well
+
+        } //End if org is in event area
+
+      } //End if this event matches the predicate
+
+    } //End going through events 
+
+    return m_event_received;
+
+  } //End operator()
+  
+  virtual void Print(std::ostream& out) {
+    // WHAT TO PRINT
+  }
+
+  virtual void Reset() { 
+    m_event_received = false;
+    m_stats_updated = false;
+
+    m_event_success.clear();
+    for(int i = 0; i < m_events.Size(); i++) {
+      set<int> p;
+      p.clear();
+      m_event_success.push_back(p);
+    }
+    m_successful_orgs.clear();
+  }
+
+  virtual bool PreviouslySatisfied() {
+    return m_event_received;
+  }
+
+  virtual cString GetName() {
+    return "EventMovedBetweenTargets";
+  }
+
+  virtual void UpdateStats(cStats& stats) {
+    if(m_event_received && !m_stats_updated) {
+/*      int eventCell = m_event->GetNextEventCellID();
+      while(eventCell != -1) {
+        stats.IncPredSat(eventCell);
+        eventCell = m_event->GetNextEventCellID();
+      }*/
+      m_stats_updated = true;
+    }
+  }
+  
+  cDemeCellEvent * GetEvent(int i) {
+    return m_events[i];
+  }
+
+  virtual int GetNumEvents() {
+    return m_events.Size();
+  }
+  
+  cPopulation& pop;
+  bool m_event_received;
+  bool m_stats_updated;
+  tVector<cDemeCellEvent *> m_events;
+  unsigned int m_total_times;
+  unsigned int m_total_orgs;
+
+  vector< set<int> > m_event_success;
+  set<int> m_successful_orgs;
+};
+
+
+
+
+/*! A predicate that returns true if the appropriate number of organisms touch
+ *  target cells
+*/
+
+struct cOrgMovementPred_EventNUniqueIndividualsMovedIntoTarget : public cOrgMovementPredicate {
+  cOrgMovementPred_EventNUniqueIndividualsMovedIntoTarget(cDemeCellEvent* event, cPopulation& population, unsigned int unique_individuals) :
+  pop(population)
+  , m_satisfied(false)
+  , m_stats_updated(false)
+  , m_event(event)
+  , m_total_individuals(unique_individuals) {
+    unique_org_ids.clear();
+  }
+  
+  virtual bool operator()(cOrganism& org) {
+    int deme_id = org.GetOrgInterface().GetDemeID();
+    
+    if(deme_id != m_event->GetDeme()->GetDemeID() || m_event->IsDead()) {
+      return false;
+    }
+
+    if(m_event->IsActive()) {
+      int absolute_cell_ID = org.GetCellID();
+      int relative_cell_ID = pop.GetDeme(deme_id).GetRelativeCellID(absolute_cell_ID);  
+      
+      // is the organism in an event cell
+      if(m_event->OnEventCell(relative_cell_ID)) {
+        unique_org_ids.insert(org.GetID());
+
+        // have enough unique organisms visited the event cells?
+        if(unique_org_ids.size() >= m_total_individuals) {
+          m_satisfied = true;
+        }
+      }
+    }
+    return m_satisfied;
+  }
+  
+  virtual void Print(std::ostream& out) {
+    if(m_event->IsDead()) {
+      return;
+    }
+    // WHAT TO PRINT
+  }
+  
+  virtual void Reset() {
+    m_satisfied = false;
+    m_stats_updated = false;
+    unique_org_ids.clear();
+  }
+  
+  virtual bool PreviouslySatisfied() {
+    return m_satisfied;
+  }
+  
+  virtual cString GetName() {
+    return "EventNUniqueIndividualsMovedIntoTarget";
+  }
+  
+  virtual void UpdateStats(cStats& stats) {
+    if(m_satisfied && !m_stats_updated) {
+      m_stats_updated = true;
+    }
+  }
+  
+  virtual cDemeCellEvent* GetEvent(int i) {
+    return m_event;
+  }
+  
+  cPopulation& pop;
+  bool m_satisfied;
+  bool m_stats_updated;
+  cDemeCellEvent* m_event;
+  unsigned int m_total_individuals;
+  set<int> unique_org_ids;
+};
+
+#endif

Modified: development/source/main/cOrganism.cc
===================================================================
--- development/source/main/cOrganism.cc	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cOrganism.cc	2008-06-13 14:34:23 UTC (rev 2644)
@@ -72,6 +72,7 @@
   , m_is_dead(false)
   , m_net(NULL)
   , m_msg(0)
+  , m_pher_drop(false)
 {
   // Initialization of structures...
   m_hardware = m_world->GetHardwareManager().Create(this);
@@ -664,3 +665,11 @@
   
   return 0;
 }
+
+// Brian Movement
+void cOrganism::Move(cAvidaContext& ctx)
+{
+  assert(m_interface);
+  DoOutput(ctx);
+} //End cOrganism::Move()
+

Modified: development/source/main/cOrganism.h
===================================================================
--- development/source/main/cOrganism.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cOrganism.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -118,11 +118,14 @@
   bool m_sent_active;       // Has this org sent a number?
   int m_test_receive_pos;   // In a test CPU, what message to receive next?
 
+  double m_gradient_movement;  // TEMP.  Remove once movement tasks are implemented.
+  bool m_pher_drop;	   // Is the organism dropping pheromone?
+
   int m_max_executed;      // Max number of instruction executed before death.  
   bool m_is_running;       // Does this organism have the CPU?
   bool m_is_sleeping;      // Is this organisms sleeping?
   bool m_is_dead;          // Is this organism dead?
-  
+
   class cNetSupport
   {
   public:
@@ -185,6 +188,10 @@
   
   bool IsDead() { return m_is_dead; }
   
+  bool GetPheromoneStatus() { return m_pher_drop; }
+  void TogglePheromone() { m_pher_drop = (m_pher_drop == true) ? false : true; }
+  void SetPheromone(bool newval) { m_pher_drop = newval; }
+
   // --------  cOrgInterface Methods  --------
   cHardwareBase& GetHardware() { return *m_hardware; }
   cOrganism* GetNeighbor() { return m_interface->GetNeighbor(); }
@@ -211,6 +218,13 @@
   tListNode<tListNode<cSaleItem> >* AddSoldItem(tListNode<cSaleItem>* node) { return m_sold_items.PushRear(node); }
   tList<tListNode<cSaleItem> >* GetSoldItems() { return &m_sold_items; }
   void UpdateMerit(double new_merit) { m_interface->UpdateMerit(new_merit); }
+
+  int GetPrevSeenCellID() const { return m_interface->GetPrevSeenCellID(); }
+  int GetPrevTaskCellID() const { return m_interface->GetPrevTaskCellID(); }
+  void SetPrevSeenCellID(int id) const { m_interface->SetPrevSeenCellID(id); }
+  void SetPrevTaskCellID(int id) const { m_interface->SetPrevTaskCellID(id); }
+  int GetNumTaskCellsReached() const { m_interface->GetNumTaskCellsReached(); }
+  void AddReachedTaskCell() { m_interface->AddReachedTaskCell(); }
   
 
   // --------  Input and Output Methods  --------
@@ -348,6 +362,21 @@
   //! Called to check for (and initialize) messaging support within this organism.
   inline void InitMessaging() { if(!m_msg) m_msg = new cMessagingSupport(); }
   // -------- End of messaging support --------
+
+  // -------- Movement TEMP --------
+public:
+  double GetGradientMovement() const {
+    return m_gradient_movement;
+  }
+  
+  void SetGradientMovement(const double value) {
+    m_gradient_movement = value;
+  }
+
+  // -------- BDC Movement ---------
+public:
+  void Move(cAvidaContext& ctx);
+
 };
 
 

Modified: development/source/main/cPopulation.cc
===================================================================
--- development/source/main/cPopulation.cc	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cPopulation.cc	2008-06-13 14:34:23 UTC (rev 2644)
@@ -1180,6 +1180,7 @@
 2: 'corners'   - ...demes with upper left and lower right corners filled.
 3: 'deme-age'  - ...demes who have reached their maximum age
 4: 'birth-count' ...demes that have had a certain number of births.
+5: 'sat-mov-pred'...demes whose movement predicate was previously satisfied
 
 */
 
@@ -1224,6 +1225,10 @@
         if(source_deme.GetBirthCount() < m_world->GetConfig().DEMES_MAX_BIRTHS.Get()) continue;
         break;
       }
+      case 5: {
+        if(!(source_deme.MovPredSatisfiedPreviously())) continue;
+        break;
+      }
       default: {
         cerr << "ERROR: Invalid replication trigger " << rep_trigger
         << " in cPopulation::ReplicateDemes()" << endl;
@@ -2402,6 +2407,33 @@
   InjectClone( cell2_id, *(cell_array[cell1_id].GetOrganism()) );    
 }
 
+void cPopulation::AddDemePred(cString type, int times) {
+  if(type == "EventReceivedCenter") {
+    for (int deme_id = 0; deme_id < deme_array.GetSize(); deme_id++) {
+      deme_array[deme_id].AddEventReceivedCenterPred(times);
+    }
+  } else if(type == "EventReceivedLeftSide") {
+    for (int deme_id = 0; deme_id < deme_array.GetSize(); deme_id++) {
+      deme_array[deme_id].AddEventReceivedLeftSidePred(times);
+    }
+  } else if(type == "EventMovedIntoCenter") {
+    for (int deme_id = 0; deme_id < deme_array.GetSize(); deme_id++) {
+      deme_array[deme_id].AddEventMoveCenterPred(times);
+    }  
+  } else if(type == "EventMovedBetweenTargets") {
+    for (int deme_id = 0; deme_id < deme_array.GetSize(); deme_id++) {
+      deme_array[deme_id].AddEventMoveBetweenTargetsPred(times);
+    }  
+  } else if(type == "EventNUniqueIndividualsMovedIntoTarget") {
+    for (int deme_id = 0; deme_id < deme_array.GetSize(); deme_id++) {
+      deme_array[deme_id].AddEventEventNUniqueIndividualsMovedIntoTargetPred(times);
+    }  
+  } else {
+    cout << "Unknown Predicate\n";
+    exit(1);
+  }
+}
+
 void cPopulation::CheckImplicitDemeRepro(cDeme& deme) {
 
   if (GetNumDemes() <= 1) return;
@@ -4230,6 +4262,25 @@
   
   // Activate the organism in the population...
   ActivateOrganism(ctx, new_organism, cell_array[cell_id]);
+
+  // Log the injection of this organism if LOG_INJECT is set to 1 and
+  // the current update number is >= INJECT_LOG_START
+  if ( (m_world->GetConfig().LOG_INJECT.Get() == 1) &&
+       (m_world->GetStats().GetUpdate() >= m_world->GetConfig().INJECT_LOG_START.Get()) ){
+
+      cString tmpfilename = cStringUtil::Stringf("injectlog.dat");
+      cDataFile& df = m_world->GetDataFile(tmpfilename);
+
+      int update = m_world->GetStats().GetUpdate();
+      int orgid = new_organism->GetID();
+      int deme_id = m_world->GetPopulation().GetCell(cell_id).GetDemeID();
+      int facing = new_organism->GetFacing();
+      const char *orgname = (const char *)new_genotype->GetName();
+
+      cString UpdateStr = cStringUtil::Stringf("%d %d %d %d %d %s", update, orgid, cell_id, deme_id, facing, orgname);
+      df.WriteRaw(UpdateStr);
+  }
+
 }
 
 

Modified: development/source/main/cPopulation.h
===================================================================
--- development/source/main/cPopulation.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cPopulation.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -221,6 +221,7 @@
   void ResetDemes();
   void CopyDeme(int deme1_id, int deme2_id);
   void SpawnDeme(int deme1_id, int deme2_id=-1);
+  void AddDemePred(cString type, int times);
 
   void CheckImplicitDemeRepro(cDeme& deme);
   

Modified: development/source/main/cPopulationCell.cc
===================================================================
--- development/source/main/cPopulationCell.cc	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cPopulationCell.cc	2008-06-13 14:34:23 UTC (rev 2644)
@@ -185,6 +185,11 @@
   // Adjust the organism's attributes to match this cell.
   m_organism->GetOrgInterface().SetCellID(m_cell_id);
   m_organism->GetOrgInterface().SetDemeID(m_deme_id);
+
+  // If this organism is new, set the previously-seen cell id
+  if(m_organism->GetOrgInterface().GetPrevSeenCellID() == -1) {
+    m_organism->GetOrgInterface().SetPrevSeenCellID(m_cell_id);
+  }
   
   if(m_world->GetConfig().ENERGY_ENABLED.Get() == 1 && m_world->GetConfig().FRAC_ENERGY_TRANSFER.Get() > 0.0) {
     // uptake all the cells energy

Modified: development/source/main/cPopulationInterface.h
===================================================================
--- development/source/main/cPopulationInterface.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cPopulationInterface.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -48,6 +48,10 @@
   int m_cell_id;
   int m_deme_id;
 
+  int m_prevseen_cell_id;	// Previously-seen cell's ID
+  int m_prev_task_cell;		// Cell ID of previous task
+  int m_num_task_cells;		// Number of task cells seen
+
   cPopulationInterface(); // @not_implemented
   cPopulationInterface(const cPopulationInterface&); // @not_implemented
   cPopulationInterface operator=(const cPopulationInterface&); // @not_implemented
@@ -62,6 +66,13 @@
   void SetCellID(int in_id) { m_cell_id = in_id; }
   void SetDemeID(int in_id) { m_deme_id = in_id; }
 
+  int GetPrevSeenCellID() { return m_prevseen_cell_id; }
+  int GetPrevTaskCellID() { return m_prev_task_cell; }
+  int GetNumTaskCellsReached() { return m_num_task_cells; }
+  void AddReachedTaskCell() { m_num_task_cells++; }
+  void SetPrevSeenCellID(int in_id) { m_prevseen_cell_id = in_id; }
+  void SetPrevTaskCellID(int in_id) { m_prev_task_cell = in_id; }
+
   bool Divide(cAvidaContext& ctx, cOrganism* parent, cGenome& child_genome);
   cOrganism* GetNeighbor();
   int GetNumNeighbors();

Modified: development/source/main/cStats.cc
===================================================================
--- development/source/main/cStats.cc	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cStats.cc	2008-06-13 14:34:23 UTC (rev 2644)
@@ -38,6 +38,7 @@
 #include "tDataEntry.h"
 #include "cOrgMessage.h"
 #include "cOrgMessagePredicate.h"
+#include "cOrgMovementPredicate.h"
 #include "cReaction.h"
 
 #include "functions.h"
@@ -229,6 +230,17 @@
   numAsleep.Resize(m_world->GetConfig().NUM_DEMES.Get());
   numAsleep.SetAll(0);
 
+  if(m_world->GetConfig().NUM_DEMES.Get() == 0) {
+    relative_pos_event_count.ResizeClear(m_world->GetConfig().WORLD_X.Get(), m_world->GetConfig().WORLD_Y.Get()); 
+    relative_pos_pred_sat.ResizeClear(m_world->GetConfig().WORLD_X.Get(), m_world->GetConfig().WORLD_Y.Get());
+  } else {
+    relative_pos_event_count.ResizeClear(m_world->GetConfig().WORLD_X.Get(), m_world->GetConfig().WORLD_Y.Get() / m_world->GetConfig().NUM_DEMES.Get());
+    relative_pos_pred_sat.ResizeClear(m_world->GetConfig().WORLD_X.Get(), m_world->GetConfig().WORLD_Y.Get() / m_world->GetConfig().NUM_DEMES.Get());
+  }
+  
+  relative_pos_event_count.SetAll(0);
+  relative_pos_pred_sat.SetAll(0);
+
   SetupPrintDatabase();
 }
 
@@ -1196,7 +1208,50 @@
   m_message_predicates.push_back(predicate);
 }
 
+void cStats::RemoveMessagePredicate(cOrgMessagePredicate* predicate)
+{
+  for(message_pred_ptr_list::iterator iter = m_message_predicates.begin(); iter != m_message_predicates.end(); iter++) {
+    if((*iter) == predicate) {
+      m_message_predicates.erase(iter);
+      return;
+    }
+  }
+}
 
+
+/*! This method adds a movement predicate to the list of all movement predicates.  Each predicate
+ * in the list is evaluated for every organism movement.
+ *
+ * NOTE: cStats does NOT own the predicate pointer!  (It DOES NOT delete them!)
+ * */
+void cStats::AddMovementPredicate(cOrgMovementPredicate* predicate)
+{
+  m_movement_predicates.push_back(predicate);
+}
+
+/*! This method is called whenever an organism moves.*/
+void cStats::Move(cOrganism& org) {
+  // Check to see if this message matches any of our predicates.
+  for(movement_pred_ptr_list::iterator i=m_movement_predicates.begin();
+      i!=m_movement_predicates.end(); ++i) {
+    (**i)(org); // Predicate is responsible for tracking info about movement.
+  }
+}
+
+// deme predicate stats
+void cStats::IncEventCount(int x, int y) {
+  relative_pos_event_count.ElementAt(x,y)++;
+}
+
+void cStats::IncPredSat(int cell_id) {
+  cPopulation& pop = m_world->GetPopulation();
+  int deme_id = pop.GetCell(cell_id).GetDemeID();
+  std::pair<int, int> pos = pop.GetDeme(deme_id).GetCellPosition(cell_id);
+  relative_pos_pred_sat.ElementAt(pos.first, pos.second)++;
+}
+
+
+
 /*! This method prints information contained within all active message predicates.
 
 about  specific messages that are being tracked.
@@ -1224,7 +1279,33 @@
   df.Endl();  
 }
 
+void cStats::PrintPredSatFracDump(const cString& filename) {
+  cDataFile& df = m_world->GetDataFile(filename);
+  df.WriteComment( "Displays the fraction of events detected in cell since last print.\n" );
+  df.FlushComments();
+  cString UpdateStr = cStringUtil::Stringf( "%07i", GetUpdate() ) + " = [ ...";
+  df.WriteRaw(UpdateStr);
 
+  int rows = relative_pos_pred_sat.GetNumRows();
+  int cols = relative_pos_pred_sat.GetNumCols();
+  for (int x = 0; x < rows; x++) {
+    for (int y = 0; y < cols; y++) {
+      double data;
+      if(relative_pos_event_count.ElementAt(x,y) == 0) {
+        data = 0.0;
+      } else {
+        data = (double) relative_pos_pred_sat.ElementAt(x,y) / (double) relative_pos_event_count.ElementAt(x,y);
+      }
+      df.WriteBlockElement(data, x*cols+y, cols);
+    }
+  }
+  df.WriteRaw("];");
+  df.Endl();
+  
+  relative_pos_pred_sat.SetAll(0);
+  relative_pos_event_count.SetAll(0);
+}
+
 void cStats::DemePreReplication(cDeme& source_deme, cDeme& target_deme)
 {
   ++m_deme_num_repls;

Modified: development/source/main/cStats.h
===================================================================
--- development/source/main/cStats.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cStats.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -53,6 +53,9 @@
 #ifndef tDataManager_h
 #include "tDataManager.h"
 #endif
+#ifndef tMatrix_h
+#include "tMatrix.h"
+#endif
 #ifndef nGeometry_h
 #include "nGeometry.h"
 #endif
@@ -67,8 +70,10 @@
 class cGenotype;
 class cInjectGenotype;
 class cWorld;
+class cOrganism;
 class cOrgMessage;
 class cOrgMessagePredicate;
+class cOrgMovementPredicate;
 class cDeme;
 class cGermline;
 
@@ -279,6 +284,10 @@
   cDoubleSum sum_deme_generations_per_lifetime;
   int m_num_occupied_demes;
 
+  // deme predicate stats
+  tMatrix<int> relative_pos_event_count;
+  tMatrix<int> relative_pos_pred_sat;
+
   // Speculative Execution Stats
   int m_spec_total;
   int m_spec_num;
@@ -688,6 +697,14 @@
   // @WRE: Added event for printing visit counts
   void PrintCellVisitsData(const cString& filename);
 
+  // deme predicate stats
+  void IncEventCount(int x, int y);
+  void IncPredSat(int cell_id);
+  void PrintPredSatFracDump(const cString& filename);
+
+  void addOrgLocations(std::vector<std::pair<int, int> >); 
+  void PrintDemeRepOrgLocation(const cString& filename);
+
   // -------- Messaging support --------
 public:
   //! Type for a list of pointers to message predicates.
@@ -697,6 +714,8 @@
   void SentMessage(const cOrgMessage& msg);
   //! Adds a predicate that will be evaluated for each message.
   void AddMessagePredicate(cOrgMessagePredicate* predicate);
+  //! Removes a predicate.
+  void RemoveMessagePredicate(cOrgMessagePredicate* predicate);
   //! Prints information regarding messages that "passed" their predicate.
   void PrintPredicatedMessages(const cString& filename);
 
@@ -707,6 +726,17 @@
   message_pred_ptr_list m_message_predicates;
   // -------- End messaging support --------
   
+
+  // -------- Movement support -------------
+public:
+  //! Type for a list of pointers to movement predicates.
+  typedef std::vector<cOrgMovementPredicate*> movement_pred_ptr_list;
+  void Move(cOrganism& org);
+  void AddMovementPredicate(cOrgMovementPredicate* predicate);
+protected:
+  movement_pred_ptr_list m_movement_predicates;
+  // -------- End movement support --------
+
   
   // -------- Deme replication support --------
 public:

Modified: development/source/main/cTaskContext.h
===================================================================
--- development/source/main/cTaskContext.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cTaskContext.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -118,6 +118,7 @@
     return ret;
   }
   inline void AddTaskState(cTaskState* value) { m_task_states->Add(m_task_entry, value); }
+  inline cOrgInterface* GetOrgInterface() { return m_interface; }
 };
 
 

Modified: development/source/main/cTaskLib.cc
===================================================================
--- development/source/main/cTaskLib.cc	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cTaskLib.cc	2008-06-13 14:34:23 UTC (rev 2644)
@@ -30,6 +30,10 @@
 #include "cEnvReqs.h"
 #include "tHashTable.h"
 #include "cTaskState.h"
+#include "cPopulation.h"
+#include "cPopulationCell.h"
+#include "cOrgMessagePredicate.h"
+#include "cOrgMovementPredicate.h"
 
 #include "platform.h"
 
@@ -384,8 +388,30 @@
   else if (name == "net_receive")
     NewTask(name, "Successfully Received Network Message", &cTaskLib::Task_NetReceive);
   
+  // Movement Tasks
+  if (name == "move_up_gradient")
+    NewTask(name, "Move up gradient", &cTaskLib::Task_MoveUpGradient);
+  else if (name == "move_neutral_gradient")
+    NewTask(name, "Move neutral gradient", &cTaskLib::Task_MoveNeutralGradient);
+  else if (name == "move_down_gradient")
+    NewTask(name, "Move down gradient", &cTaskLib::Task_MoveDownGradient);
+  else if (name == "move_not_up_gradient")
+    NewTask(name, "Move not up gradient", &cTaskLib::Task_MoveNotUpGradient);
+  else if (name == "move_to_right_side")
+    NewTask(name, "Move to right side", &cTaskLib::Task_MoveToRightSide);
+  else if (name == "move_to_left_side")
+    NewTask(name, "Move to left side", &cTaskLib::Task_MoveToLeftSide);
+  // BDC Movement Tasks
+  else if (name == "move")
+    NewTask(name, "Successfully Moved", &cTaskLib::Task_Move);
+  else if (name == "movetotarget")
+    NewTask(name, "Move to a target area", &cTaskLib::Task_MoveToTarget);
+  else if (name == "movetoevent")
+    NewTask(name, "Move to a target area", &cTaskLib::Task_MoveToMovementEvent);
+  else if (name == "movebetweenevent")
+    NewTask(name, "Move to a target area", &cTaskLib::Task_MoveBetweenMovementEvent);  
+
   
-  
   // Make sure we have actually found a task  
   if (task_array.GetSize() == start_size) {
     if (errors != NULL && errors->GetSize() == 0) {
@@ -2834,3 +2860,150 @@
   if (ctx.NetIsValid()) return 1.0;
   return 0.0;
 }
+
+//TODO: add movement tasks here
+
+double cTaskLib::Task_MoveUpGradient(cTaskContext& ctx) const {
+  if(ctx.GetOrganism()->GetGradientMovement() == 1.0)
+    return 1.0;
+  return 0.0;
+}
+
+double cTaskLib::Task_MoveNeutralGradient(cTaskContext& ctx) const {
+  if(ctx.GetOrganism()->GetGradientMovement() == 0.0)
+    return 1.0;
+  return 0.0;
+}
+
+double cTaskLib::Task_MoveDownGradient(cTaskContext& ctx) const {
+  if(ctx.GetOrganism()->GetGradientMovement() == -1.0)
+    return 1.0;
+  return 0.0;
+}
+
+double cTaskLib::Task_MoveNotUpGradient(cTaskContext& ctx) const {
+  if(Task_MoveUpGradient(ctx))
+    return 0.0;
+  return 1.0;
+}
+
+double cTaskLib::Task_MoveToRightSide(cTaskContext& ctx) const {
+  cDeme& deme = m_world->GetPopulation().GetDeme(ctx.GetOrgInterface()->GetDemeID());
+  std::pair<int, int> location = deme.GetCellPosition(ctx.GetOrgInterface()->GetCellID());
+  
+  if(location.first == m_world->GetConfig().WORLD_X.Get()-1)
+    return 1.0;
+  return 0.0;
+}
+
+double cTaskLib::Task_MoveToLeftSide(cTaskContext& ctx) const {
+  cDeme& deme = m_world->GetPopulation().GetDeme(ctx.GetOrgInterface()->GetDemeID());
+  std::pair<int, int> location = deme.GetCellPosition(ctx.GetOrgInterface()->GetCellID());
+  
+  if(location.first == 0)
+    return 1.0;
+  return 0.0;
+}
+
+double cTaskLib::Task_Move(cTaskContext& ctx) const
+{
+  if(ctx.GetOrganism()->GetCellID() != ctx.GetOrganism()->GetPrevSeenCellID()) {
+    ctx.GetOrganism()->SetPrevSeenCellID(ctx.GetOrganism()->GetCellID());
+    return 1.0;
+  }
+  
+  return 0.0;
+
+} //End cTaskLib::Task_Move()
+
+double cTaskLib::Task_MoveToTarget(cTaskContext& ctx) const
+//Note - a generic version of this is now at - Task_MoveToMovementEvent
+{
+  cOrgInterface* iface = ctx.GetOrgInterface();
+  cDeme& deme = m_world->GetPopulation().GetDeme(ctx.GetOrgInterface()->GetDemeID());
+  int celldata = m_world->GetPopulation().GetCell(iface->GetCellID()).GetCellData();
+
+  int current_cell = deme.GetRelativeCellID(iface->GetCellID());
+  int prev_target = deme.GetRelativeCellID(iface->GetPrevTaskCellID());
+  
+  // If the organism is currently on a target cell, see which target cell it previously
+  // visited.  Since we want them to move back and forth, only reward if we are on
+  // a different target cell.
+
+  if(celldata > 1) 
+  {
+    if (current_cell == prev_target) {
+      // At some point, we may want to return a fraction
+      return 0;
+    } else {
+      iface->AddReachedTaskCell();
+      iface->SetPrevTaskCellID(current_cell);
+      return 1.0;
+    }
+  }
+
+  return 0;
+
+} //End cTaskLib::TaskMoveToTarget()
+
+double cTaskLib::Task_MoveToMovementEvent(cTaskContext& ctx) const {
+  cDeme& deme = m_world->GetPopulation().GetDeme(ctx.GetOrgInterface()->GetDemeID());
+  int cell_data = m_world->GetPopulation().GetCell(ctx.GetOrgInterface()->GetCellID()).GetCellData();
+  cOrgInterface* iface = ctx.GetOrgInterface();
+
+  if(cell_data <= 0)
+    return 0.0;
+    
+  for(int i = 0; i < deme.GetNumMovementPredicates(); i++) {
+      if(deme.GetMovPredicate(i)->GetEvent(0)->GetEventID() == cell_data) {
+        iface->AddReachedTaskCell();
+        iface->SetPrevTaskCellID(cell_data);
+        return 1.0;
+      }
+  }
+  return 0.0;
+}
+
+
+double cTaskLib::Task_MoveBetweenMovementEvent(cTaskContext& ctx) const {
+  cDeme& deme = m_world->GetPopulation().GetDeme(ctx.GetOrgInterface()->GetDemeID());
+  int cell_data = m_world->GetPopulation().GetCell(ctx.GetOrgInterface()->GetCellID()).GetCellData();
+  cOrgInterface* iface = ctx.GetOrgInterface();
+  int prev_target = deme.GetRelativeCellID(iface->GetPrevTaskCellID());
+
+  int cellid = ctx.GetOrgInterface()->GetCellID();
+
+  // NOTE: as of now, orgs aren't rewarded if they touch a target more than
+  //   once in a row.  Could be useful in the future to have fractional reward
+  //   or something.
+  if( (cell_data <= 0) || (cell_data == prev_target) )
+    return 0.0;
+    
+  for(int i = 0; i < deme.GetNumMovementPredicates(); i++) {
+      // NOTE: having problems with calling the GetNumEvents function for some reason.  FIXME
+      //int num_events = deme.GetMovPredicate(i)->GetNumEvents;
+      int num_events = 2;
+
+      if(num_events == 1) {
+        if( (deme.GetMovPredicate(i)->GetEvent(0)->IsActive()) &&
+            (deme.GetMovPredicate(i)->GetEvent(0)->GetEventID() == cell_data) ) {
+          iface->AddReachedTaskCell();
+          iface->SetPrevTaskCellID(cell_data);
+          return 1.0;
+        }
+      } else {
+        for(int j = 0; j < num_events; j++) {
+          cDemeCellEvent *event = deme.GetMovPredicate(i)->GetEvent(j);
+          if( (event != NULL) && (event->IsActive()) &&
+              (event->GetEventID() == cell_data) ) {
+            iface->AddReachedTaskCell();
+            iface->SetPrevTaskCellID(cell_data);
+            return 1.0;
+          }
+        }
+      }
+
+  }
+  return 0.0;
+}
+

Modified: development/source/main/cTaskLib.h
===================================================================
--- development/source/main/cTaskLib.h	2008-06-11 19:37:26 UTC (rev 2643)
+++ development/source/main/cTaskLib.h	2008-06-13 14:34:23 UTC (rev 2644)
@@ -278,6 +278,21 @@
   // Network Tasks
   double Task_NetSend(cTaskContext& ctx) const;
   double Task_NetReceive(cTaskContext& ctx) const;
+
+  // Movement tasks (temp, rely on hack)
+  double Task_MoveUpGradient(cTaskContext& ctx) const;
+  double Task_MoveNeutralGradient(cTaskContext& ctx) const;
+  double Task_MoveDownGradient(cTaskContext& ctx) const;
+  double Task_MoveNotUpGradient(cTaskContext& ctx) const;
+  double Task_MoveToRightSide(cTaskContext& ctx) const;
+  double Task_MoveToLeftSide(cTaskContext& ctx) const;
+
+  // BDC Movement tasks
+  double Task_Move(cTaskContext& ctx) const;
+  double Task_MoveToTarget(cTaskContext& ctx) const;
+  double Task_MoveToMovementEvent(cTaskContext& ctx) const;
+  double Task_MoveBetweenMovementEvent(cTaskContext& ctx) const;
+
 };
 
 




More information about the Avida-cvs mailing list