[Avida-SVN] r1910 - in development: documentation source/actions source/cpu source/main

barrick at myxo.css.msu.edu barrick at myxo.css.msu.edu
Wed Aug 8 20:14:09 PDT 2007


Author: barrick
Date: 2007-08-08 23:14:09 -0400 (Wed, 08 Aug 2007)
New Revision: 1910

Modified:
   development/documentation/environment.html
   development/source/actions/PopulationActions.cc
   development/source/cpu/cHardwareBase.cc
   development/source/cpu/cHardwareBase.h
   development/source/cpu/cHardwareCPU.cc
   development/source/cpu/cHardwareCPU.h
   development/source/cpu/cHardwareExperimental.cc
   development/source/cpu/cHardwareGX.cc
   development/source/cpu/cHardwareGX.h
   development/source/main/cAvidaConfig.h
   development/source/main/cEnvironment.cc
   development/source/main/cOrganism.cc
   development/source/main/cOrganism.h
   development/source/main/cPhenotype.cc
   development/source/main/cPhenotype.h
   development/source/main/cPopulation.cc
   development/source/main/cPopulation.h
   development/source/main/cReactionProcess.h
   development/source/main/nReaction.h
Log:
* GX Model
More changes to implement "implicit transcription" with regulation.

* CompeteOrganisms/NewTrial Actions 
Allow you to use Avida like a GA and combine fitnesses from several trials. Mostly adapted from CompeteDemes. Added new ways of calculating fitness to go along with this.

* Resources
Option to mark whether a resource is 'depletable' (so sense commands can work with resources that behave as if they are unlimited). 'Enzyme' type reaction with Michaelis-Menten equation.

..other misc stuff...  



Modified: development/documentation/environment.html
===================================================================
--- development/documentation/environment.html	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/documentation/environment.html	2007-08-09 03:14:09 UTC (rev 1910)
@@ -552,6 +552,9 @@
     <br /><em>pow</em>: Multiply the current merit by 2<sup>bonus</sup>.
        this is effectively multiplicative, but positive bonuses are
        always beneficial, and negative bonuses are harmful.
+    <br /><em>enzyme</em>: Add bonus * resource / (resource + frac) to the current merit.
+    	This is gives a Michaelis-Menten enzyme type reward where bonus is the K<sub>cat</sub>
+    	and frac is the K<sub>m</sub>. Does not work with unlimited resources.
   </td>
   <td>add</td>
 </tr>
@@ -601,6 +604,13 @@
   <td>Whether the cell dies after performing the process</td>
   <td>0</td>
 </tr>
+<tr>
+  <td class="resall">depletable</td>
+  <td>
+    Whether this resource is consumed by reactions.
+  </td>
+  <td>true</td>
+</tr>
 </table>
 <p>&nbsp;</p>
 </div>

Modified: development/source/actions/PopulationActions.cc
===================================================================
--- development/source/actions/PopulationActions.cc	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/actions/PopulationActions.cc	2007-08-09 03:14:09 UTC (rev 1910)
@@ -1091,6 +1091,49 @@
 };
 
 
+class cActionNewTrial : public cAction
+{
+private:
+public:
+  cActionNewTrial(cWorld* world, const cString& args) : cAction(world, args)
+  {
+    cString largs(args);
+  }
+  
+  static const cString GetDescription() { return "No Arguments"; }
+  
+  void Process(cAvidaContext& ctx)
+  {
+    m_world->GetPopulation().NewTrial();
+  }
+};
+
+class cActionCompeteOrganisms : public cAction
+{
+private:
+  int m_type;
+  int m_parents_survive;
+  double m_scaled_time;
+  int m_dynamic_scaling;
+public:
+  cActionCompeteOrganisms(cWorld* world, const cString& args) : cAction(world, args), m_type(0), m_parents_survive(0), m_scaled_time(1.0), m_dynamic_scaling(0)
+  {
+    cString largs(args);
+    if (largs.GetSize()) m_type = largs.PopWord().AsInt();
+    if (largs.GetSize()) m_parents_survive = largs.PopWord().AsInt();
+    if (largs.GetSize()) m_scaled_time = largs.PopWord().AsDouble();
+    if (largs.GetSize()) m_dynamic_scaling = largs.PopWord().AsInt();
+  }
+  
+  static const cString GetDescription() { return "Arguments: [int type=0] [int parents_survive=0] [double scaled_time=1.0] [int dynamic_scaling=0]"; }
+  
+  void Process(cAvidaContext& ctx)
+  {
+    m_world->GetPopulation().CompeteOrganisms(m_type, m_parents_survive, m_scaled_time, m_dynamic_scaling);
+  }
+};
+
+
 /*
  Remove the connections between cells along a column in an avida grid.
  
@@ -1501,6 +1544,9 @@
   action_lib->Register<cActionResetDemes>("ResetDemes");
   action_lib->Register<cActionCopyDeme>("CopyDeme");
   
+  action_lib->Register<cActionNewTrial>("NewTrial");
+  action_lib->Register<cActionCompeteOrganisms>("CompeteOrganisms");
+  
   action_lib->Register<cActionSeverGridCol>("SeverGridCol");
   action_lib->Register<cActionSeverGridRow>("SeverGridRow");
   action_lib->Register<cActionJoinGridCol>("JoinGridCol");
@@ -1531,6 +1577,9 @@
   action_lib->Register<cActionResetDemes>("reset_demes");
   action_lib->Register<cActionCopyDeme>("copy_deme");
   
+  action_lib->Register<cActionCompeteDemes>("new_trial");
+  action_lib->Register<cActionCompeteDemes>("compete_organisms");
+  
   action_lib->Register<cActionSeverGridCol>("sever_grid_col");
   action_lib->Register<cActionSeverGridRow>("sever_grid_row");
   action_lib->Register<cActionJoinGridCol>("join_grid_col");

Modified: development/source/cpu/cHardwareBase.cc
===================================================================
--- development/source/cpu/cHardwareBase.cc	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/cpu/cHardwareBase.cc	2007-08-09 03:14:09 UTC (rev 1910)
@@ -740,8 +740,9 @@
 // @JEB Check implicit repro conditions -- meant to be called at the end of SingleProcess
 void cHardwareBase::CheckImplicitRepro(cAvidaContext& ctx)         
 {  
-  if( (m_world->GetConfig().IMPLICIT_REPRO_TIME.Get() && (organism->GetPhenotype().GetCPUCyclesUsed() >= m_world->GetConfig().IMPLICIT_REPRO_TIME.Get()))
-      || (m_world->GetConfig().IMPLICIT_REPRO_BONUS.Get() && (organism->GetPhenotype().GetCurBonus() >= m_world->GetConfig().IMPLICIT_REPRO_BONUS.Get())) )
+  if( (m_world->GetConfig().IMPLICIT_REPRO_TIME.Get() && (organism->GetPhenotype().GetTimeUsed() >= m_world->GetConfig().IMPLICIT_REPRO_TIME.Get()))
+   || (m_world->GetConfig().IMPLICIT_REPRO_CPU_CYCLES.Get() && (organism->GetPhenotype().GetCurBonus() >= m_world->GetConfig().IMPLICIT_REPRO_CPU_CYCLES.Get()))
+   || (m_world->GetConfig().IMPLICIT_REPRO_BONUS.Get() && (organism->GetPhenotype().GetCPUCyclesUsed() >= m_world->GetConfig().IMPLICIT_REPRO_BONUS.Get())) )
   {
     Inst_Repro(ctx);
   }
@@ -751,7 +752,7 @@
 bool cHardwareBase::Inst_Repro(cAvidaContext& ctx) 
 {
   cout << "This hardware type does not have a =repro= instruction. IMPLICIT_REPRO conditions cannot be used!" << endl;
-  assert(1);
+  exit(1);
   return false;
 }
 

Modified: development/source/cpu/cHardwareBase.h
===================================================================
--- development/source/cpu/cHardwareBase.h	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/cpu/cHardwareBase.h	2007-08-09 03:14:09 UTC (rev 1910)
@@ -72,7 +72,9 @@
   virtual int GetCopiedSize(const int parent_size, const int child_size) = 0;  
   
   bool Divide_CheckViable(cAvidaContext& ctx, const int parent_size, const int child_size);
+public:  //@JEB
   unsigned Divide_DoMutations(cAvidaContext& ctx, double mut_multiplier = 1.0, const int maxmut = INT_MAX);
+protected:
   unsigned Divide_DoExactMutations(cAvidaContext& ctx, double mut_multiplier = 1.0, const int pointmut = INT_MAX);
   bool Divide_TestFitnessMeasures(cAvidaContext& ctx);
   

Modified: development/source/cpu/cHardwareCPU.cc
===================================================================
--- development/source/cpu/cHardwareCPU.cc	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/cpu/cHardwareCPU.cc	2007-08-09 03:14:09 UTC (rev 1910)
@@ -193,6 +193,7 @@
     tInstLibEntry<tMethod>("put-reset", &cHardwareCPU::Inst_TaskPutResetInputs),
     tInstLibEntry<tMethod>("IO", &cHardwareCPU::Inst_TaskIO, nInstFlag::DEFAULT, "Output ?BX?, and input new number back into ?BX?"),
     tInstLibEntry<tMethod>("IO-Feedback", &cHardwareCPU::Inst_TaskIO_Feedback, 0, "Output ?BX?, and input new number back into ?BX?,  and push 1,0,  or -1 onto stack1 if merit increased, stayed the same, or decreased"),
+    tInstLibEntry<tMethod>("IO-bc-0.001", &cHardwareCPU::Inst_TaskIO_BonusCost_0_001),
     tInstLibEntry<tMethod>("match-strings", &cHardwareCPU::Inst_MatchStrings),
     tInstLibEntry<tMethod>("sell", &cHardwareCPU::Inst_Sell),
     tInstLibEntry<tMethod>("buy", &cHardwareCPU::Inst_Buy),
@@ -211,25 +212,24 @@
     tInstLibEntry<tMethod>("donate-quantagb",  &cHardwareCPU::Inst_DonateQuantaThreshGreenBeard),
     tInstLibEntry<tMethod>("donate-NUL", &cHardwareCPU::Inst_DonateNULL),
 
-	tInstLibEntry<tMethod>("IObuf-add1", &cHardwareCPU::Inst_IOBufAdd1),
+    tInstLibEntry<tMethod>("IObuf-add1", &cHardwareCPU::Inst_IOBufAdd1),
     tInstLibEntry<tMethod>("IObuf-add0", &cHardwareCPU::Inst_IOBufAdd0),
 
     tInstLibEntry<tMethod>("rotate-l", &cHardwareCPU::Inst_RotateL),
     tInstLibEntry<tMethod>("rotate-r", &cHardwareCPU::Inst_RotateR),
     tInstLibEntry<tMethod>("rotate-label", &cHardwareCPU::Inst_RotateLabel),
-
     
     tInstLibEntry<tMethod>("set-cmut", &cHardwareCPU::Inst_SetCopyMut),
     tInstLibEntry<tMethod>("mod-cmut", &cHardwareCPU::Inst_ModCopyMut),
     // @WRE additions for movement
     tInstLibEntry<tMethod>("tumble", &cHardwareCPU::Inst_Tumble),
     tInstLibEntry<tMethod>("move", &cHardwareCPU::Inst_Move),
-
-    // Energy instruction
-    tInstLibEntry<tMethod>("recover", &cHardwareCPU::Inst_ZeroEnergyUsed),
     
     // Threading instructions
     tInstLibEntry<tMethod>("fork-th", &cHardwareCPU::Inst_ForkThread),
+    tInstLibEntry<tMethod>("forkl", &cHardwareCPU::Inst_ForkThreadLabel),
+    tInstLibEntry<tMethod>("forkl!=0", &cHardwareCPU::Inst_ForkThreadLabelIfNot0),
+    tInstLibEntry<tMethod>("forkl=0", &cHardwareCPU::Inst_ForkThreadLabelIf0),
     tInstLibEntry<tMethod>("kill-th", &cHardwareCPU::Inst_KillThread),
     tInstLibEntry<tMethod>("id-th", &cHardwareCPU::Inst_ThreadID),
     
@@ -492,11 +492,11 @@
   
   if (m_world->GetConfig().PROMOTERS_ENABLED.Get() == 1) {
     //First instruction - check whether we should be starting at a promoter.
-    if (phenotype.GetTimeUsed() == 0) Inst_Terminate(m_world->GetDefaultContext());
+    if (phenotype.GetCPUCyclesUsed() == 0) Inst_Terminate(m_world->GetDefaultContext());
   }
   
-  phenotype.IncTimeUsed();
   phenotype.IncCPUCyclesUsed();
+  if (!m_world->GetConfig().NO_CPU_CYCLE_TIME.Get()) phenotype.IncTimeUsed();
 
   const int num_threads = GetNumThreads();
   
@@ -534,7 +534,7 @@
       // NOTE: This call based on the cur_inst must occur prior to instruction
       //       execution, because this instruction reference may be invalid after
       //       certain classes of instructions (namely divide instructions) @DMB
-      const int addl_time_cost = m_inst_set->GetAddlTimeCost(cur_inst);
+      const int time_cost = m_inst_set->GetAddlTimeCost(cur_inst);
 
       // Prob of exec (moved from SingleProcess_PayCosts so that we advance IP after a fail)
       if ( m_inst_set->GetProbFail(cur_inst) > 0.0 ) {
@@ -547,8 +547,8 @@
       // we now want to move to the next instruction in the memory.
       if (m_advance_ip == true) IP().Advance();
       
-      // Pay the additional death_cost of the instruction now
-      phenotype.IncTimeUsed(addl_time_cost);
+      // Pay the time cost of the instruction now
+      phenotype.IncTimeUsed(time_cost);
       
       // In the promoter model, there may be a chance of termination
       // that causes execution to start at a new instruction (per instruction executed)
@@ -2809,6 +2809,17 @@
   return true;
 }
 
+bool cHardwareCPU::Inst_TaskIO_BonusCost(cAvidaContext& ctx, double bonus_cost)
+{
+  // Levy the cost
+  double new_bonus = organism->GetPhenotype().GetCurBonus() * (1 - bonus_cost);
+  if (new_bonus < 0) new_bonus = 0;
+  //keep the bonus positive or zero
+  organism->GetPhenotype().SetCurBonus(new_bonus);
+  
+  return Inst_TaskIO(ctx);
+}
+
 bool cHardwareCPU::Inst_TaskIO_Feedback(cAvidaContext& ctx)
 {
   const int reg_used = FindModifiedRegister(REG_BX);
@@ -2910,11 +2921,11 @@
 
 bool cHardwareCPU::DoSense(cAvidaContext& ctx, int conversion_method, double base)
 {
-  // Returns the log2 amount of a resource or resources 
+  // Returns the amount of a resource or resources 
   // specified by modifying NOPs into register BX
   const tArray<double> & res_count = organism->GetOrgInterface().GetResources();
 
-  // Arbitrarily set to BX since the conditionals use this directly.
+  // Arbitrarily set to BX since the conditional instructions use this directly.
   int reg_to_set = REG_BX;
 
   // There are no resources, return
@@ -2943,7 +2954,7 @@
   // because their mapping to resources will be disrupted
   
   // Attempt to read a label with this maximum length
-  cHardwareCPU::ReadLabel(max_label_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();
@@ -3701,15 +3712,6 @@
   }
 }
 
-// Energy use
-
-bool cHardwareCPU::Inst_ZeroEnergyUsed(cAvidaContext& ctx)
-{
-  // Typically, this instruction should be triggered by a REACTION
-  organism->GetPhenotype().SetTimeUsed(0); 
-  return true;  
-}
-
 // Multi-threading.
 
 bool cHardwareCPU::Inst_ForkThread(cAvidaContext& ctx)
@@ -3719,6 +3721,49 @@
   return true;
 }
 
+bool cHardwareCPU::Inst_ForkThreadLabel(cAvidaContext& ctx)
+{
+  ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
+  
+  // If there is no label, then do normal fork behavior
+  if (GetLabel().GetSize() == 0)
+  {
+    return Inst_ForkThread(ctx);
+  }
+  
+  cHeadCPU searchHead = FindLabel(+1);
+  if ( searchHead.GetPosition() != IP().GetPosition() )
+  {
+    int save_pos = IP().GetPosition();
+    IP().Set(searchHead.GetPosition() + 1);
+    if (!ForkThread()) organism->Fault(FAULT_LOC_THREAD_FORK, FAULT_TYPE_FORK_TH);
+    IP().Set( save_pos );
+  }
+  
+  return true;
+}
+
+bool cHardwareCPU::Inst_ForkThreadLabelIfNot0(cAvidaContext& ctx)
+{
+  if (GetRegister(REG_BX) == 0) 
+  {
+    ReadLabel();
+    return false;
+  }
+  return Inst_ForkThreadLabel(ctx);
+}
+
+bool cHardwareCPU::Inst_ForkThreadLabelIf0(cAvidaContext& ctx)
+{
+  if (GetRegister(REG_BX) != 0)
+  {
+    ReadLabel();
+    return false;
+  }
+  return Inst_ForkThreadLabel(ctx);
+}
+
 bool cHardwareCPU::Inst_KillThread(cAvidaContext& ctx)
 {
   if (!KillThread()) organism->Fault(FAULT_LOC_THREAD_KILL, FAULT_TYPE_KILL_TH);

Modified: development/source/cpu/cHardwareCPU.h
===================================================================
--- development/source/cpu/cHardwareCPU.h	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/cpu/cHardwareCPU.h	2007-08-09 03:14:09 UTC (rev 1910)
@@ -408,6 +408,8 @@
   bool Inst_TaskPutResetInputs(cAvidaContext& ctx);
   bool Inst_TaskIO(cAvidaContext& ctx);
   bool Inst_TaskIO_Feedback(cAvidaContext& ctx);
+  bool Inst_TaskIO_BonusCost(cAvidaContext& ctx, double bonus_cost);
+  bool Inst_TaskIO_BonusCost_0_001(cAvidaContext& ctx) { return Inst_TaskIO_BonusCost(ctx, 0.001); };
   bool Inst_MatchStrings(cAvidaContext& ctx);
   bool Inst_Sell(cAvidaContext& ctx);
   bool Inst_Buy(cAvidaContext& ctx);
@@ -446,13 +448,12 @@
   bool Inst_Tumble(cAvidaContext& ctx);
   bool Inst_Move(cAvidaContext& ctx);
 
-  // Energy use
-  
-  bool Inst_ZeroEnergyUsed(cAvidaContext& ctx); 
-
   // Multi-threading...
 
   bool Inst_ForkThread(cAvidaContext& ctx);
+  bool Inst_ForkThreadLabel(cAvidaContext& ctx);
+  bool Inst_ForkThreadLabelIf0(cAvidaContext& ctx);
+  bool Inst_ForkThreadLabelIfNot0(cAvidaContext& ctx);
   bool Inst_KillThread(cAvidaContext& ctx);
   bool Inst_ThreadID(cAvidaContext& ctx);
 

Modified: development/source/cpu/cHardwareExperimental.cc
===================================================================
--- development/source/cpu/cHardwareExperimental.cc	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/cpu/cHardwareExperimental.cc	2007-08-09 03:14:09 UTC (rev 1910)
@@ -249,8 +249,8 @@
   organism->SetRunning(true);
   
   cPhenotype & phenotype = organism->GetPhenotype();
-  phenotype.IncTimeUsed();
   phenotype.IncCPUCyclesUsed();
+  if (!m_world->GetConfig().NO_CPU_CYCLE_TIME.Get()) phenotype.IncTimeUsed();
 
   const int num_threads = GetNumThreads();
   

Modified: development/source/cpu/cHardwareGX.cc
===================================================================
--- development/source/cpu/cHardwareGX.cc	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/cpu/cHardwareGX.cc	2007-08-09 03:14:09 UTC (rev 1910)
@@ -187,6 +187,7 @@
     tInstLibEntry<tMethod>("put", &cHardwareGX::Inst_TaskPut),
     tInstLibEntry<tMethod>("put-reset", &cHardwareGX::Inst_TaskPutResetInputs),
     tInstLibEntry<tMethod>("IO", &cHardwareGX::Inst_TaskIO, nInstFlag::DEFAULT, "Output ?BX?, and input new number back into ?BX?"),
+    tInstLibEntry<tMethod>("IO-decay", &cHardwareGX::Inst_TaskIO_DecayBonus),
     tInstLibEntry<tMethod>("IO-Feedback", &cHardwareGX::Inst_TaskIO_Feedback, 0, "Output ?BX?, and input new number back into ?BX?,  and push 1,0,  or -1 onto stack1 if merit increased, stayed the same, or decreased"),
     tInstLibEntry<tMethod>("match-strings", &cHardwareGX::Inst_MatchStrings),
     tInstLibEntry<tMethod>("sell", &cHardwareGX::Inst_Sell),
@@ -395,7 +396,8 @@
     AdjustPromoterRates();
     
     // \todo implement different initial conditions for created executable programids
-    ProcessImplicitGeneExpression(); 
+    m_promoter_update_head.Set(organism->GetGenome().GetSize() - 1); //So that ++ moves it to position zero
+    ProcessImplicitGeneExpression(1); 
   }
   
   m_current = m_programids.back();
@@ -436,12 +438,20 @@
   if ( m_world->GetConfig().IMPLICIT_GENE_EXPRESSION.Get() )
   {
     m_recycle_state += (double)m_world->GetConfig().IMPLICIT_TURNOVER_RATE.Get();
+    int num_programids = m_programids.size();
     while (m_recycle_state >= 1.0)
     {
-      if (m_programids.size() > 1) RemoveProgramid(1);
+      if (m_programids.size() > (unsigned int)m_world->GetConfig().MAX_PROGRAMIDS.Get()) 
+      {
+        RemoveProgramid(1);
+      }
+      else
+      {
+        num_programids++;
+      }
       m_recycle_state -= 1.0;
     }
-    ProcessImplicitGeneExpression();
+    ProcessImplicitGeneExpression(num_programids);
   }
     
   organism->SetRunning(true);
@@ -2317,6 +2327,13 @@
   return true;
 }
 
+bool cHardwareGX::Inst_TaskIO_DecayBonus(cAvidaContext& ctx)
+{
+  (void) Inst_TaskIO(ctx);  
+  organism->GetPhenotype().SetCurBonus(organism->GetPhenotype().GetCurBonus() * 0.99);
+  return true;
+}
+
 bool cHardwareGX::Inst_TaskIO_Feedback(cAvidaContext& ctx)
 {
   const int reg_used = FindModifiedRegister(REG_BX);
@@ -3981,6 +3998,7 @@
 
   // Find next best match.
   ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
 
   int match_pos = FindRegulatoryMatch( GetLabel() );
   if (match_pos == -1) return false;
@@ -4029,6 +4047,7 @@
 
   // Find next best match.
   ReadLabel();
+  GetLabel().Rotate(1, NUM_NOPS);
 
   int match_pos = FindRegulatoryMatch( GetLabel() );
   if (match_pos == -1) return false;
@@ -4145,7 +4164,8 @@
   static cInstruction terminator_inst = GetInstSet().GetInst(cStringUtil::Stringf("terminator"));
 
   if (in_limit == -1 ) in_limit = m_world->GetConfig().MAX_PROGRAMIDS.Get();
-  
+  if (in_limit > m_world->GetConfig().MAX_PROGRAMIDS.Get()) in_limit = m_world->GetConfig().MAX_PROGRAMIDS.Get();
+
   // Create executable programids up to the limit
   const int genome_size = m_programids[m_promoter_update_head.GetMemSpace()]->GetMemory().GetSize();
   const int inc = Min(genome_size, m_world->GetConfig().IMPLICIT_MAX_PROGRAMID_LENGTH.Get());
@@ -4154,10 +4174,12 @@
   {
     // Update promoter states according to rates until one fires
     
-    while ( m_promoter_states[m_promoter_update_head.GetPosition()] < 1.0)
-    {
-      m_promoter_states[m_promoter_update_head.GetPosition()] += m_promoter_rates[m_promoter_update_head.GetPosition()];
-
+    do  {
+      // This way goes straight through the genome
+      m_promoter_update_head++;
+      
+      // This way goes interspersed through the genome -- Add as a config option @JEB
+      /*
       int new_pos = m_promoter_update_head.GetPosition();
       new_pos += inc;
       if ( new_pos >= genome_size )
@@ -4165,10 +4187,15 @@
         new_pos++;
         new_pos %= inc;
       }
+      */
       
-      assert((new_pos >= 0) && (new_pos < genome_size));
-      m_promoter_update_head.Set(new_pos);
-    }
+      m_promoter_states[m_promoter_update_head.GetPosition()] += m_promoter_rates[m_promoter_update_head.GetPosition()];
+      if ( (m_world->GetVerbosity() >= VERBOSE_DETAILS) && (m_promoter_states[m_promoter_update_head.GetPosition()] > 0) )
+      {
+        cout << "Promoter position " <<  m_promoter_update_head.GetPosition() << " value " << m_promoter_states[m_promoter_update_head.GetPosition()] << endl;
+      }
+    } while (m_promoter_states[m_promoter_update_head.GetPosition()] < 1.0);
+    
     m_promoter_states[m_promoter_update_head.GetPosition()] -= 1.0;
     
     // Create new programid
@@ -4205,10 +4232,9 @@
       cout << "New programid created. Start position = " << new_programid->GetHead(nHardware::HEAD_READ).GetPosition();
       cout << " length = " <<  new_programid->m_memory.GetSize() << endl;
     }
+    
+    m_promoter_update_head++; //move on to the next position
   }
-
-  m_promoter_update_head++;
-  
 }
 
 
@@ -4257,7 +4283,7 @@
     for (int i=0; i<label.GetSize(); i++)
     {
       // Don't allow a site that overlaps current regulation
-      if (m_promoter_occupied_sites[i] != 0)
+      if (m_promoter_occupied_sites[m.GetPosition()] != 0)
       {
         matched_positions = 0;
         break;
@@ -4524,8 +4550,8 @@
   for (int i=0; i < 2*regulatory_footprint + _label_size; i++)
   {
     m_gx_hardware->m_promoter_occupied_sites[h.GetPosition()] = 0; //Zero regulation
-  }
-  h++;    
+    h++;   
+  } 
   
   m_gx_hardware->AdjustPromoterRates();
 }

Modified: development/source/cpu/cHardwareGX.h
===================================================================
--- development/source/cpu/cHardwareGX.h	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/cpu/cHardwareGX.h	2007-08-09 03:14:09 UTC (rev 1910)
@@ -501,6 +501,7 @@
   bool Inst_TaskPut(cAvidaContext& ctx);
   bool Inst_TaskPutResetInputs(cAvidaContext& ctx);
   bool Inst_TaskIO(cAvidaContext& ctx);
+  bool Inst_TaskIO_DecayBonus(cAvidaContext& ctx);
   bool Inst_TaskIO_Feedback(cAvidaContext& ctx);
   bool Inst_MatchStrings(cAvidaContext& ctx);
   bool Inst_Sell(cAvidaContext& ctx);

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/main/cAvidaConfig.h	2007-08-09 03:14:09 UTC (rev 1910)
@@ -245,8 +245,9 @@
   CONFIG_ADD_VAR(REQUIRED_TASK, int, -1, "Task ID required for successful divide.");
   CONFIG_ADD_VAR(IMMUNITY_TASK, int, -1, "Task providing immunity from the required task.");
   CONFIG_ADD_VAR(REQUIRED_REACTION, int, -1, "Reaction ID required for successful divide.");
-  CONFIG_ADD_VAR(IMPLICIT_REPRO_BONUS, int, 0, "Immediately call Inst_Repro to divide when upon achieving this bonus. 0 = OFF");  
-  CONFIG_ADD_VAR(IMPLICIT_REPRO_TIME, int, 0, "Immediately call Inst_Repro after this many cpu cycles. 0 = OFF");  
+  CONFIG_ADD_VAR(IMPLICIT_REPRO_BONUS, int, 0, "Call Inst_Repro to divide upon achieving this bonus. 0 = OFF");  
+  CONFIG_ADD_VAR(IMPLICIT_REPRO_CPU_CYCLES, int, 0, "Call Inst_Repro after this many cpu cycles. 0 = OFF");  
+  CONFIG_ADD_VAR(IMPLICIT_REPRO_TIME, int, 0, "Call Inst_Repro after this time used. 0 = OFF");  
 
   CONFIG_ADD_GROUP(MUTATION_GROUP, "Mutations");
   CONFIG_ADD_VAR(POINT_MUT_PROB, double, 0.0, "Mutation rate (per-location per update)");
@@ -290,11 +291,14 @@
   CONFIG_ADD_VAR(MERIT_DEFAULT_BONUS, int, 0, "Scale the merit of an offspring by the default bonus\nrather than the accumulated bonus of the parent?"); 
   CONFIG_ADD_VAR(MERIT_BONUS_INST, int, 0, "in BASE_MERIT_METHOD 6, this sets which instruction counts\n(-1 = none, 0 = First in INST_SET.)"); 
   CONFIG_ADD_VAR(MERIT_BONUS_EFFECT, int, 0, "in BASE_MERIT_METHOD 6, this sets how much merit is earned\nper instruction (-1 = penalty, 0 = no effect.)"); 
+  CONFIG_ADD_VAR(FITNESS_METHOD, int, 0, "0 = default, >1 = experimental"); 
+  CONFIG_ADD_VAR(FITNESS_COEFF, double, 1.0, "A FITNESS_METHOD parameter");  
   CONFIG_ADD_VAR(FITNESS_VALLEY, int, 0, "in BASE_MERIT_METHOD 6, this creates valleys from\nFITNESS_VALLEY_START to FITNESS_VALLEY_STOP\n(0 = off, 1 = on)"); 
   CONFIG_ADD_VAR(FITNESS_VALLEY_START, int, 0, "if FITNESS_VALLEY = 1, orgs with num_key_instructions\nfrom FITNESS_VALLEY_START to FITNESS_VALLEY_STOP\nget fitness 1 (lowest)"); 
   CONFIG_ADD_VAR(FITNESS_VALLEY_STOP, int, 0, "if FITNESS_VALLEY = 1, orgs with num_key_instructions\nfrom FITNESS_VALLEY_START to FITNESS_VALLEY_STOP\nget fitness 1 (lowest)"); 
   CONFIG_ADD_VAR(MAX_CPU_THREADS, int, 1, "Number of Threads a CPU can spawn");
   CONFIG_ADD_VAR(THREAD_SLICING_METHOD, int, 0, "Formula for and organism's thread slicing\n  (num_threads-1) * THREAD_SLICING_METHOD + 1\n0 = One thread executed per time slice.\n1 = All threads executed each time slice.\n");
+  CONFIG_ADD_VAR(NO_CPU_CYCLE_TIME, int, 0, "Don't count each CPU cycle as part of gestation time\n");
   CONFIG_ADD_VAR(MAX_LABEL_EXE_SIZE, int, 1, "Max nops marked as executed when labels are used");
   CONFIG_ADD_VAR(MERIT_GIVEN, double, 0.0, "Fraction of merit donated with 'donate' command");
   CONFIG_ADD_VAR(MERIT_RECEIVED, double, 0.0, "Multiplier of merit given with 'donate' command"); 

Modified: development/source/main/cEnvironment.cc
===================================================================
--- development/source/main/cEnvironment.cc	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/main/cEnvironment.cc	2007-08-09 03:14:09 UTC (rev 1910)
@@ -160,6 +160,7 @@
       else if (var_value=="pow") new_process->SetType(nReaction::PROCTYPE_POW);
       else if (var_value=="lin") new_process->SetType(nReaction::PROCTYPE_LIN);
       else if (var_value=="energy") new_process->SetType(nReaction::PROCTYPE_ENERGY);
+      else if (var_value=="enzyme") new_process->SetType(nReaction::PROCTYPE_ENZYME);
       else {
         cerr << "Unknown reaction process type '" << var_value
         << "' found in '" << reaction->GetName() << "'." << endl;
@@ -218,7 +219,13 @@
     }
     else if (var_name == "string") {
       new_process->SetMatchString(var_value);
-	}
+    }
+    else if (var_name == "depletable") {
+    if (!AssertInputBool(var_value, "depletable", var_type))
+        return false;
+    new_process->SetDepletable(var_value.AsInt());  
+    }
+
     else {
       cerr << "Error: Unknown process variable '" << var_name
       << "' in reaction '" << reaction->GetName() << "'" << endl;
@@ -955,7 +962,7 @@
       // Test if infinite resource
       consumed = max_consumed * task_quality;
     } else {
-      // Otherwise we're using a finite resource
+      // Otherwise we're using a finite resource      
       const int res_id = in_resource->GetID();
       
       assert(resource_count[res_id] >= 0);
@@ -976,7 +983,7 @@
       if (consumed == 0.0) continue;
       
       // Mark in the results the resource consumed.
-      result.Consume(res_id, consumed);
+      if (cur_process->GetDepletable()) result.Consume(res_id, consumed);
     }
     
     // Calculate the bonus
@@ -998,7 +1005,14 @@
       case nReaction::PROCTYPE_ENERGY:
         result.AddEnergy(bonus);
         break;
-        
+      case nReaction::PROCTYPE_ENZYME: //@JEB
+        const int res_id = in_resource->GetID();
+        assert(cur_process->GetMaxFraction() != 0);
+        assert(resource_count[res_id] != 0);
+        double reward = cur_process->GetValue() * resource_count[res_id] / (resource_count[res_id] + cur_process->GetMaxFraction());
+        result.AddBonus( reward , reaction_id);
+        break;
+          
       default:
         assert(false);  // Should not get here!
         break;

Modified: development/source/main/cOrganism.cc
===================================================================
--- development/source/main/cOrganism.cc	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/main/cOrganism.cc	2007-08-09 03:14:09 UTC (rev 1910)
@@ -598,3 +598,12 @@
 
   m_phenotype.IncErrors();
 }
+
+void cOrganism::NewTrial()
+{
+  //More should be reset here... @JEB
+  GetPhenotype().NewTrial();
+  m_input_pointer = 0;
+  m_input_buf.Clear();
+  m_output_buf.Clear();
+}

Modified: development/source/main/cOrganism.h
===================================================================
--- development/source/main/cOrganism.h	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/main/cOrganism.h	2007-08-09 03:14:09 UTC (rev 1910)
@@ -248,6 +248,7 @@
   void PrintFinalStatus(std::ostream& fp, int time_used, int time_allocated) const;
   void Fault(int fault_loc, int fault_type, cString fault_desc="");
 
+  void NewTrial();
 
   // --------  Mutation Rate Convenience Methods  --------
   bool TestCopyMut(cAvidaContext& ctx) const { return m_mut_rates.TestCopyMut(ctx); }

Modified: development/source/main/cPhenotype.cc
===================================================================
--- development/source/main/cPhenotype.cc	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/main/cPhenotype.cc	2007-08-09 03:14:09 UTC (rev 1910)
@@ -271,13 +271,14 @@
   
   gestation_time  = parent_phenotype.gestation_time;
   gestation_start = 0;
+  cpu_cycles_used = 0;
   fitness         = parent_phenotype.fitness;
   div_type        = parent_phenotype.div_type;
 
   assert(genome_length > 0);
   assert(copied_size > 0);
   assert(executed_size > 0);
-  assert(gestation_time > 0);
+  assert(gestation_time >= 0); //@JEB 0 valid for some fitness methods
   assert(div_type > 0);
 
   // Initialize current values, as neeeded.
@@ -297,10 +298,16 @@
   for (int j = 0; j < sensed_resources.GetSize(); j++)
 	      sensed_resources[j] =  parent_phenotype.sensed_resources[j];
   SetupPromoterWeights(_genome, true);
+  cur_trial_fitnesses.Resize(0); 
+  cur_trial_bonuses.Resize(0); 
+  cur_trial_times_used.Resize(0); 
+  trial_time_used = 0;
+  trial_cpu_cycles_used = 0;
   
   // Copy last values from parent
   last_merit_base           = parent_phenotype.last_merit_base;
   last_bonus                = parent_phenotype.last_bonus;
+  last_cpu_cycles_used      = parent_phenotype.last_cpu_cycles_used;
   last_num_errors           = parent_phenotype.last_num_errors;
   last_num_donates          = parent_phenotype.last_num_donates;
   last_task_count           = parent_phenotype.last_task_count;
@@ -310,7 +317,7 @@
   last_reaction_add_reward  = parent_phenotype.last_reaction_add_reward;
   last_inst_count           = parent_phenotype.last_inst_count;
   last_sense_count          = parent_phenotype.last_sense_count;
-  last_fitness              = last_merit_base * last_bonus / gestation_time;
+  last_fitness              = CalcFitness(last_merit_base, last_bonus, gestation_time, last_cpu_cycles_used);
 
   // Setup other miscellaneous values...
   num_divides     = 0;
@@ -425,10 +432,16 @@
   cur_sense_count.SetAll(0);
   cur_task_time.SetAll(0.0);
   SetupPromoterWeights(_genome, true);
+  cur_trial_fitnesses.Resize(0);
+  cur_trial_bonuses.Resize(0); 
+  cur_trial_times_used.Resize(0); 
+  trial_time_used = 0;
+  trial_cpu_cycles_used = 0;
   
   // Copy last values from parent
   last_merit_base = genome_length;
   last_bonus      = 1;
+  last_cpu_cycles_used = 0;
   last_num_errors = 0;
   last_num_donates = 0;
   last_task_count.SetAll(0);
@@ -515,10 +528,10 @@
 /**
  * This function is run whenever an organism executes a successful divide.
  **/
-
-void cPhenotype::DivideReset(const cGenome & _genome)
+ 
+ void cPhenotype::DivideReset(const cGenome & _genome)
 {
-  assert(time_used > 0);
+  assert(time_used >= 0);
   assert(initialized == true);
 
   // Update these values as needed...
@@ -542,11 +555,12 @@
   (void) executed_size;        // Unchanged
   gestation_time  = time_used - gestation_start;
   gestation_start = time_used;
-  fitness         = merit.GetDouble() / gestation_time;
+  fitness = CalcFitness( cur_merit_base, cur_bonus, gestation_time, cpu_cycles_used); 
 
   // Lock in cur values as last values.
   last_merit_base           = cur_merit_base;
   last_bonus                = cur_bonus;
+  last_cpu_cycles_used      = cpu_cycles_used;
 //TODO?  last_energy         = cur_energy_bonus;
   last_num_errors           = cur_num_errors;
   last_num_donates          = cur_num_donates;
@@ -560,6 +574,7 @@
 
   // Reset cur values.
   cur_bonus       = m_world->GetConfig().DEFAULT_BONUS.Get();
+  cpu_cycles_used = 0;
   cur_energy_bonus = 0.0;
   cur_num_errors  = 0;
   cur_num_donates  = 0;
@@ -658,7 +673,6 @@
   m_task_states.ClearAll();
 }
 
-
 /**
  * This function runs whenever a *test* CPU divides. It processes much of
  * the information for that CPU in order to actively reflect its executed
@@ -679,12 +693,13 @@
   (void) executed_size;                          // Unchanged
   gestation_time  = time_used - gestation_start;
   gestation_start = time_used;
-  fitness         = merit.GetDouble() / gestation_time;
+  fitness         = CalcFitness(cur_merit_base, cur_bonus, gestation_time, cpu_cycles_used);
   (void) div_type; 				// Unchanged
 
   // Lock in cur values as last values.
   last_merit_base           = cur_merit_base;
   last_bonus                = cur_bonus;
+  last_cpu_cycles_used      = cpu_cycles_used;
   last_num_errors           = cur_num_errors;
   last_num_donates          = cur_num_donates;
   last_task_count           = cur_task_count;
@@ -697,6 +712,7 @@
 
   // Reset cur values.
   cur_bonus       = m_world->GetConfig().DEFAULT_BONUS.Get();
+  cpu_cycles_used = 0;
   cur_num_errors  = 0;
   cur_num_donates  = 0;
   cur_task_count.SetAll(0);
@@ -710,7 +726,12 @@
   cur_task_time.SetAll(0.0);
   sensed_resources.SetAll(-1.0);
   SetupPromoterWeights(_genome, true);
-  
+  cur_trial_fitnesses.Resize(0); 
+  cur_trial_bonuses.Resize(0); 
+  cur_trial_times_used.Resize(0); 
+  trial_time_used = 0;
+  trial_cpu_cycles_used = 0;
+
   // Setup other miscellaneous values...
   num_divides++;
   generation++;
@@ -808,11 +829,12 @@
   assert(genome_length > 0);
   assert(copied_size > 0);
   assert(executed_size > 0);
-  assert(gestation_time > 0);
+  assert(gestation_time >= 0); //@JEB 0 valid for some fitness methods
   assert(div_type > 0);
 
   // Initialize current values, as neeeded.
   cur_bonus       = m_world->GetConfig().DEFAULT_BONUS.Get();
+  cpu_cycles_used = 0;
   cur_num_errors  = 0;
   cur_num_donates  = 0;
   cur_task_count.SetAll(0);
@@ -824,11 +846,17 @@
   cur_task_time.SetAll(0.0);
   for (int j = 0; j < sensed_resources.GetSize(); j++)
 	      sensed_resources[j] =  clone_phenotype.sensed_resources[j];
-  //SetupPromoterWeights(_genome); Do we reset here?
+  //SetupPromoterWeights(_genome); Do we reset here? @JEB
+  cur_trial_fitnesses.Resize(0); 
+  cur_trial_bonuses.Resize(0); 
+  cur_trial_times_used.Resize(0); 
+  trial_time_used = 0;
+  trial_cpu_cycles_used = 0;
 
   // Copy last values from parent
   last_merit_base          = clone_phenotype.last_merit_base;
   last_bonus               = clone_phenotype.last_bonus;
+  last_cpu_cycles_used     = clone_phenotype.last_cpu_cycles_used;
   last_num_errors          = clone_phenotype.last_num_errors;
   last_num_donates         = clone_phenotype.last_num_donates;
   last_task_count          = clone_phenotype.last_task_count;
@@ -836,7 +864,7 @@
   last_reaction_add_reward = clone_phenotype.last_reaction_add_reward;
   last_inst_count          = clone_phenotype.last_inst_count;
   last_sense_count         = clone_phenotype.last_sense_count;  
-  last_fitness             = last_merit_base * last_bonus / gestation_time;
+  last_fitness             = CalcFitness(last_merit_base, last_bonus, gestation_time, last_cpu_cycles_used);
 
   // Setup other miscellaneous values...
   num_divides     = 0;
@@ -1305,33 +1333,31 @@
   return out_size;
 } 
 
-void cPhenotype::SetupPromoterWeights(const cGenome & _genome, const bool clear)
+
+double cPhenotype::CalcFitness(double _merit_base, double _bonus, int _gestation_time, int _cpu_cycles) const
 {
-  if (!m_world->GetConfig().PROMOTERS_ENABLED.Get()) return;
-
-  // Ideally, this wouldn't be hard-coded
-  static cInstruction promoter_inst = m_world->GetHardwareManager().GetInstSet().GetInst(cStringUtil::Stringf("promoter"));
-
-  int old_size = base_promoter_weights.GetSize();
-  cur_promoter_weights.Resize(_genome.GetSize());
-  base_promoter_weights.Resize(_genome.GetSize());
-  promoter_repression.Resize(_genome.GetSize());
-  promoter_activation.Resize(_genome.GetSize());
-
-  // Only change new regions of the genome (that might have been allocated since this was last called)
-  for ( int i = (clear ? 0 : old_size); i<_genome.GetSize(); i++)
+  double out_fitness = 0;
+  switch (m_world->GetConfig().FITNESS_METHOD.Get())
   {
-    base_promoter_weights[i] = 1;
-    promoter_repression[i] = 0;
-    promoter_activation[i] = 0;
+    case 0: // Normal
+    assert(_gestation_time > 0);
+    out_fitness = _merit_base * _bonus / _gestation_time;
+    break;
 
-    // Now change the weights at instructions that are not promoters if called for
-    if ( _genome[i] != promoter_inst)
+    case 1: //Activity of one enzyme in pathway altered (with diminishing returns and a cost for each executed instruction)
     {
-      base_promoter_weights[i] *= m_world->GetConfig().PROMOTER_BG_STRENGTH.Get(); 
+      out_fitness = 0;
+      double net_bonus = _bonus +  - m_world->GetConfig().DEFAULT_BONUS.Get();
+      out_fitness = net_bonus / (net_bonus + 1)* exp (_gestation_time * log(1 - m_world->GetConfig().FITNESS_COEFF.Get())); 
     }
-    cur_promoter_weights[i] = base_promoter_weights[i];
+    break;
+     
+    default:
+    cout << "Unknown FITNESS_METHOD!" << endl;
+    exit(1);
   }
+  
+  return out_fitness;
 }
 
 void cPhenotype::ReduceEnergy(const double cost) {
@@ -1364,17 +1390,6 @@
   energy_tobe_applied = 0.0;
 }
 
-void cPhenotype::DecayAllPromoterRegulation()
-{
-  for ( int i=0; i<cur_promoter_weights.GetSize(); i++)
-  {
-    promoter_activation[i] *= (1 - m_world->GetConfig().REGULATION_DECAY_FRAC.Get());
-    promoter_repression[i] *= (1 - m_world->GetConfig().REGULATION_DECAY_FRAC.Get());
-    cur_promoter_weights[i] = base_promoter_weights[i] * exp((1+promoter_activation[i])*log(2.0)) / exp((1+promoter_repression[i])*log(2.0));
-
-  }
-}
-
 double cPhenotype::ExtractParentEnergy() {
   assert(m_world->GetConfig().ENERGY_ENABLED.Get() > 0);
   // energy model config variables
@@ -1409,6 +1424,47 @@
   return child_energy;
 }
 
+void cPhenotype::SetupPromoterWeights(const cGenome & _genome, const bool clear)
+{
+  if (!m_world->GetConfig().PROMOTERS_ENABLED.Get()) return;
+
+  // Ideally, this wouldn't be hard-coded
+  static cInstruction promoter_inst = m_world->GetHardwareManager().GetInstSet().GetInst(cStringUtil::Stringf("promoter"));
+
+  int old_size = base_promoter_weights.GetSize();
+  cur_promoter_weights.Resize(_genome.GetSize());
+  base_promoter_weights.Resize(_genome.GetSize());
+  promoter_repression.Resize(_genome.GetSize());
+  promoter_activation.Resize(_genome.GetSize());
+
+  // Only change new regions of the genome (that might have been allocated since this was last called)
+  for ( int i = (clear ? 0 : old_size); i<_genome.GetSize(); i++)
+  {
+    base_promoter_weights[i] = 1;
+    promoter_repression[i] = 0;
+    promoter_activation[i] = 0;
+
+    // Now change the weights at instructions that are not promoters if called for
+    if ( _genome[i] != promoter_inst)
+    {
+      base_promoter_weights[i] *= m_world->GetConfig().PROMOTER_BG_STRENGTH.Get(); 
+    }
+    cur_promoter_weights[i] = base_promoter_weights[i];
+  }
+}
+
+
+void cPhenotype::DecayAllPromoterRegulation()
+{
+  for ( int i=0; i<cur_promoter_weights.GetSize(); i++)
+  {
+    promoter_activation[i] *= (1 - m_world->GetConfig().REGULATION_DECAY_FRAC.Get());
+    promoter_repression[i] *= (1 - m_world->GetConfig().REGULATION_DECAY_FRAC.Get());
+    cur_promoter_weights[i] = base_promoter_weights[i] * exp((1+promoter_activation[i])*log(2.0)) / exp((1+promoter_repression[i])*log(2.0));
+
+  }
+}
+
 void cPhenotype::RegulatePromoter(const int i, const bool up )
 {
   // Make sure we were initialized
@@ -1426,7 +1482,196 @@
   cur_promoter_weights[i] = base_promoter_weights[i] * exp((1+promoter_activation[i])*log(2.0)) / exp((1+promoter_repression[i])*log(2.0));
 }
 
+// Save the current fitness and reset relevant parts of the phenotype
+void cPhenotype::NewTrial()
+{ 
+  //Return if a complete trial has not occurred.
+  //(This will happen if CompeteOrganisms was called before in the same update
+  if (trial_cpu_cycles_used == 0) return;
+  
+  //Record the merit of this trial
+  fitness = CalcFitness( GetCurMeritBase(), GetCurBonus() , trial_time_used, trial_cpu_cycles_used); // This is a per-trial fitness @JEB
+  cur_trial_fitnesses.Push(fitness);
+  cur_trial_bonuses.Push(GetCurBonus());
+  cur_trial_times_used.Push(trial_time_used);
 
+  //The rest of the function, resets the phenotype like DivideReset(), but without
+  //incrementing the generation or child statistics.
+  
+  //Most importantly, this does (below):
+  // trial_time_used = 0;
+  // trial_cpu_cycles_used = 0;
+  // SetCurBonus(m_world->GetConfig().DEFAULT_BONUS.Get());
+  
+  // Update these values as needed...
+  int cur_merit_base = CalcSizeMerit();
+  
+  // If we are resetting the current merit, do it here
+  // and it will also be propagated to the child
+  int merit_default_bonus = m_world->GetConfig().MERIT_DEFAULT_BONUS.Get();
+  if (merit_default_bonus) {
+    merit = cur_merit_base * m_world->GetConfig().DEFAULT_BONUS.Get();
+  }
+  else { // Default
+    merit = cur_merit_base * cur_bonus;
+  }
+  
+  // update energy store
+  energy_store += cur_energy_bonus;
+  energy_store = m_world->GetConfig().ENERGY_GIVEN_AT_BIRTH.Get(); // We reset to what they had at birth
+  cur_energy_bonus = 0;
+      // to be perfectly accurate, this should be from a last_energy value??
+
+  
+ // genome_length   = _genome.GetSize();  //No child! @JEB
+  (void) copied_size;          // Unchanged
+  (void) executed_size;        // Unchanged
+  gestation_time  = time_used - gestation_start;  //Keep gestation referring to actual replication time! @JEB
+  gestation_start = time_used;                    //Keep gestation referring to actual replication time! @JEB
+ // fitness         = merit.GetDouble() / gestation_time; //Use fitness measure that is per-trial @JEB
+
+  // Lock in cur values as last values.
+  last_merit_base           = cur_merit_base;
+  last_bonus                = cur_bonus;
+  last_cpu_cycles_used      = cpu_cycles_used;
+//TODO?  last_energy         = cur_energy_bonus;
+  last_num_errors           = cur_num_errors;
+  last_num_donates          = cur_num_donates;
+  last_task_count           = cur_task_count;
+  last_task_quality         = cur_task_quality;
+  last_task_value			= cur_task_value;
+  last_reaction_count       = cur_reaction_count;
+  last_reaction_add_reward  = cur_reaction_add_reward;
+  last_inst_count           = cur_inst_count;
+  last_sense_count          = cur_sense_count;
+
+  // Reset cur values.
+  cur_bonus       = m_world->GetConfig().DEFAULT_BONUS.Get();
+  cpu_cycles_used = 0;
+  cur_energy_bonus = 0.0;
+  cur_num_errors  = 0;
+  cur_num_donates  = 0;
+  cur_task_count.SetAll(0);
+  eff_task_count.SetAll(0);
+  cur_task_quality.SetAll(0);
+  cur_task_value.SetAll(0);
+  cur_reaction_count.SetAll(0);
+  cur_reaction_add_reward.SetAll(0);
+  cur_inst_count.SetAll(0);
+  cur_sense_count.SetAll(0);
+  //cur_trial_fitnesses.Resize(0); Don't throw out the tiral fitnesses! @JEB
+  trial_time_used = 0;
+  trial_cpu_cycles_used = 0;
+
+  // Setup other miscellaneous values...
+  num_divides++;
+  (void) generation;
+  (void) time_used;
+  age             = 0;
+  fault_desc      = "";
+  (void) neutral_metric;
+  life_fitness = fitness; 
+
+  num_thresh_gb_donations_last = num_thresh_gb_donations;
+  num_thresh_gb_donations = 0;
+  num_quanta_thresh_gb_donations_last = num_quanta_thresh_gb_donations;
+  num_quanta_thresh_gb_donations = 0;
+
+  // Leave flags alone...
+  (void) is_injected;
+  is_donor_last = is_donor_cur;
+  is_donor_cur = false;
+  is_donor_rand_last = is_donor_rand;
+  is_donor_rand = false;
+  is_donor_null_last = is_donor_null;
+  is_donor_null = false;
+  is_donor_kin_last = is_donor_kin;
+  is_donor_kin = false;
+  is_donor_edit_last = is_donor_edit;
+  is_donor_edit = false;
+  is_donor_gbg_last = is_donor_gbg;
+  is_donor_gbg = false;
+  is_donor_truegb_last = is_donor_truegb;
+  is_donor_truegb = false;
+  is_donor_threshgb_last = is_donor_threshgb;
+  is_donor_threshgb = false;
+  is_donor_quanta_threshgb_last = is_donor_quanta_threshgb;
+  is_donor_quanta_threshgb = false;
+  is_receiver_last = is_receiver;
+  is_receiver = false;
+  is_receiver_rand = false;
+  is_receiver_kin_last = is_receiver_kin;
+  is_receiver_kin = false;
+  is_receiver_edit_last = is_receiver_edit;
+  is_receiver_edit = false;
+  is_receiver_gbg = false;
+  is_receiver_truegb_last = is_receiver_truegb;
+  is_receiver_truegb = false;
+  is_receiver_threshgb_last = is_receiver_threshgb;
+  is_receiver_threshgb = false;
+  is_receiver_quanta_threshgb_last = is_receiver_quanta_threshgb;
+  is_receiver_quanta_threshgb = false;
+  (void) is_modifier;
+  (void) is_modified;
+  (void) is_fertile;
+  (void) is_mutated;
+  (void) is_multi_thread;
+  (void) parent_true;
+  (void) parent_sex;
+  (void) parent_cross_num;
+
+}
+
+/**
+ * This function is run to reset an organism whose task counts (etc) have already been moved from cur to last
+ * by another call (like NewTrial). It is a subset of DivideReset @JEB
+ **/
+ 
+void cPhenotype::TrialDivideReset(const cGenome & _genome)
+{
+  int cur_merit_base = CalcSizeMerit();
+
+  // If we are resetting the current merit, do it here
+  // and it will also be propagated to the child
+  const int merit_default_bonus = m_world->GetConfig().MERIT_DEFAULT_BONUS.Get();
+  if (merit_default_bonus) {
+    merit = cur_merit_base * m_world->GetConfig().DEFAULT_BONUS.Get();
+  }
+  else { // Defaul
+    merit = cur_merit_base * cur_bonus;
+  }
+
+  //BB:TODO update energy store
+  SetEnergy(energy_store + cur_energy_bonus);
+    
+  genome_length   = _genome.GetSize();
+  gestation_start = time_used;
+  cur_trial_fitnesses.Resize(0); 
+  cur_trial_bonuses.Resize(0); 
+  cur_trial_times_used.Resize(0); 
+
+  // Reset child info...
+  (void) copy_true;
+  (void) divide_sex;
+  (void) mate_select_id;
+  (void) cross_num;
+  last_child_fertile = child_fertile;
+  child_fertile     = true;
+  (void) child_copied_size;
+
+  // A few final changes if the parent was supposed to be be considered
+  // a second child on the divide.
+  if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) {
+    gestation_start = 0;
+    cpu_cycles_used = 0;
+    time_used = 0;
+    neutral_metric += m_world->GetRandom().GetRandNormal();
+    SetupPromoterWeights(_genome, true);
+  }
+
+  if (m_world->GetConfig().GENERATION_INC_METHOD.Get() == GENERATION_INC_BOTH) generation++;
+}
+
 // C O M P A R I S O N    O P E R A T O R S
 
 bool cPhenotype::operator<(const cPhenotype&  rhs) const

Modified: development/source/main/cPhenotype.h
===================================================================
--- development/source/main/cPhenotype.h	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/main/cPhenotype.h	2007-08-09 03:14:09 UTC (rev 1910)
@@ -113,7 +113,7 @@
   tArray<int> cur_task_count;                 // Total times each task was performed
   tArray<int> eff_task_count;                 // Total times each task was performed (resetable during the life of the organism)
   tArray<double> cur_task_quality;            // Average (total?) quality with which each task was performed
-  tArray<double> cur_task_value;			  // Value with which this phenotype performs task
+  tArray<double> cur_task_value;              // Value with which this phenotype performs task
   tArray<int> cur_reaction_count;             // Total times each reaction was triggered.  
   tArray<double> cur_reaction_add_reward;     // Bonus change from triggering each reaction.
   tArray<int> cur_inst_count;                 // Instruction exection counter
@@ -125,11 +125,13 @@
   tArray<double> cur_promoter_weights;        // Current of starting execution from each position, adjusted for regulation; @JEB 
   tArray<double> promoter_activation;         // Amount of positive regulation in play at each site; @JEB 
   tArray<double> promoter_repression;         // Amount of negative regulation in play at each site; @JEB 
-  bool promoter_last_inst_terminated;         // Did terminatin occur when executing the last instruction
-  
-
+  bool promoter_last_inst_terminated;         // Did termination occur when executing the last instruction; @JEB
   tHashTable<void*, cTaskState*> m_task_states;
-
+  tArray<double> cur_trial_fitnesses;         // Fitnesses of various trials.; @JEB
+  tArray<double> cur_trial_bonuses;           // Bonuses of various trials.; @JEB
+  tArray<int> cur_trial_times_used;        // Time used in of various trials.; @JEB
+  int trial_time_used;                        // like time_used, but reset every trial; @JEB
+  int trial_cpu_cycles_used;                  // like cpu_cycles_used, but reset every trial; @JEB
   
   // 3. These mark the status of "in progess" variables at the last divide.
   double last_merit_base;         // Either constant or based on genome length.
@@ -145,6 +147,7 @@
   tArray<int> last_inst_count;	  // Instruction exection counter
   tArray<int> last_sense_count;   // Total times resource combinations have been sensed; @JEB 
   double last_fitness;            // Used to determine sterilization.
+  int last_cpu_cycles_used;
 
   // 4. Records from this organisms life...
   int num_divides;       // Total successful divides organism has produced.
@@ -257,6 +260,8 @@
 
   // Some useful methods...
   int CalcSizeMerit() const;
+  double CalcFitness(double _merit_base, double _bonus, int _gestation_time, int _cpu_cycles) const;
+
   double CalcFitnessRatio() {
     const int merit_base = CalcSizeMerit();
     const double cur_fitness = merit_base * cur_bonus / time_used;
@@ -301,6 +306,12 @@
   double GetSensedResource(int _in) { assert(initialized == true); return sensed_resources[_in]; }
   const tArray<cCodeLabel>& GetActiveTransposons() { assert(initialized == true); return active_transposons; }
   const tArray<double>& GetCurPromoterWeights() { assert(initialized == true); return cur_promoter_weights; }
+  
+  void  NewTrial(); //Save the current fitness, and reset the bonus. @JEB
+  void  TrialDivideReset(const cGenome & _genome); //Subset of resets specific to division not done by NewTrial. @JEB
+  const tArray<double>& GetTrialFitnesses() { return cur_trial_fitnesses; }; //Return list of trial fitnesses. @JEB
+  const tArray<double>& GetTrialBonuses() { return cur_trial_bonuses; }; //Return list of trial bonuses. @JEB
+  const tArray<int>& GetTrialTimesUsed() { return cur_trial_times_used; }; //Return list of trial times used. @JEB
 
   double GetLastMeritBase() const { assert(initialized == true); return last_merit_base; }
   double GetLastBonus() const { assert(initialized == true); return last_bonus; }
@@ -432,8 +443,8 @@
   void IncNumQuantaThreshGbDonations() { assert(initialized == true); num_quanta_thresh_gb_donations++; }
 
   void IncAge()      { assert(initialized == true); age++; }
-  void IncCPUCyclesUsed() { assert(initialized == true); cpu_cycles_used++; }
-  void IncTimeUsed(int i=1) { assert(initialized == true); time_used+=i; }
+  void IncCPUCyclesUsed() { assert(initialized == true); cpu_cycles_used++; trial_cpu_cycles_used++; }
+  void IncTimeUsed(int i=1) { assert(initialized == true); time_used+=i; trial_time_used+=i; }
   void IncErrors()   { assert(initialized == true); cur_num_errors++; }
   void IncDonates()   { assert(initialized == true); cur_num_donates++; }
   void IncSenseCount(const int i) { assert(initialized == true); cur_sense_count[i]++; }  

Modified: development/source/main/cPopulation.cc
===================================================================
--- development/source/main/cPopulation.cc	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/main/cPopulation.cc	2007-08-09 03:14:09 UTC (rev 1910)
@@ -2727,7 +2727,66 @@
   ActivateOrganism(ctx, new_organism, cell_array[cell_id]);
 }
 
+// This function injects the child genome of an organism into the population at cell_id.
+// Takes care of divide mutations.
+void cPopulation::InjectChild(int cell_id, cOrganism& orig_org)
+{
+  assert(cell_id >= 0 && cell_id < cell_array.GetSize());
+  
+  cAvidaContext& ctx = m_world->GetDefaultContext();
+  
+  // Do mutations on the child genome, but restore it to its current state afterward.
+  cGenome save_child = orig_org.ChildGenome();
+  orig_org.GetHardware().Divide_DoMutations(ctx);
+  
+  tArray<cOrganism*> child_array;
+  tArray<cMerit> merit_array;
+  birth_chamber.SubmitOffspring(ctx, orig_org.ChildGenome(), orig_org, child_array, merit_array);
+    //@JEB may want to force asex for an injected child, sex will mess up CompeteOrganisms
+  assert(child_array.GetSize() == 1);
+  cOrganism * new_organism = child_array[0];
+  orig_org.ChildGenome() = save_child;
+  
+  // Set the genotype...
+  //new_organism->SetGenotype(orig_org.GetGenotype());
 
+  // Setup the phenotype...
+  orig_org.GetPhenotype().SetLinesCopied(new_organism->ChildGenome().GetSize());
+  new_organism->GetPhenotype().SetMerit(merit_array[0]);
+  new_organism->GetPhenotype().SetupOffspring(orig_org.GetPhenotype(), new_organism->GetGenome());
+  
+  // Do lineage tracking for the new organisms.
+  LineageSetupOrganism(new_organism, orig_org.GetLineage(),
+                       orig_org.GetLineageLabel(), orig_org.GetGenotype());
+		
+  //By default, store the parent cclade, this may get modified in ActivateOrgansim (@MRR)
+  new_organism->SetCCladeLabel(orig_org.GetCCladeLabel());
+  
+  // Prep the cell..
+  if (m_world->GetConfig().BIRTH_METHOD.Get() == POSITION_CHILD_FULL_SOUP_ELDEST &&
+      cell_array[cell_id].IsOccupied() == true) {
+    // Have to manually take this cell out of the reaper Queue.
+    reaper_queue.Remove( &(cell_array[cell_id]) );
+  }
+  
+  // Setup the mutation rate based on the population cell...
+  const int mut_source = m_world->GetConfig().MUT_RATE_SOURCE.Get();
+  if (mut_source == 1) {
+    // Update the mutation rates of each child from the environment....
+    new_organism->MutationRates().Copy(cell_array[cell_id].MutationRates());
+  } else {
+    // Update the mutation rates of each child from its parent.
+    new_organism->MutationRates().Copy(orig_org.MutationRates());
+  }
+  
+  // Activate the organism in the population...
+//  cGenotype* child_genotype = new_organism->GetGenotype();
+//  child_genotype->DecDeferAdjust();
+//  m_world->GetClassificationManager().AdjustGenotype(*child_genotype);
+  ActivateOrganism(ctx, new_organism, cell_array[cell_id]);
+}
+
+
 void cPopulation::InjectGenome(int cell_id, const cGenome& genome, int lineage_label)
 {
   // Setup the genotype...
@@ -2878,3 +2937,274 @@
   sleep_log[cellID].RemoveAt(sleep_log[cellID].Size()-1);
   sleep_log[cellID].Add(make_pair(p.first, end_time));
 }
+
+// Starts a new trial for each organism in the population
+void cPopulation::NewTrial()
+{
+  for (int i=0; i< GetSize(); i++)
+  {
+    if (GetCell(i).IsOccupied())
+    {
+      GetCell(i).GetOrganism()->NewTrial();
+      GetCell(i).GetOrganism()->GetHardware().Reset();
+    }
+  }
+  
+  //Recalculate the stats immediately, so that if they are printed before a new update 
+  //is processed, they accurately reflect this trial only...
+  cStats& stats = m_world->GetStats();
+  stats.ProcessUpdate();
+  CalcUpdateStats();
+}
+
+/*
+  CompeteOrganisms
+  
+   parents_survive => for any organism represented by >=1 child, the first created is the parent (has no mutations)
+   dynamic_scaling => rescale the time interval such that the geometric mean of the highest fitness versus lower fitnesses
+                      equals a time of 1 unit
+*/
+
+void cPopulation::CompeteOrganisms(int competition_type, int parents_survive, double scaled_time, int dynamic_scaling)
+{
+  cout << "==Compete Organisms==" << endl;
+  double total_fitness = 0;
+  int num_cells = GetSize();
+  tArray<double> org_fitness(num_cells); 
+
+  double lowest_fitness = -1.0;
+  double highest_fitness = -1.0;
+  double lowest_fitness_copied = -1.0;
+  double highest_fitness_copied = -1.0;
+  int different_orgs_copied = 0;
+  int num_competed_orgs = 0;
+
+  int num_trials = 0;
+  
+  // How many trials were there?
+  for (int i = 0; i < num_cells; i++) 
+  {
+    if (GetCell(i).IsOccupied())
+    { 
+      cPhenotype& p = GetCell(i).GetOrganism()->GetPhenotype();
+      num_trials = p.GetTrialFitnesses().GetSize();
+      break;
+    }
+  }
+  tArray<double> min_trial_fitnesses(num_trials);
+  tArray<double> max_trial_fitnesses(num_trials);
+  tArray<double> bonus_sums(num_trials);
+  bonus_sums.SetAll(0);
+  double max_bonus_sum = -1;
+
+  bool init = false;
+  // What is the min and max fitness in each trial
+  for (int i = 0; i < num_cells; i++) 
+  {
+    if (GetCell(i).IsOccupied())
+    {
+      cPhenotype& p = GetCell(i).GetOrganism()->GetPhenotype();
+      tArray<double> trial_fitnesses = p.GetTrialFitnesses();
+      for (int t=0; t < trial_fitnesses.GetSize(); t++) 
+      { 
+        if ((!init) || (min_trial_fitnesses[t] > trial_fitnesses[t])) min_trial_fitnesses[t] = trial_fitnesses[t];
+        if ((!init) || (max_trial_fitnesses[t] < trial_fitnesses[t])) max_trial_fitnesses[t] = trial_fitnesses[t];
+      }
+      init = true;
+    }
+  }  
+  
+  
+  for (int t=0; t < min_trial_fitnesses.GetSize(); t++) 
+  {
+    cout << "Trial #" << t << " Min Fitness = " << min_trial_fitnesses[t] << " Max Fitness = " << max_trial_fitnesses[t] << endl;
+    //cout << "Bonus sum = " << bonus_sums[t] << endl;
+  }
+  
+  bool using_trials = true;
+  for (int i = 0; i < num_cells; i++) 
+  {
+    if (GetCell(i).IsOccupied())
+    {
+      num_competed_orgs++;
+      double fitness = 0.0;
+      cPhenotype& p = GetCell(i).GetOrganism()->GetPhenotype();
+      //Don't need to reset trial_fitnesses because we will call cPhenotype::OffspringReset on the entire pop
+      tArray<double> trial_fitnesses = p.GetTrialFitnesses();
+      tArray<int> trial_times_used = p.GetTrialTimesUsed();
+
+      //If there are no trial fitnesses...use the actual fitness.
+      if (trial_fitnesses.GetSize() == 0)
+      {
+        using_trials = false;
+        trial_fitnesses.Push(p.GetFitness());
+      }
+      switch (competition_type)
+      {
+        //Arithmetic Mean
+        case 0:
+        fitness = 0;
+        for (int t=0; t < trial_fitnesses.GetSize(); t++) 
+        { 
+          fitness+=trial_fitnesses[t]; 
+        }
+        fitness /= trial_fitnesses.GetSize();
+        break;
+      
+        //Product        
+        case 1:
+        fitness = 1.0;
+        for (int t=0; t < trial_fitnesses.GetSize(); t++) 
+        { 
+          fitness*=trial_fitnesses[t]; 
+        }
+        break;
+      
+        //Geometric Mean        
+        case 2:
+        fitness = 1;
+        for (int t=0; t < trial_fitnesses.GetSize(); t++) 
+        { 
+          fitness*=trial_fitnesses[t]; 
+        }
+        fitness = exp( (1/trial_fitnesses.GetSize()) * log(fitness) );
+        break;
+                         
+        default:
+        cout << "Unknown CompeteOrganisms method!" << endl;
+        exit(1);
+      }
+      if (m_world->GetVerbosity() >= VERBOSE_DETAILS) cout << "Trial fitness in cell " << i << " = " << fitness << endl;
+      //-->Note: Setting fitness here will not print out the value of the last trial's fitness because the makeup of the population is going to change anyway.
+      //It will be printed out correctly only if NewTrial and PrintAverages are called on the same update, before CompeteDemes.
+      //p.SetCurBonus( fitness *  (p.GetTimeUsed() - p.GetGestationStart()) / p.GetCurMeritBase() ); //Indirectly set fitness over all trials...??
+     // p.SetCurBonus( trial_fitnesses[trial_fitnesses.GetSize()-1] *  (p.GetTimeUsed() - p.GetGestationStart()) / p.CalcSizeMerit() ); //Or to last trial
+
+      org_fitness[i] = fitness;
+      total_fitness += fitness;
+      
+      if ((highest_fitness == -1.0) || (fitness > highest_fitness)) highest_fitness = fitness;
+      if ((lowest_fitness == -1.0) || (fitness < lowest_fitness)) lowest_fitness = fitness;
+    } // end if occupied
+  }
+  
+  //Rescale by the geometric mean of the difference from the top score and the median
+  if ( dynamic_scaling )
+  {
+    int num_org_not_max = 0;
+    double dynamic_factor = 0;
+    for (int i = 0; i < num_cells; i++) 
+    {
+      if (GetCell(i).IsOccupied())
+      {
+          if (org_fitness[i] != highest_fitness)
+          {
+            num_org_not_max++;
+            dynamic_factor += log(highest_fitness - org_fitness[i]);
+            //cout << "Time scaling factor " << time_scaling_factor << endl;
+          }
+      }
+    }
+    if (num_org_not_max > 0) scaled_time *= exp ( -(1.0/num_org_not_max) * dynamic_factor );
+  }
+  
+  cout << "Competition time " << scaled_time << " units" << endl;
+  total_fitness = 0;
+  for (int i = 0; i < num_cells; i++) 
+  {
+    if (GetCell(i).IsOccupied())
+    {
+        double fitness = exp(log(2) * scaled_time *  (org_fitness[i] - highest_fitness));
+        org_fitness[i] = fitness;
+        total_fitness += fitness;
+    }
+  }
+  
+   // Pick which orgs should be in the next generation. (Filling all cells)
+  tArray<int> new_orgs(num_cells);
+  for (int i = 0; i < num_cells; i++) {
+    double birth_choice = (double) m_world->GetRandom().GetDouble(total_fitness);
+    double test_total = 0;
+    for (int test_org = 0; test_org < num_cells; test_org++) {
+      test_total += org_fitness[test_org];
+      if (birth_choice < test_total) {
+        new_orgs[i] = test_org;
+        if (m_world->GetVerbosity() >= VERBOSE_DETAILS) cout << "Propagating from cell " << test_org << " to " << i << endl;
+        if ((highest_fitness_copied == -1.0) || (org_fitness[test_org] > highest_fitness_copied)) highest_fitness_copied = org_fitness[test_org];
+        if ((lowest_fitness_copied == -1.0) || (org_fitness[test_org] < lowest_fitness_copied)) lowest_fitness_copied = org_fitness[test_org];
+        break;
+      }
+    }
+  }
+  
+  // Track how many of each org we should have.
+  tArray<int> org_count(num_cells);
+  org_count.SetAll(0);
+  for (int i = 0; i < num_cells; i++) {
+    org_count[new_orgs[i]]++;
+  }
+  
+  // Reset organism phenotypes that have successfully divided! Must do before injecting children.
+  // -- but not the full reset if we are using trials, the trial reset should already cover things like task counts, etc.
+  // calling that twice would erase this information before it could potentially be output between NewTrial and CompeteOrganisms events.
+  for (int i = 0; i < num_cells; i++) {
+    if (org_count[i] > 0) {
+      different_orgs_copied++;
+      cPhenotype& p = GetCell(i).GetOrganism()->GetPhenotype();
+      if (using_trials)
+      {
+        p.TrialDivideReset( GetCell(i).GetOrganism()->GetGenome() );
+      }
+      else //trials not used
+      {
+        //TrialReset has never been called so we need the entire routine to make "last" of "cur" stats.
+        p.DivideReset( GetCell(i).GetOrganism()->GetGenome() );
+      }
+    }
+  }
+  
+  tArray<bool> is_init(num_cells); 
+  is_init.SetAll(false);
+  
+  // Copy orgs until all org counts are 1.
+  while (true) {
+    // Find the next org to copy...
+    int from_cell_id, to_cell_id;
+    for (from_cell_id = 0; from_cell_id < num_cells; from_cell_id++) {
+      if (org_count[from_cell_id] > 1) break;
+    }
+    
+    // Stop If we didn't find another org to copy
+    if (from_cell_id == num_cells) break;
+    
+    for (to_cell_id = 0; to_cell_id < num_cells; to_cell_id++) {
+      if (org_count[to_cell_id] == 0) break;
+    }
+    
+    // We now have both a from and a to org....
+    org_count[from_cell_id]--;
+    org_count[to_cell_id]++;
+    
+    cOrganism * organism = GetCell(from_cell_id).GetOrganism();
+    organism->ChildGenome() = organism->GetGenome();
+    InjectChild( to_cell_id, *organism );    
+    
+    is_init[to_cell_id] = true;
+  }
+
+  if (!parents_survive)
+  {
+    // Now create children from remaining cells into themselves
+    for (int cell_id = 0; cell_id < num_cells; cell_id++) {
+      if (is_init[cell_id] == true) continue;
+      cOrganism * organism = GetCell(cell_id).GetOrganism();
+      organism->ChildGenome() = organism->GetGenome();
+      InjectChild( cell_id, *organism ); 
+    }
+  }
+  
+  cout << "Competed: Min fitness = " << lowest_fitness << ", Max fitness = " << highest_fitness << endl;
+  cout << "Copied  : Min fitness = " << lowest_fitness_copied << ", Max fitness = " << highest_fitness_copied << " (scaled to Max = 1.0)" << endl;
+  cout << "Copied  : Different organisms = " << different_orgs_copied << endl;
+
+}

Modified: development/source/main/cPopulation.h
===================================================================
--- development/source/main/cPopulation.h	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/main/cPopulation.h	2007-08-09 03:14:09 UTC (rev 1910)
@@ -135,6 +135,7 @@
   void InjectGenotype(int cell_id, cGenotype* genotype);
   void InjectGenome(int cell_id, const cGenome& genome, int lineage_label);
   void InjectClone(int cell_id, cOrganism& orig_org);
+  void InjectChild(int cell_id, cOrganism& orig_org);
 
   void LineageSetupOrganism(cOrganism* organism, cLineage* lineage, int lin_label, cGenotype* parent_genotype = NULL);
   void CCladeSetupOrganism(cOrganism* organism); 
@@ -243,6 +244,10 @@
   void AddEndSleep(int cellID, int end_time);
  
   tVector<pair<int,int> > getCellSleepLog(int i) { return sleep_log[i]; }
+
+  // Trials and genetic algorithm @JEB
+  void NewTrial();
+  void CompeteOrganisms(int competition_type, int parents_survive, double scaled_time, int dynamic_scaling);
 };
 
 

Modified: development/source/main/cReactionProcess.h
===================================================================
--- development/source/main/cReactionProcess.h	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/main/cReactionProcess.h	2007-08-09 03:14:09 UTC (rev 1910)
@@ -55,6 +55,9 @@
   bool lethal;		 // Lethality of reaction
   cString match_string;	 // Bit string to match if this is a match string reaction
   int inst_id;           // Instruction to be triggered if reaction successful.
+  bool depletable;       // Does completing consume resource?
+                         // (This is not quite redundant with an infinite resource
+                         // because it allows the resource level to be sensed @JEB)
 
   // Resource detection
   cResource * detect;    // Resource Measured
@@ -77,6 +80,7 @@
     , conversion(1.0)
     , lethal(0)
     , inst_id(-1)
+    , depletable(true)
     , detect(NULL)
     , detection_threshold(0.0)
     , detection_error(0.0)
@@ -93,6 +97,7 @@
   cResource* GetProduct() const { return product; }
   double GetConversion() const { return conversion; }
   int GetInstID() const { return inst_id; }
+  bool GetDepletable() const { return depletable; }
   bool GetLethal() const { return lethal; }
   cResource* GetDetect() const { return detect; }
   double GetDetectionThreshold() const { return detection_threshold; }
@@ -108,6 +113,7 @@
   void SetProduct(cResource* _in) { product = _in; }
   void SetConversion(double _in) { conversion = _in; }
   void SetInstID(int _in) { inst_id = _in; }
+  void SetDepletable(bool _in) { depletable = _in; }
   void SetLethal(int _in) { lethal = _in; }
   void SetDetect(cResource* _in) { detect = _in; }
   void SetDetectionThreshold(double _in) { detection_threshold = _in; }

Modified: development/source/main/nReaction.h
===================================================================
--- development/source/main/nReaction.h	2007-08-08 20:47:57 UTC (rev 1909)
+++ development/source/main/nReaction.h	2007-08-09 03:14:09 UTC (rev 1910)
@@ -31,7 +31,8 @@
     PROCTYPE_MULT,
     PROCTYPE_POW,
     PROCTYPE_LIN,
-    PROCTYPE_ENERGY
+    PROCTYPE_ENERGY,
+    PROCTYPE_ENZYME
   };
 }
 




More information about the Avida-cvs mailing list