[avida-cvs] avida CVS commits: /current/source/cpu hardware_4stack.cc hardware_4stack.hh hardware_base.hh hardware_cpu.cc hardware_cpu.hh /current/source/main Makefile.am config.cc config.hh genebank.cc genebank.hh genome.hh population.cc /current/source/viewers view.cc zoom_screen.cc

wisnelaw avida-cvs at alife.org
Thu Jul 31 23:34:28 PDT 2003


wisnelaw		Thu Jul 31 15:34:28 2003 EDT

  Modified files:              
    /avida/current/source/cpu	hardware_4stack.cc hardware_4stack.hh 
                             	hardware_base.hh hardware_cpu.cc 
                             	hardware_cpu.hh 
    /avida/current/source/main	Makefile.am config.cc config.hh 
                              	genebank.cc genebank.hh genome.hh 
                              	population.cc 
    /avida/current/source/viewers	view.cc zoom_screen.cc 
  Log:
  Fixed problems with text viewer and 4-stack CPU.
  Fixed issues with 4-stack "Inject" command.
  Cleaned up hardware_4stack.cc and other 4-Stack CPU related code.
  
  
  
-------------- next part --------------
Index: avida/current/source/cpu/hardware_4stack.cc
diff -u avida/current/source/cpu/hardware_4stack.cc:1.10 avida/current/source/cpu/hardware_4stack.cc:1.11
--- avida/current/source/cpu/hardware_4stack.cc:1.10	Wed Jul 16 19:36:54 2003
+++ avida/current/source/cpu/hardware_4stack.cc	Thu Jul 31 15:34:27 2003
@@ -450,6 +450,7 @@
   // timestep, adjust the number of instructions executed accordingly.
   //const int num_inst_exec = (cConfig::GetThreadSlicingMethod() == 1) ?
   //  GetNumThreads() : 1;
+
   const int num_inst_exec = int(slice_array[GetNumThreads()]+ inst_remainder);
   inst_remainder = slice_array[GetNumThreads()] + inst_remainder - num_inst_exec;
   
@@ -960,52 +961,91 @@
   return temp_head;
 }
 
-
-int cHardware4Stack::Inject(const cCodeLabel & in_label, const cGenome & injection)
+// This is the code run by the INFECTED organism.  Its function is to SPREAD infection.
+bool cHardware4Stack::Inject_Parasite(int mem_space_used, double mut_multiplier)
 {
-  // Make sure the genome will be below max size after injection.
+  const int end_pos = GetHead(HEAD_WRITE).GetPosition();
 
-  int target_mem_space = 2; //TEMPORARY!!! -law
-  const int new_size = injection.GetSize() + GetMemory(target_mem_space).GetSize();
+  // Make sure the creature will still be above the minimum size,
+  if (end_pos <= 0) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
+    return false; // (inject fails)
+  }
+  
+  if (end_pos < MIN_CREATURE_SIZE) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: new size too small");
+    return false; // (inject fails)
+  }
+
+  GetMemory(mem_space_used).Resize(end_pos);
+  cCPUMemory injected_code = GetMemory(mem_space_used);
 
-  if (new_size > MAX_CREATURE_SIZE) return 1; // (inject fails)
+  Inject_DoMutations(mut_multiplier, injected_code);
 
-  //ALSO TEMPORARY - we should have this match injection templates - law
-  //const int inject_line = FindFullLabel(in_label).GetPosition();
+  int inject_signal = false;
 
-  // Abort if no compliment is found.
-  //if (inject_line == -1) return 2; // (inject fails)
+  //************* CALL GOES HERE ******************//
+  // spin around randomly (caution: possible organism dizziness)
+  const int num_neighbors = organism->GetNeighborhoodSize();
+  for(unsigned int i=0; i<g_random.GetUInt(num_neighbors); i++)
+    organism->Rotate(1);
 
-  // Inject the code! /****/ for right now the only injection point will be the
-  // first address in a memory space. -law /***/
-  InjectCode(injection, target_mem_space);//inject_line+1);
+  // If we don't have a host, stop here.
+  cOrganism * host_organism = organism->GetNeighbor();
+  
+ 
+  if(host_organism!=NULL)
+    {
+      inject_signal = host_organism->GetHardware().Inject_Host(GetLabel(), injected_code);
+    }
+ 
+  //************** CALL ENDS HERE ******************//
 
-  return 0; // (inject succeeds!)
+  //reset the memory space which was injected
+  GetMemory(mem_space_used)=cGenome(ConvertToInstruction(mem_space_used)); 
+
+  for(int x=0; x<NUM_HEADS; x++)
+    {
+      GetHead(x).Reset(IP().GetMemSpace(), this);
+    }
+
+  for(int x=0; x<NUM_LOCAL_STACKS; x++)
+    {
+      Stack(x).Clear();
+    }
+  
+  AdvanceIP() = false;
+  
+  return inject_signal;
 }
 
-void cHardware4Stack::InjectCode(const cGenome & inject_code, const int in_mem_space)
+//This is the code run by the TARGET of an injection.  This RECIEVES the infection.
+bool cHardware4Stack::Inject_Host(const cCodeLabel & in_label, const cGenome & inject_code)
 {
-  assert(in_mem_space >=0 && in_mem_space < 4);
-  //assert(line_num >= 0);
-  //assert(line_num <= memory_array[0].GetSize());
-  assert(GetMemory(in_mem_space).GetSize() + inject_code.GetSize() < MAX_CREATURE_SIZE);
+  // Make sure the genome will be below max size after injection.
+
+  // xxxTEMPORARYxxx - we should have this match injection templates.  For now it simply 
+  // makes sure the target_mem_space (hardcoded to 2) is empty. - law
+  int target_mem_space = 2; 
+  if(!(isEmpty(target_mem_space)))
+    return false;
 
+  assert(target_mem_space >=0 && target_mem_space < 4);
+  
   if(ForkThread()) {
     // Inject the new code
-    cCPUMemory oldcode = GetMemory(in_mem_space);
-    GetMemory(in_mem_space) = inject_code;
-    GetMemory(in_mem_space).Resize(inject_code.GetSize() + oldcode.GetSize());
+    cCPUMemory oldcode = GetMemory(target_mem_space);
+    GetMemory(target_mem_space) = inject_code;
+    GetMemory(target_mem_space).Resize(inject_code.GetSize() + oldcode.GetSize());
 
+    // Copies previous instructions to the end of the injected code.
     // Is there a faster way to do this?? -law
     for(int x=0; x<oldcode.GetSize(); x++)
-      GetMemory(in_mem_space)[inject_code.GetSize()+x] = oldcode[x];
-
-    //const int inject_size = inject_code.GetSize();
-    //memory_array[0].Insert(line_num, inject_code);
+      GetMemory(target_mem_space)[inject_code.GetSize()+x] = oldcode[x];
   
     // Set instruction flags on the injected code
     for (int i = 0; i < inject_code.GetSize(); i++) {
-      memory_array[in_mem_space].FlagInjected(i) = true;
+      memory_array[target_mem_space].FlagInjected(i) = true;
     }
     organism->GetPhenotype().IsModified() = true;
     
@@ -1013,22 +1053,22 @@
     
     cur_thread=GetNumThreads()-1;
     
-    for(int i=0; i<cur_thread; i++)
-      {
-	for(int j=0; j<NUM_HEADS; j++)
-	  {
-	    if(threads[i].heads[j].GetMemSpace()==in_mem_space)
-	      threads[i].heads[j].Jump(inject_code.GetSize());
-	  }
+    for(int i=0; i<cur_thread; i++) {
+      for(int j=0; j<NUM_HEADS; j++) {
+	if(threads[i].heads[j].GetMemSpace()==target_mem_space)
+	  threads[i].heads[j].Jump(inject_code.GetSize());
       }
+    }
     
     for (int i=0; i < NUM_HEADS; i++) {    
-      GetHead(i).Reset(in_mem_space, this);
+      GetHead(i).Reset(target_mem_space, this);
     }
     for (int i=0; i < NUM_LOCAL_STACKS; i++) {
       Stack(i).Clear();
     }
   }
+
+  return true; // (inject succeeds!)
 }
 
 void cHardware4Stack::Mutate(int mut_point)
@@ -1391,14 +1431,6 @@
   // Make sure the organism is okay with dividing now...
   if (organism->Divide_CheckViable() == false) return false; // (divide fails)
 
-  //mal_active=true;
-
-  // If required, make sure an allocate has occured.
-  //if (cConfig::GetRequireAllocate() && mal_active == false) {
-  // Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR, "Must allocate before divide");
-  //return false; //  (divide fails)
-  //}
-
   // Make sure that neither parent nor child will be below the minimum size.
 
   const int genome_size = organism->GetGenome().GetSize();
@@ -1412,13 +1444,6 @@
     return false; // (divide fails)
   }
 
-  //This is unneccesary...Parent size cannot change
-  //if (parent_size < min_size || parent_size > max_size) {
-  //  Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
-  //  cStringUtil::Stringf("Invalid post-divide length (%d)",parent_size));
-  //return false; // (divide fails)
-  //}
-
   // Count the number of lines executed in the parent, and make sure the
   // specified fraction has been reached.
 
@@ -1570,6 +1595,118 @@
   }
 }
 
+void cHardware4Stack::Inject_DoMutations(double mut_multiplier, cCPUMemory & injected_code)
+{
+  //sCPUStats & cpu_stats = organism->CPUStats();
+  //cCPUMemory & child_genome = organism->ChildGenome();
+  
+  organism->GetPhenotype().SetDivType(mut_multiplier);
+
+  // Divide Mutations
+  if (organism->TestDivideMut()) {
+    const UINT mut_line = g_random.GetUInt(injected_code.GetSize());
+    injected_code[mut_line] = GetRandomInst();
+    //cpu_stats.mut_stats.divide_mut_count++;
+  }
+
+  // Divide Insertions
+  if (organism->TestDivideIns() && injected_code.GetSize() < MAX_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(injected_code.GetSize() + 1);
+    injected_code.Insert(mut_line, GetRandomInst());
+    //cpu_stats.mut_stats.divide_insert_mut_count++;
+  }
+
+  // Divide Deletions
+  if (organism->TestDivideDel() && injected_code.GetSize() > MIN_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(injected_code.GetSize());
+    // if( injected_code.FlagCopied(mut_line) == true) copied_size_change--;
+    injected_code.Remove(mut_line);
+    //cpu_stats.mut_stats.divide_delete_mut_count++;
+  }
+
+  // Divide Mutations (per site)
+  if(organism->GetDivMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(injected_code.GetSize(), 
+				   	   organism->GetDivMutProb() / mut_multiplier);
+    // If we have lines to mutate...
+    if( num_mut > 0 ){
+      for (int i = 0; i < num_mut; i++) {
+	int site = g_random.GetUInt(injected_code.GetSize());
+	injected_code[site]=GetRandomInst();
+	//cpu_stats.mut_stats.div_mut_count++;
+      }
+    }
+  }
+
+
+  // Insert Mutations (per site)
+  if(organism->GetInsMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(injected_code.GetSize(),
+					   organism->GetInsMutProb());
+    // If would make creature to big, insert up to MAX_CREATURE_SIZE
+    if( num_mut + injected_code.GetSize() > MAX_CREATURE_SIZE ){
+      num_mut = MAX_CREATURE_SIZE - injected_code.GetSize();
+    }
+    // If we have lines to insert...
+    if( num_mut > 0 ){
+      // Build a list of the sites where mutations occured
+      static int mut_sites[MAX_CREATURE_SIZE];
+      for (int i = 0; i < num_mut; i++) {
+	mut_sites[i] = g_random.GetUInt(injected_code.GetSize() + 1);
+      }
+      // Sort the list
+      qsort( (void*)mut_sites, num_mut, sizeof(int), &IntCompareFunction );
+      // Actually do the mutations (in reverse sort order)
+      for(int i = num_mut-1; i >= 0; i--) {
+	injected_code.Insert(mut_sites[i], GetRandomInst());
+	//cpu_stats.mut_stats.insert_mut_count++;
+      }
+    }
+  }
+
+
+  // Delete Mutations (per site)
+  if( organism->GetDelMutProb() > 0 ){
+    int num_mut = g_random.GetRandBinomial(injected_code.GetSize(),
+					   organism->GetDelMutProb());
+    // If would make creature too small, delete down to MIN_CREATURE_SIZE
+    if (injected_code.GetSize() - num_mut < MIN_CREATURE_SIZE) {
+      num_mut = injected_code.GetSize() - MIN_CREATURE_SIZE;
+    }
+
+    // If we have lines to delete...
+    for (int i = 0; i < num_mut; i++) {
+      int site = g_random.GetUInt(injected_code.GetSize());
+      // if (injected_code.FlagCopied(site) == true) copied_size_change--;
+      injected_code.Remove(site);
+      //cpu_stats.mut_stats.delete_mut_count++;
+    }
+  }
+
+  // Mutations in the parent's genome
+  if (organism->GetParentMutProb() > 0) {
+    for (int i = 0; i < GetMemory(0).GetSize(); i++) {
+      if (organism->TestParentMut()) {
+	GetMemory(0)[i] = GetRandomInst();
+	//cpu_stats.mut_stats.parent_mut_line_count++;
+      }
+    }
+  }
+
+  /*
+  // Count up mutated lines
+  for(int i = 0; i < GetMemory(0).GetSize(); i++){
+    if (GetMemory(0).FlagPointMut(i) == true) {
+      cpu_stats.mut_stats.point_mut_line_count++;
+    }
+  }
+  for(int i = 0; i < injected_code.GetSize(); i++){
+    if( injected_code.FlagCopyMut(i) == true) {
+      cpu_stats.mut_stats.copy_mut_line_count++;
+    }
+    }*/
+}
+
 
 // test whether the offspring creature contains an advantageous mutation.
 void cHardware4Stack::Divide_TestFitnessMeasures()
@@ -1639,10 +1776,6 @@
   // for right now -law
   if(IP().GetMemSpace()!=0)
     return false;
-  //if(GetMemory(mem_space_used).GetSize() != GetMemory(IP().GetMemSpace()).GetSize())
-  //int q=1;
-
-  //assert(GetMemory(mem_space_used).GetSize() == GetMemory(IP().GetMemSpace()).GetSize());
 
   // Make sure this divide will produce a viable offspring.
   if(!Divide_CheckViable(GetMemory(IP().GetMemSpace()).GetSize(), 
@@ -1654,9 +1787,6 @@
   cGenome & child_genome = organism->ChildGenome();
   GetMemory(mem_space_used).Resize(write_head_pos);
   child_genome = GetMemory(mem_space_used);
-  //GetMemory(mem_space_used).Resize(1);
-  GetMemory(mem_space_used)=cGenome(ConvertToInstruction(mem_space_used)); 
-  //GetMemory(mem_space_used)[0].SetOp(mem_space_used);
 
   // Handle Divide Mutations...
   Divide_DoMutations(mut_multiplier);
@@ -1675,9 +1805,16 @@
 
   bool parent_alive = organism->ActivateDivide();
 
-  // I am still iffy about how we want to reset organisms after divide. -law
+  //reset the memory of the memory space that has been divided off
+  GetMemory(mem_space_used)=cGenome(ConvertToInstruction(mem_space_used)); 
+
+  // 3 Division Methods:
+  // 1) DIVIDE_METHOD_OFFSPRING - Create a child, leave parent state untouched.
+  // 2) DIVIDE_METHOD_SPLIT - Create a child, completely reset state of parent.
+  // 3) DIVIDE_METHOD_BIRTH - Create a child, reset state of parent's current thread.
   if(parent_alive && !(cConfig::GetDivideMethod() == DIVIDE_METHOD_OFFSPRING))
     {
+      
       if(cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT)
 	{
 	  //this will wipe out all parasites on a divide.
@@ -1837,15 +1974,8 @@
 //14
 bool cHardware4Stack::Inst_Divide()
 {
-  //return Inst_HeadDivideMut(1);
   int mem_space_used = GetHead(HEAD_WRITE).GetMemSpace();
-  //if(GetMemory(mem_space_used).GetSize()==GetMemory(0).GetSize()+1)
-  //  {
-  //    int x=0;
-  //  }
   int mut_multiplier = 1;
-  //if(mem_space_used==0)
-  //  mem_space_used++;
 
   return Divide_Main(mem_space_used, mut_multiplier);
 }
@@ -2219,102 +2349,13 @@
 
 bool cHardware4Stack::Inst_Inject()
 {
-  const int mem_space_used = GetHead(HEAD_WRITE).GetMemSpace();  //FindModifiedStack(STACK_DX);
-  const int end_pos = GetHead(HEAD_WRITE).GetPosition();
-  
-  /*AdjustHeads();
-  const int start_pos = GetHead(HEAD_READ).GetPosition();
-  const int end_pos = GetHead(HEAD_WRITE).GetPosition();
-  const int inject_size = end_pos - start_pos;
-  */
-
-  // Make sure the creature will still be above the minimum size,
-  if (end_pos <= 0) {
-    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
-    return false; // (inject fails)
-  }
-  
-  if (end_pos < MIN_CREATURE_SIZE) {
-    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: new size too small");
-    return false; // (inject fails)
-  }
-
-  GetMemory(mem_space_used).Resize(end_pos);
-
-  /*
-  // Since its legal to cut out the injected piece, do so.
-  cGenome inject_code( cGenomeUtil::Crop(GetMemory(), start_pos, end_pos) );
-  GetMemory().Remove(start_pos, inject_size);
-  */
-
-  // spin around randomly (caution: possible organism dizziness)
-  const int num_neighbors = organism->GetNeighborhoodSize();
-  for(int i=0; i<g_random.GetUInt(num_neighbors); i++)
-    organism->Rotate(1);
-
-  // If we don't have a host, stop here.
-  cOrganism * host_organism = organism->GetNeighbor();
-  
-  //if (host_organism == NULL) 
-  //  {
-  //  GetMemory(mem_space_used)=cGenome(ConvertToInstruction(mem_space_used));
-  //  return false;
-  //}
-
-  /*
-  // Scan for the label to match...
-  ReadLabel();
-
-  // If there is no label, abort.
-  if (GetLabel().GetSizhe() == 0) {
-    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: label required");
-    return false; // (inject fails)
-  }
-
-  // Search for the label in the host...
-  GetLabel().Rotate(2, NUM_NOPS_4STACK);
-  */
-  int inject_signal = false;
-  int target_mem_space=2;
-  //cHardware4Stack & target_hardware = (cHardware4Stack &)host_organism->GetHardware();
-  if(host_organism!=NULL && ((cHardware4Stack &)host_organism->GetHardware()).isEmpty(target_mem_space))
-    {
-      inject_signal = host_organism->GetHardware().Inject(GetLabel(), GetMemory(mem_space_used));
-    }
-
-  //reset the memory space which was injected
-  GetMemory(mem_space_used)=cGenome(ConvertToInstruction(mem_space_used)); 
+  const int mem_space_used = GetHead(HEAD_WRITE).GetMemSpace(); 
+  double mut_multiplier = 1;
 
-  for(int x=0; x<NUM_HEADS; x++)
-    {
-      GetHead(x).Reset(IP().GetMemSpace(), this);
-    }
+  return Inject_Parasite(mem_space_used, mut_multiplier);
+}
 
-  for(int x=0; x<NUM_LOCAL_STACKS; x++)
-    {
-      Stack(x).Clear();
-    }
-  
-  AdvanceIP() = false;
-  /*
-  const int inject_signal =
-    host_organism->GetHardware().Inject(GetLabel(), inject_code);
-  if (inject_signal == 1) {
-    Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: host too large.");
-    return false; // Inject failed.
-  }
-  if (inject_signal == 2) {
-    Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: target not in host.");
-    return false; // Inject failed.
-  }
 
-  // Set the relevent flags.
-  organism->GetPhenotype().IsModifier() = true;
-  */
-  
-  
-  return inject_signal;
-}
 
 /*
 bool cHardware4Stack::Inst_InjectRand()
Index: avida/current/source/cpu/hardware_4stack.hh
diff -u avida/current/source/cpu/hardware_4stack.hh:1.6 avida/current/source/cpu/hardware_4stack.hh:1.7
--- avida/current/source/cpu/hardware_4stack.hh:1.6	Wed Jul 16 19:36:54 2003
+++ avida/current/source/cpu/hardware_4stack.hh	Thu Jul 31 15:34:27 2003
@@ -148,12 +148,15 @@
 
   // --------  Stack Manipulation...  --------
   inline void StackFlip();
-  inline int GetStack(int depth=0, int stack_id=-1) const;
+  inline int GetStack(int depth=0, int stack_id=-1, int in_thread=-1) const;
   inline void StackClear();
   inline void SwitchStack();
   cString GetActiveStackID(int stackID) const;
-  inline cCPUStack & Stack(int stack_id); //retrieves appropriate stack
+  //retrieves appropriate stack
+  inline cCPUStack & Stack(int stack_id); 
   inline const cCPUStack & Stack(int stack_id) const;
+  inline cCPUStack & Stack(int stack_id, int in_thread);
+  inline const cCPUStack & Stack(int stack_id, int in_thread) const;
 
   // --------  Tasks & IO  --------
   tBuffer<int> & GetInputBuffer() { return threads[cur_thread].input_buf; }
@@ -166,9 +169,16 @@
   { threads[cur_thread].cur_head = (UCHAR) new_head; }
 
   int GetCurHead() const { return threads[cur_thread].cur_head; }
+  
   const c4StackHead & GetHead(int head_id) const
-    { return threads[cur_thread].heads[head_id]; }
-  c4StackHead & GetHead(int head_id) { return threads[cur_thread].heads[head_id];}
+  { return threads[cur_thread].heads[head_id]; }
+  c4StackHead & GetHead(int head_id) 
+  { return threads[cur_thread].heads[head_id];}
+  
+  const c4StackHead & GetHead(int head_id, int thread) const
+  { return threads[thread].heads[head_id]; }
+  c4StackHead & GetHead(int head_id, int thread) 
+  { return threads[thread].heads[head_id];}
 
   const c4StackHead & GetActiveHead() const { return GetHead(GetCurHead()); }
   c4StackHead & GetActiveHead() { return GetHead(GetCurHead()); }
@@ -179,6 +189,12 @@
     { return threads[cur_thread].heads[HEAD_IP]; }
   inline c4StackHead & IP() { return threads[cur_thread].heads[HEAD_IP]; }
 
+  inline const c4StackHead & IP(int thread) const
+  { return threads[thread].heads[HEAD_IP]; }
+  inline c4StackHead & IP(int thread) 
+  { return threads[thread].heads[HEAD_IP]; }
+
+
   inline const bool & AdvanceIP() const
     { return threads[cur_thread].advance_ip; }
   inline bool & AdvanceIP() { return threads[cur_thread].advance_ip; }
@@ -236,9 +252,9 @@
   c4StackHead FindFullLabel(const cCodeLabel & in_label);
 
   int GetType() const { return HARDWARE_TYPE_CPU_4STACK; }
-  int Inject(const cCodeLabel & in_label, const cGenome & injection);
+  bool Inject_Parasite(int mem_space_used, double mut_multiplier);
+  bool Inject_Host(const cCodeLabel & in_label, const cGenome & injection);
   int InjectThread(const cCodeLabel &, const cGenome &) { return -1; }
-  void InjectCode(const cGenome & injection, const int line_num);
   void Mutate(const int mut_point);
   int PointMutate(const double mut_rate);
   int FindFirstEmpty();
@@ -281,6 +297,7 @@
   bool Divide_Main(const int mem_space_used, double mut_multiplier=1);
   bool Divide_CheckViable(const int parent_size, const int child_size, const int mem_space);
   void Divide_DoMutations(double mut_multiplier=1);
+  void Inject_DoMutations(double mut_multiplier, cCPUMemory & injected_code);
   void Divide_TestFitnessMeasures();
 
   bool HeadCopy_ErrorCorrect(double reduction);
@@ -422,17 +439,14 @@
   }
 }*/
 
-inline int cHardware4Stack::GetStack(int depth, int stack_id) const
+inline int cHardware4Stack::GetStack(int depth, int stack_id, int in_thread) const
 {
-  //int value = 0;
-
   if(stack_id<0 || stack_id>NUM_STACKS) stack_id=0;
-
-  int value = Stack(stack_id).Get(depth);
-  return value; //Stack(stack_id).Get(depth);
-  //threads[cur_thread].Stack(stack_id).Get(depth);
-
-  //return value;
+  
+  if(in_thread==-1)
+    in_thread=cur_thread;
+  
+  return Stack(stack_id, in_thread).Get(depth);
 }
 
 //inline void cHardware4Stack::StackClear()
@@ -474,4 +488,31 @@
   else
     return global_stacks[stack_id % NUM_LOCAL_STACKS];
 }
+
+inline cCPUStack& cHardware4Stack::Stack(int stack_id, int in_thread) 
+{
+  if(stack_id >= NUM_STACKS)
+      stack_id=0;
+  if(in_thread >= threads.GetSize())
+      in_thread=cur_thread;
+
+  if(stack_id < NUM_LOCAL_STACKS)
+    return threads[in_thread].local_stacks[stack_id];
+  else
+    return global_stacks[stack_id % NUM_LOCAL_STACKS];
+}
+
+inline const cCPUStack& cHardware4Stack::Stack(int stack_id, int in_thread) const 
+{
+  if(stack_id >= NUM_STACKS)
+      stack_id=0;
+  if(in_thread >= threads.GetSize())
+      in_thread=cur_thread;
+
+  if(stack_id < NUM_LOCAL_STACKS)
+    return threads[in_thread].local_stacks[stack_id];
+  else
+    return global_stacks[stack_id % NUM_LOCAL_STACKS];
+}
+
 #endif
Index: avida/current/source/cpu/hardware_base.hh
diff -u avida/current/source/cpu/hardware_base.hh:1.18 avida/current/source/cpu/hardware_base.hh:1.19
--- avida/current/source/cpu/hardware_base.hh:1.18	Thu Jun  5 13:14:40 2003
+++ avida/current/source/cpu/hardware_base.hh	Thu Jul 31 15:34:27 2003
@@ -52,7 +52,7 @@
 
   // --------  Other Virtual Tools --------
   virtual int GetType() const = 0;
-  virtual int Inject(const cCodeLabel & in_label,
+  virtual bool Inject_Host(const cCodeLabel & in_label,
 		      const cGenome & injection) = 0;
   virtual int InjectThread(const cCodeLabel & in_label,
 			   const cGenome & injection) = 0;
Index: avida/current/source/cpu/hardware_cpu.cc
diff -u avida/current/source/cpu/hardware_cpu.cc:1.53 avida/current/source/cpu/hardware_cpu.cc:1.54
--- avida/current/source/cpu/hardware_cpu.cc:1.53	Wed Jul 16 19:36:54 2003
+++ avida/current/source/cpu/hardware_cpu.cc	Thu Jul 31 15:34:27 2003
@@ -1090,22 +1090,22 @@
 }
 
 
-int cHardwareCPU::Inject(const cCodeLabel & in_label, const cGenome & injection)
+bool cHardwareCPU::Inject_Host(const cCodeLabel & in_label, const cGenome & injection)
 {
   // Make sure the genome will be below max size after injection.
 
   const int new_size = injection.GetSize() + GetMemory().GetSize();
-  if (new_size > MAX_CREATURE_SIZE) return 1; // (inject fails)
+  if (new_size > MAX_CREATURE_SIZE) return false; // (inject fails)
 
   const int inject_line = FindFullLabel(in_label).GetPosition();
 
   // Abort if no compliment is found.
-  if (inject_line == -1) return 2; // (inject fails)
+  if (inject_line == -1) return false; // (inject fails)
 
   // Inject the code!
   InjectCode(injection, inject_line+1);
 
-  return 0; // (inject succeeds!)
+  return true; // (inject succeeds!)
 }
 
 int cHardwareCPU::InjectThread(const cCodeLabel & in_label, const cGenome & injection)
@@ -2763,8 +2763,8 @@
   // Search for the label in the host...
   GetLabel().Rotate(1, NUM_NOPS);
 
-  const int inject_signal =
-    host_organism->GetHardware().Inject(GetLabel(), inject_code);
+  const bool inject_signal =
+    host_organism->GetHardware().Inject_Host(GetLabel(), inject_code);
   if (inject_signal == 1) {
     Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: host too large.");
     return false; // Inject failed.
@@ -2777,7 +2777,7 @@
   // Set the relevent flags.
   organism->GetPhenotype().IsModifier() = true;
 
-  return true;
+  return inject_signal;
 }
 
 
Index: avida/current/source/cpu/hardware_cpu.hh
diff -u avida/current/source/cpu/hardware_cpu.hh:1.32 avida/current/source/cpu/hardware_cpu.hh:1.33
--- avida/current/source/cpu/hardware_cpu.hh:1.32	Wed Jul 16 19:36:54 2003
+++ avida/current/source/cpu/hardware_cpu.hh	Thu Jul 31 15:34:27 2003
@@ -216,7 +216,7 @@
   cCPUHead FindFullLabel(const cCodeLabel & in_label);
 
   int GetType() const { return HARDWARE_TYPE_CPU_ORIGINAL; }
-  int Inject(const cCodeLabel & in_label, const cGenome & injection);
+  bool Inject_Host(const cCodeLabel & in_label, const cGenome & injection);
   int InjectThread(const cCodeLabel & in_label, const cGenome & injection);
   void InjectCode(const cGenome & injection, const int line_num);
   void InjectCodeThread(const cGenome & injection, const int line_num);
Index: avida/current/source/main/Makefile.am
diff -u avida/current/source/main/Makefile.am:1.29 avida/current/source/main/Makefile.am:1.30
--- avida/current/source/main/Makefile.am:1.29	Thu Jul 17 10:40:55 2003
+++ avida/current/source/main/Makefile.am	Thu Jul 31 15:34:27 2003
@@ -43,6 +43,7 @@
     mutations.hh		mutations.cc		\
     org_message.hh      org_message.cc          \
     organism.hh		organism.cc		\
+    parasite.hh		parasite.cc		\
     phenotype.hh		phenotype.cc		\
     population.hh		population.cc		\
     population_cell.hh	population_cell.cc	\
Index: avida/current/source/main/config.cc
diff -u avida/current/source/main/config.cc:1.58 avida/current/source/main/config.cc:1.59
--- avida/current/source/main/config.cc:1.58	Fri Jun  6 12:46:23 2003
+++ avida/current/source/main/config.cc	Thu Jul 31 15:34:27 2003
@@ -46,7 +46,7 @@
 int cConfig::num_instructions;
 int cConfig::hardware_type;
 int cConfig::max_cpu_threads;
-int cConfig::thread_slicing_method;
+double cConfig::thread_slicing_method;
 int cConfig::size_merit_method;
 int cConfig::base_size_merit;
 int cConfig::task_merit_method;
@@ -154,7 +154,7 @@
   repro_group->Add(alloc_method, "0", "ALLOC_METHOD",
 		   "0 = Allocated space is set to default instruction.\n1 = Set to section of dead genome (Necrophilia)\n2 = Allocated space is set to random instruction.");
   repro_group->Add(divide_method, "1", "DIVIDE_METHOD",
-		   "0 = Divide leaves state of mother untouched.\n1 = Divide resets state of mother\n    (after the divide, we have 2 children)");
+		   "0 = Divide leaves state of mother untouched.\n1 = Divide resets state of mother (after the divide, we have 2 children)\n2 = Divide resets state of current thread only(does not touch possible parasite threads)");
   repro_group->Add(generation_inc_method, "1", "GENERATION_INC_METHOD",
 		   "0 = Only the generation of the child is\n    increased on divide.\n1 = Both the generation of the mother and child are\n    increased on divide (good with DIVIDE_METHOD 1).");
 
@@ -239,7 +239,7 @@
   time_group->Add(max_cpu_threads, "1", "MAX_CPU_THREADS",
 		  "Number of Threads a CPU can spawn");
   time_group->Add(thread_slicing_method, "0", "THREAD_SLICING_METHOD",
-		  "0 = One thread executed per time slice.\n1 = All threads executed each time slice.");
+		  "Formula for and organism's thread slicing -> 1 + (num_organism_threads-1) * THREAD_SLICING_METHOD.\n0 = One thread executed per time slice.\n1 = All threads executed each time slice.\n");
   time_group->Add(max_label_exe_size, "1", "MAX_LABEL_EXE_SIZE",
 		  "Max nops marked as executed when labels are used");
   time_group->Add(base_size_merit, "0", "BASE_SIZE_MERIT",
Index: avida/current/source/main/config.hh
diff -u avida/current/source/main/config.hh:1.53 avida/current/source/main/config.hh:1.54
--- avida/current/source/main/config.hh:1.53	Thu Jul 17 11:32:27 2003
+++ avida/current/source/main/config.hh	Thu Jul 31 15:34:27 2003
@@ -187,7 +187,7 @@
   static int num_instructions;
   static int hardware_type;
   static int max_cpu_threads;
-  static int thread_slicing_method;
+  static double thread_slicing_method;
 
   // Merit info
   static int size_merit_method;
@@ -310,7 +310,7 @@
   static int GetNumInstructions() { return num_instructions; }
   static int GetHardwareType() { return hardware_type; }
   static int GetMaxCPUThreads() { return max_cpu_threads; }
-  static int GetThreadSlicingMethod() { return thread_slicing_method; }
+  static double GetThreadSlicingMethod() { return thread_slicing_method; }
 
   static int GetSizeMeritMethod() { return size_merit_method; }
   static int GetBaseSizeMerit()  { return base_size_merit; }
Index: avida/current/source/main/genebank.cc
diff -u avida/current/source/main/genebank.cc:1.30 avida/current/source/main/genebank.cc:1.31
--- avida/current/source/main/genebank.cc:1.30	Sat May 17 02:48:08 2003
+++ avida/current/source/main/genebank.cc	Thu Jul 31 15:34:27 2003
@@ -13,6 +13,7 @@
 #include "genotype.hh"
 #include "config.hh"
 #include "stats.hh"
+#include "parasite.hh"
 
 #include "../cpu/test_util.hh"
 
@@ -690,6 +691,7 @@
 
   genotype_control = new cGenotypeControl(*this);
   species_control  = new cSpeciesControl(*this);
+  parasite_control = new cParasiteControl(*this);
 
 }
 
@@ -697,6 +699,7 @@
 {
   delete genotype_control;
   delete species_control;
+  delete parasite_control;
 }
 
 void cGenebank::UpdateReset()
@@ -1217,9 +1220,9 @@
   return total;
 }
 
-void cGenebank::SpeciesTest(char * message, cGenotype & genotype)
-{
-  cSpecies * cur_species = genotype.GetSpecies();
+//void cGenebank::SpeciesTest(char * message, cGenotype & genotype)
+//{
+  //cSpecies * cur_species = genotype.GetSpecies();
 
 //    if (cur_species) {
 //      g_debug.Comment("UD %d: %s on genotype [%d] (size %d) of species [%d]",
@@ -1236,4 +1239,624 @@
 //  	    cur_species->GetID(), cur_species->GetNumGenotypes(),
 //  	    cur_species->GetNumThreshold(), cur_species->GetQueueType());
 //    }
+//}
+
+void cGenebank::AddParasite(cParasite * in_parasite, int in_list_num)
+{
+  assert( in_parasite != 0 );
+  
+  if ( in_list_num < 0 )
+    in_list_num = FindCRC(in_parasite->GetGenome()) % GENOTYPE_HASH_SIZE;
+  
+  active_parasites[in_list_num].Insert(*in_parasite);
+  parasite_control->Insert(*in_parasite);
+  //stats.AddParasite(in_parasite->GetID());
+
+  // Speciation... If we are creating a new parasite here, we must
+  // initilize it to the species of its parent parasite.
+
+  cSpecies * parent_species = NULL;
+  if ( in_parasite->GetParentParasite() != NULL) {
+    parent_species = in_parasite->GetParentParasite()->GetSpecies();
+  }
+
+  //in_parasite->SetSpecies(parent_species);
+  //if (parent_species != NULL) parent_species->AddParasite();
+}
+
+
+cParasite * cGenebank::AddParasite(const cGenome & in_genome,
+				   cParasite * parent_parasite)
+{
+  int list_num = FindCRC(in_genome) % GENOTYPE_HASH_SIZE;
+  cParasite * found_parasite;
+
+  found_parasite = active_parasites[list_num].Find(in_genome);
+
+  if (!found_parasite) {
+    found_parasite = new cParasite(stats.GetUpdate());
+    found_parasite->SetGenome(in_genome);
+    found_parasite->SetParent(parent_parasite);
+    
+    AddParasite( found_parasite, list_num );
+    /*
+    active_parasites[list_num].Insert(*found_parasite);
+    parasite_control->Insert(*found_parasite);
+    stats.AddParasite(found_parasite->GetID());
+
+    // Speciation... If we are creating a new parasite here, we must
+    // initilize it to the species of its parent parasite.
+
+    cSpecies * parent_species = NULL;
+    if (parent_parasite != NULL) {
+      parent_species = parent_parasite->GetSpecies();
+    }
+
+    found_parasite->SetSpecies(parent_species);
+    if (parent_species != NULL) parent_species->AddParasite();
+    */
+  }
+
+  return found_parasite;
+}
+
+cParasite * cGenebank::FindParasite(const cGenome & in_genome) const
+{
+  int list_num = FindCRC(in_genome) % GENOTYPE_HASH_SIZE;
+  return active_parasites[list_num].Find(in_genome);
+}
+
+void cGenebank::RemoveParasite(cParasite & in_parasite)
+{
+  // If this parasite is still active, mark it no longer active and
+  // take it out of the hash table so it doesn't have any new organisms
+  // assigned to it.
+
+  if (in_parasite.GetActive() == true) {
+    int list_num = FindCRC(in_parasite.GetGenome()) % GENOTYPE_HASH_SIZE;
+    active_parasites[list_num].Remove(in_parasite);
+    parasite_control->Remove(in_parasite);
+    in_parasite.Deactivate(stats.GetUpdate());
+    if (cConfig::GetTrackMainLineage()) {
+      parasite_control->InsertHistoric(in_parasite);
+    }
+  }
+
+  // If we are tracking the main lineage, we only want to delete a
+  // parasite when all of its decendents have also died out.
+
+  if (cConfig::GetTrackMainLineage()) {
+    // If  there are more offspring parasites, hold off on deletion...
+    if (in_parasite.GetNumOffspringParasites() != 0) return;
+
+    // If this is a dead end, delete it and recurse up...
+    cParasite * parent = in_parasite.GetParentParasite();
+    if (parent != NULL) {
+      parent->RemoveOffspringParasite();
+
+      // Test to see if we need to update the coalescent parasite.
+      const int new_coal = parasite_control->UpdateCoalescent();
+      //stats.SetCoalescentParasiteDepth(new_coal);
+      // cout << "Set coalescent to " << found_gen->GetDepth() << endl;
+
+      if (parent->GetNumOrganisms() == 0) {
+	// Regardless, run RemoveParasite on the parent.
+	RemoveParasite(*parent);
+      }
+    }
+
+    parasite_control->RemoveHistoric(in_parasite);
+  }
+
+  // Handle the relevent statistics...
+  /* stats.RemoveParasite(in_parasite.GetID(),
+	      in_parasite.GetParentID(), in_parasite.GetParentDistance(),
+	      in_parasite.GetDepth(), in_parasite.GetTotalOrganisms(),
+              in_parasite.GetTotalParasites(),
+	      stats.GetUpdate() - in_parasite.GetUpdateBorn(),
+              in_parasite.GetLength());*/
+  //if (in_parasite.GetThreshold()) {
+  //  stats.RemoveThreshold(in_parasite.GetID());
+  //}
+
+
+  // Speciation...  If a Threshold parasite was removed, the position of this
+  // species in the active list will at least shift, and it is possible that
+  // the species is made inactive, or removed all-togeather.  If it is a non-
+  // threshold parasite, then the species will only be effected if this was
+  // the last parasite of that species.
+
+  //cSpecies * cur_species = in_parasite.GetSpecies();
+  /*if (cur_species) {
+
+    // First, re-adjust the species.
+
+    //   cur_species->RemoveParasite();
+
+    // Then, check to see how this species changes if it is a threshold.
+
+    //    if (in_parasite.GetThreshold()) {
+    //  cur_species->RemoveThreshold(in_parasite);
+
+      // If we are out of thresholds, move this species to the inactive
+      // list for now.  Otherwise, just adjust it.
+
+      if (cur_species->GetNumThreshold() == 0) {
+	species_control->SetInactive(*cur_species);
+      }
+      else {
+	species_control->Adjust(*cur_species);
+      }
+    }
+
+    // Finally, remove the species completely if it has no parasites left.
+
+    //if (!cur_species->GetNumParasites()) {
+    //  species_control->SetGarbage(*cur_species);
+    }*/
+  //}
+
+
+  delete &in_parasite;
+}
+
+void cGenebank::ThresholdParasite(cParasite & in_parasite)
+{
+  cSpecies * found_species = NULL;
+
+  in_parasite.SetName( GetLabel(in_parasite.GetLength(),
+				parasite_count[in_parasite.GetLength()]++) );
+  in_parasite.SetThreshold();
+
+  // If speciation is on, assign a species to the parasite now that it is
+  // threshold.
+
+  //if (cConfig::GetSpeciesRecording()) {
+    // Record the old species to know if it changes.
+
+    //cSpecies * old_species = in_parasite.GetSpecies();
+
+    // Determine the "proper" species.
+
+    //found_species = species_control->Find(in_parasite,
+    //				  cConfig::GetSpeciesRecording());
+
+    // If no species was found, create a new one.
+    /*
+    if (!found_species) {
+      found_species = new cSpecies(in_parasite.GetGenome(), stats.GetUpdate());
+      if (in_parasite.GetSpecies())
+	found_species->SetParentID(in_parasite.GetSpecies()->GetID());
+      species_control->SetActive(*found_species);
+      stats.AddSpecies(found_species->GetID());
+
+      // Since this is a new species, see if we should be printing it.
+
+      if (cConfig::GetSpeciesPrint()) {
+	cString filename;
+	filename.Set("genebank/spec-%04d", found_species->GetID());
+	cTestUtil::PrintGenome(in_parasite.GetGenome(), filename,
+			       &in_parasite, stats.GetUpdate());
+			       }
+  
+    else {
+      // If we are not creating a new species, but are adding a threshold
+      // to one which is currently in-active, make sure to move it back to
+      // the active list.
+
+      if (found_species->GetNumThreshold() == 0) {
+	species_control->SetActive(*found_species);
+      }
+    }
+
+    // Now that we know for sure what the species is, and that it is in
+    // the proper list, setup both the species and the parasite.
+
+    in_parasite.SetSpecies(found_species);
+    found_species->AddThreshold(in_parasite);
+
+    // Finally test to see if the species has been changed, and adjust
+    // accordingly.
+
+    if (found_species != old_species) {
+      found_species->AddParasite();
+      if (old_species) {
+	old_species->RemoveParasite();
+	if (old_species->GetNumParasites() == 0)
+	  species_control->SetGarbage(*old_species);
+      }
+    }
+    else {
+      if (found_species->GetNumThreshold() > 1) {
+	species_control->Adjust(*found_species);
+      }
+    }
+  }
+
+  // Do the relevent statistics...
+
+  if (cConfig::GetSpeciesRecording()) {
+    stats.AddThreshold(in_parasite.GetID(), in_parasite.GetName()(),
+			 found_species->GetID());
+  } else {
+    stats.AddThreshold(in_parasite.GetID(), in_parasite.GetName()());
+  }
+
+  // Print the parasite?
+
+  if (cConfig::GetParasitePrint()) {
+    cString filename;
+    filename.Set("genebank/%s", in_parasite.GetName()());
+    cTestUtil::PrintGenome(in_parasite.GetGenome(), filename,
+			   &in_parasite, stats.GetUpdate());
+			   }*/
+}
+
+bool cGenebank::AdjustParasite(cParasite & in_parasite)
+{
+  if (!parasite_control->Adjust(in_parasite)) return false;
+
+  if ((in_parasite.GetNumOrganisms() >= cConfig::GetThreshold() ||
+       &in_parasite == parasite_control->GetBest()) &&
+      !(in_parasite.GetThreshold())) {
+    ThresholdParasite(in_parasite);
+  }
+
+  return true;
+}
+
+/////////////////////
+// cParasiteQueue
+/////////////////////
+
+cParasiteQueue::cParasiteQueue()
+{
+  size = 0;
+  root.SetNext(&root);
+  root.SetPrev(&root);
+}
+
+
+cParasiteQueue::~cParasiteQueue()
+{
+  while (root.GetNext() != &root) {
+    Remove(root.GetNext());
+  }
+}
+
+bool cParasiteQueue::OK()
+{
+  bool result = true;
+  int count = 0;
+
+  for (cParasiteElement * temp_element = root.GetNext();
+       temp_element != &root;
+       temp_element = temp_element->GetNext()) {
+    assert (temp_element->GetNext()->GetPrev() == temp_element);
+    assert (temp_element->GetParasite()->GetID() >= 0);
+
+    count++;
+    assert (count <= size);
+  }
+
+  assert (count == size);
+
+  return result;
+}
+
+void cParasiteQueue::Insert(cParasite & in_parasite)
+{
+  cParasiteElement * new_element = new cParasiteElement(&in_parasite);
+  new_element->SetNext(root.GetNext());
+  new_element->SetPrev(&root);
+  root.GetNext()->SetPrev(new_element);
+  root.SetNext(new_element);
+  size++;
+}
+
+void cParasiteQueue::Remove(cParasite & in_parasite)
+{
+  cParasiteElement * cur_element;
+
+  for (cur_element = root.GetNext();
+       cur_element != &root;
+       cur_element = cur_element->GetNext()) {
+    if (cur_element->GetParasite() == &in_parasite) break;
+  }
+
+  assert (cur_element != &root);
+
+  Remove(cur_element);
+}
+
+void cParasiteQueue::Remove(cParasiteElement * in_element)
+{
+  in_element->GetPrev()->SetNext(in_element->GetNext());
+  in_element->GetNext()->SetPrev(in_element->GetPrev());
+  in_element->SetNext(NULL);
+  in_element->SetPrev(NULL);
+  delete(in_element);
+
+  size--;
+}
+
+cParasite * cParasiteQueue::Find(const cGenome & in_genome) const
+{
+  for (cParasiteElement * cur_element = root.GetNext();
+       cur_element != &root;
+       cur_element = cur_element->GetNext()) {
+    if (cur_element->GetParasite()->GetGenome() == in_genome) {
+      return cur_element->GetParasite();
+    }
+  }
+  return NULL;
+}
+
+///////////////////////
+//  cParasiteControl
+///////////////////////
+
+cParasiteControl::cParasiteControl(cGenebank & in_gb) : genebank(in_gb)
+{
+  size = 0;
+  best = NULL;
+  coalescent = NULL;
+  for (int i = 0; i < GENOTYPE_THREADS; i++) threads[i] = NULL;
+
+  historic_list = NULL;
+  historic_count = 0;
+}
+
+cParasiteControl::~cParasiteControl()
+{
+}
+
+bool cParasiteControl::OK()
+{
+  int ret_value = true;
+
+  // Cycle through the list, making sure all connections are proper, size
+  // is correct, and all parasites are OK().
+
+  cParasite * cur_pos = best;
+  for (int i = 0; i < size; i++) {
+    if (!cur_pos->OK()) ret_value = false;
+    assert (cur_pos->GetNext()->GetPrev() == cur_pos);
+    cur_pos = cur_pos->GetNext();
+  }
+
+  assert (cur_pos == best);
+
+  return ret_value;
+}
+
+void cParasiteControl::Insert(cParasite & in_parasite, cParasite * prev_parasite)
+{
+  if (prev_parasite == NULL) {
+    assert(size == 0); // Destroying a full parasite queue...
+
+    best = &in_parasite;
+    best->SetNext(best);
+    best->SetPrev(best);
+  }
+  else {
+    in_parasite.SetPrev(prev_parasite);
+    in_parasite.SetNext(prev_parasite->GetNext());
+    prev_parasite->SetNext(&in_parasite);
+    in_parasite.GetNext()->SetPrev(&in_parasite);
+  }
+
+  size++;
+}
+
+void cParasiteControl::Remove(cParasite & in_parasite)
+{
+  if (size == 1) {
+    best = NULL;
+  }
+  if (&in_parasite == best) {
+    best = best->GetNext();
+  }
+
+  in_parasite.GetNext()->SetPrev(in_parasite.GetPrev());
+  in_parasite.GetPrev()->SetNext(in_parasite.GetNext());
+  in_parasite.SetNext(NULL);
+  in_parasite.SetPrev(NULL);
+
+  size--;
+}
+
+void cParasiteControl::RemoveHistoric(cParasite & in_parasite)
+{
+  if (historic_count == 1) {
+    historic_list = NULL;
+  }
+  if (&in_parasite == historic_list) {
+    historic_list = historic_list->GetNext();
+  }
+
+  in_parasite.GetNext()->SetPrev(in_parasite.GetPrev());
+  in_parasite.GetPrev()->SetNext(in_parasite.GetNext());
+  in_parasite.SetNext(NULL);
+  in_parasite.SetPrev(NULL);
+
+  historic_count--;
+}
+
+void cParasiteControl::InsertHistoric(cParasite & in_parasite)
+{
+  if (historic_count == 0) {
+    in_parasite.SetNext(&in_parasite);
+    in_parasite.SetPrev(&in_parasite);
+  }
+  else {
+    in_parasite.SetPrev(historic_list->GetPrev());
+    in_parasite.SetNext(historic_list);
+    historic_list->GetPrev()->SetNext(&in_parasite);
+    historic_list->SetPrev(&in_parasite);
+  }
+
+  historic_list = &in_parasite;
+  historic_count++;
+}
+
+
+int cParasiteControl::UpdateCoalescent()
+{
+  // Test to see if any updating needs to be done...
+  // Don't update active coalescent parasite, or if there is more than
+  // one offspring.
+  if (coalescent != NULL &&
+      (coalescent->GetNumOrganisms() > 0 ||
+       coalescent->GetNumOffspringParasites() > 1)) {
+    return coalescent->GetDepth();
+  }
+
+  // If there is no best, there is nothing to search through...
+  if (best == NULL) return -1;
+
+  // Find the new point...
+  cParasite * test_gen = best;
+  cParasite * found_gen = best;
+  cParasite * parent_gen = best->GetParentParasite();
+
+  while (parent_gen != NULL) {
+    // See if this parasite should be the new found parasite...
+    if (test_gen->GetNumOrganisms() > 0 ||
+	test_gen->GetNumOffspringParasites() > 1) {
+      found_gen = test_gen;
+    }
+
+    // Move to the next parasite...
+    test_gen = parent_gen;
+    parent_gen = test_gen->GetParentParasite();
+  }
+
+  coalescent = found_gen;
+
+  return coalescent->GetDepth();
+}
+
+
+bool cParasiteControl::CheckPos(cParasite & in_parasite)
+{
+  int next_OK = false;
+  int prev_OK = false;
+
+  if (in_parasite.GetNumOrganisms() >= in_parasite.GetNext()->GetNumOrganisms()) {
+    next_OK =true;
+  }
+  if (in_parasite.GetNumOrganisms() <= in_parasite.GetPrev()->GetNumOrganisms()) {
+    prev_OK =true;
+  }
+
+  if ((&in_parasite == best && next_OK) ||
+      (next_OK && prev_OK) ||
+      (&in_parasite == best->GetPrev() && prev_OK)) {
+    return true;
+  }
+
+  return false;
+}
+
+void cParasiteControl::Insert(cParasite & new_parasite)
+{
+  // If there is nothing in the list, add this.
+
+  if (size == 0) {
+    Insert(new_parasite, NULL);
+  }
+
+  // Otherwise tack it on the end.
+
+  else {
+    Insert(new_parasite, best->GetPrev());
+  }
+}
+
+bool cParasiteControl::Adjust(cParasite & in_parasite)
+{
+  if (in_parasite.GetDeferAdjust() == true) return true;
+
+  cParasite * cur_parasite = in_parasite.GetPrev();
+
+  // Check to see if this parasite should be removed completely.
+
+  if (in_parasite.GetNumOrganisms() == 0) {
+    genebank.RemoveParasite(in_parasite);
+    return false;
+  }
+
+  // Do not adjust if this was and still is the best parasite, or is
+  // otherwise in the proper spot...
+
+  if (CheckPos(in_parasite)) {
+    return true;
+  }
+
+  // Otherwise, remove it from the queue for just the moment.
+
+  Remove(in_parasite);
+
+  // Also, if this parasite is the best, put it there.
+
+  if (in_parasite.GetNumOrganisms() > best->GetNumOrganisms()) {
+    Insert(in_parasite, best->GetPrev());
+    best = &in_parasite;
+    return true;
+  }
+
+  // Finally, find out where this parasite *does* go.
+
+  while (cur_parasite->GetNumOrganisms() >= in_parasite.GetNumOrganisms() &&
+	 cur_parasite != best->GetPrev()) {
+    cur_parasite = cur_parasite->GetNext();
+  }
+  while (cur_parasite->GetNumOrganisms() < in_parasite.GetNumOrganisms() &&
+	 cur_parasite != best) {
+    cur_parasite = cur_parasite->GetPrev();
+  }
+
+  Insert(in_parasite, cur_parasite);
+
+  return true;
+}
+
+
+cParasite * cParasiteControl::Find(const cGenome & in_genome) const
+{
+  int i;
+  cParasite * cur_parasite = best;
+
+  for (i = 0; i < size; i++) {
+    if (in_genome == cur_parasite->GetGenome()) {
+      return cur_parasite;
+    }
+    cur_parasite = cur_parasite->GetNext();
+  }
+
+  return NULL;
+}
+
+int cParasiteControl::FindPos(cParasite & in_parasite, int max_depth)
+{
+  cParasite * temp_parasite = best;
+  if (max_depth < 0 || max_depth > size) max_depth = size;
+
+  for (int i = 0; i < max_depth; i++) {
+    if (temp_parasite == &in_parasite) return i;
+    temp_parasite = temp_parasite->GetNext();
+  }
+
+  return -1;
+}
+
+cParasite * cParasiteControl::Next(int thread)
+{
+  return threads[thread] = threads[thread]->GetNext();
+}
+
+cParasite * cParasiteControl::Prev(int thread)
+{
+  return threads[thread] = threads[thread]->GetPrev();
 }
Index: avida/current/source/main/genebank.hh
diff -u avida/current/source/main/genebank.hh:1.19 avida/current/source/main/genebank.hh:1.20
--- avida/current/source/main/genebank.hh:1.19	Sat May 17 02:48:09 2003
+++ avida/current/source/main/genebank.hh	Thu Jul 31 15:34:27 2003
@@ -20,6 +20,7 @@
 class cGenome;
 class cSpecies;
 class cStats;
+class cParasite;
 
 #define GENOTYPE_HASH_SIZE 307    // @CAO Is this an optimal number?
 #define SPECIES_HASH_SIZE 101
@@ -158,13 +159,95 @@
   inline int GetInactiveSize() const { return inactive_queue.GetSize(); }
 };
 
+class cParasiteElement {
+private:
+  cParasite * parasite;
+  cParasiteElement * next;
+  cParasiteElement * prev;
+public:
+  inline cParasiteElement(cParasite * in_gen=NULL) : parasite(in_gen) {
+    next = NULL;  prev = NULL;
+  }
+  inline ~cParasiteElement() { ; }
+
+  inline cParasite * GetParasite() const { return parasite; }
+  inline cParasiteElement * GetNext() const { return next; }
+  inline cParasiteElement * GetPrev() const { return prev; }
+
+  inline void SetNext(cParasiteElement * in_next) { next = in_next; }
+  inline void SetPrev(cParasiteElement * in_prev) { prev = in_prev; }
+};
+
+class cParasiteQueue {
+private:
+  int size;
+  cParasiteElement root;
+
+  void Remove(cParasiteElement * in_element);
+public:
+  cParasiteQueue();
+  ~cParasiteQueue();
+
+  bool OK();
+
+  void Insert(cParasite & in_parasite);
+  void Remove(cParasite & in_parasite);
+  cParasite * Find(const cGenome & in_genome) const;
+};
+
+class cParasiteControl {
+private:
+  int size;
+  cParasite * best;
+  cParasite * coalescent;
+  cParasite * threads[GENOTYPE_THREADS];
+  cGenebank & genebank;
+
+  cParasite * historic_list;
+  int historic_count;
+
+  void Insert(cParasite & in_parasite, cParasite * prev_parasite);
+  bool CheckPos(cParasite & in_parasite);
+public:
+  cParasiteControl(cGenebank & in_gb);
+  ~cParasiteControl();
+
+  bool OK();
+  void Remove(cParasite & in_parasite);
+  void Insert(cParasite & new_parasite);
+  bool Adjust(cParasite & in_parasite);
+
+  void RemoveHistoric(cParasite & in_parasite);
+  void InsertHistoric(cParasite & in_parasite);
+  int GetHistoricCount() { return historic_count; }
+
+  int UpdateCoalescent();
+
+  inline int GetSize() const { return size; }
+  inline cParasite * GetBest() const { return best; }
+  inline cParasite * GetCoalescent() const { return coalescent; }
+
+  cParasite * Find(const cGenome & in_genome) const;
+  int FindPos(cParasite & in_parasite, int max_depth = -1);
+
+  inline cParasite * Get(int thread) const { return threads[thread]; }
+  inline cParasite * Reset(int thread)
+    { return threads[thread] = best; }
+  inline cParasite * ResetHistoric(int thread)
+    { return threads[thread] = historic_list; }
+  cParasite * Next(int thread);
+  cParasite * Prev(int thread);
+};
 
 class cGenebank {
 private:
   unsigned int genotype_count[MAX_CREATURE_SIZE];
+  unsigned int parasite_count[MAX_CREATURE_SIZE];
   cGenotypeQueue active_genotypes[GENOTYPE_HASH_SIZE];
+  cParasiteQueue active_parasites[GENOTYPE_HASH_SIZE];
   cGenotypeControl * genotype_control;
   cSpeciesControl * species_control;
+  cParasiteControl * parasite_control;
   cStats & stats;
 
 private:
@@ -227,6 +310,14 @@
   unsigned int FindCRC(const cGenome & in_genome) const;
 
   void SpeciesTest(char * message, cGenotype & genotype);
+
+  void AddParasite(cParasite *in_parasite, int in_list_num = -1 );
+  cParasite * AddParasite(const cGenome & in_genome,
+			  cParasite * parent_parasite = NULL);
+  cParasite * FindParasite(const cGenome & in_genome) const;
+  void RemoveParasite(cParasite & in_parasite);
+  void ThresholdParasite(cParasite & in_parasite);
+  bool AdjustParasite(cParasite & in_parasite);
 };
 
 #endif
Index: avida/current/source/main/genome.hh
diff -u avida/current/source/main/genome.hh:1.3 avida/current/source/main/genome.hh:1.4
--- avida/current/source/main/genome.hh:1.3	Thu Feb 28 22:37:51 2002
+++ avida/current/source/main/genome.hh	Thu Jul 31 15:34:27 2003
@@ -32,6 +32,8 @@
 
   virtual void operator=(const cGenome & other_genome);
   virtual bool operator==(const cGenome & other_genome) const;
+  virtual bool operator<(const cGenome & other_genome) const
+  { return AsString() < other_genome.AsString(); }
 
   cInstruction & operator[](int index)
     { assert(index >= 0 && index < active_size);  return genome[index]; }
Index: avida/current/source/main/population.cc
diff -u avida/current/source/main/population.cc:1.110 avida/current/source/main/population.cc:1.111
--- avida/current/source/main/population.cc:1.110	Wed Jul 16 19:36:55 2003
+++ avida/current/source/main/population.cc	Thu Jul 31 15:34:27 2003
@@ -1095,7 +1095,7 @@
   }
   else
     {
-      GetCell(cell_id).GetOrganism()->GetHardware().Inject(cCodeLabel(), genome);
+      GetCell(cell_id).GetOrganism()->GetHardware().Inject_Host(cCodeLabel(), genome);
     }
       
 }
Index: avida/current/source/viewers/view.cc
diff -u avida/current/source/viewers/view.cc:1.11 avida/current/source/viewers/view.cc:1.12
--- avida/current/source/viewers/view.cc:1.11	Wed Jul 16 19:36:55 2003
+++ avida/current/source/viewers/view.cc	Thu Jul 31 15:34:27 2003
@@ -125,11 +125,12 @@
 void cView::NotifyUpdate()
 {
   // If we're locked onto a specific thread, only stop for it.
-  if (info.GetPauseLevel() == PAUSE_ADVANCE_STEP &&
+  /*if (info.GetPauseLevel() == PAUSE_ADVANCE_STEP &&
       info.GetThreadLock() != -1  &&
       info.GetThreadLock() != info.GetActiveCell()->GetOrganism()->GetHardware().ViewerLock()){
     return;
-  }
+    }*/
+
 
   bar_screen->Update();
   info.UpdateSymbols();
Index: avida/current/source/viewers/zoom_screen.cc
diff -u avida/current/source/viewers/zoom_screen.cc:1.26 avida/current/source/viewers/zoom_screen.cc:1.27
--- avida/current/source/viewers/zoom_screen.cc:1.26	Wed Jul 16 19:36:55 2003
+++ avida/current/source/viewers/zoom_screen.cc	Thu Jul 31 15:34:27 2003
@@ -697,6 +697,7 @@
 void cZoomScreen::UpdateCPU_Original(cHardwareBase & hardware)
 {
   cHardwareCPU & hardwareCPU = (cHardwareCPU &) hardware;
+  //hardwareCPU.SetThread(cur_view_thread);
 
   // Place the registers onto the screen.
   SetBoldColor(COLOR_CYAN);
@@ -833,12 +834,19 @@
 void cZoomScreen::UpdateCPU_4Stack(cHardwareBase & hardware)
 {
   cHardware4Stack & hardware4Stack = (cHardware4Stack &) hardware;
-  hardware4Stack.SetThread(cur_view_thread);
+  
+  if(cur_view_thread>=hardware4Stack.GetNumThreads())
+    {
+      cur_view_thread=0;
+      cur_mem_space = hardware4Stack.IP(cur_view_thread).GetMemSpace();
+    }
+  //hardware4Stack.SetThread(cur_view_thread);
+  c4StackHead & cur_ip = hardware4Stack.IP(cur_view_thread);
 
-  // Place the registers onto the screen.
+  // Place the stacks onto the screen.
   SetBoldColor(COLOR_CYAN);
   for (int i = 0; i < 4; i++) {
-    Print(REG_Y+2 + i, REG_X+6, "%11d", hardware4Stack.Stack(i).Top());
+    Print(REG_Y+2 + i, REG_X+6, "%11d", hardware4Stack.Stack(i, cur_view_thread).Top());
   }
 
   // Place the active stack onto the screen.
@@ -851,13 +859,13 @@
   Print(STACK_Y, STACK_X + 8, "%s" , hardware4Stack.GetActiveStackID(cur_stack)());
 
   //SetBoldColor(COLOR_CYAN);
-  Print(STACK_Y+2, STACK_X + 2, "%11d", hardware4Stack.GetStack(0, cur_stack));
+  //Print(STACK_Y+2, STACK_X + 2, "%11d", hardware4Stack.GetStack(0, cur_stack));
   SetColor(COLOR_CYAN);
-  for (int i = 1; i <= 3; i++) {
-    Print(STACK_Y+2 + i, STACK_X+2, "%11d", hardware4Stack.GetStack(i, cur_stack));
+  for (int i = 0; i <= 3; i++) {
+    Print(STACK_Y+2 + i, STACK_X+2, "%11d", hardware4Stack.GetStack(i, cur_stack, cur_view_thread));
    }
 
-  Print(19, 74, "%2d/%2d", hardware4Stack.GetCurThread() + 1,
+  Print(19, 74, "%2d/%2d", cur_view_thread + 1,
 	hardware4Stack.GetNumThreads());
   
   // This line gets the creature that is currently executing. Usually the
@@ -884,7 +892,7 @@
   }
   
   int adj_inst_ptr = 0;
-  int base_inst_ptr = hardware4Stack.IP().GetPosition();
+  int base_inst_ptr = cur_ip.GetPosition();
   if (base_inst_ptr < 0 || parasite_zoom == true) base_inst_ptr = 0;
 
   const cInstSet & inst_set = hardware4Stack.GetInstSet();
@@ -906,7 +914,7 @@
       // If we are on the instruction about to be executed by the CPU,
       // hilight it...
       if (adj_inst_ptr == base_inst_ptr && 
-	  hardware4Stack.IP().GetMemSpace() == cur_mem_space) {
+	  hardware4Stack.IP(cur_view_thread).GetMemSpace() == cur_mem_space) {
 	SetBoldColor(COLOR_WHITE);
 	Print(MEMORY_Y + MEMORY_PRE_SIZE + 3 + i, MEMORY_X + 1, "%3d: ",
 		  adj_inst_ptr);
@@ -947,16 +955,16 @@
 	Print(MEMORY_Y + MEMORY_PRE_SIZE + 3 + i, MEMORY_X + 28, "Bp");
       }
 
-      if (adj_inst_ptr == hardware4Stack.GetHead(HEAD_READ).GetPosition() &&
-	  cur_mem_space == hardware4Stack.GetHead(HEAD_READ).GetMemSpace()) {
+      if (adj_inst_ptr == hardware4Stack.GetHead(HEAD_READ, cur_view_thread).GetPosition() &&
+	  cur_mem_space == hardware4Stack.GetHead(HEAD_READ, cur_view_thread).GetMemSpace()) {
 	Print(MEMORY_Y + MEMORY_PRE_SIZE + 3 + i, MEMORY_X + 31, "R");
       }
-      if (adj_inst_ptr == hardware4Stack.GetHead(HEAD_WRITE).GetPosition() &&
-	  cur_mem_space == hardware4Stack.GetHead(HEAD_WRITE).GetMemSpace()) {
+      if (adj_inst_ptr == hardware4Stack.GetHead(HEAD_WRITE, cur_view_thread).GetPosition() &&
+	  cur_mem_space == hardware4Stack.GetHead(HEAD_WRITE, cur_view_thread).GetMemSpace()) {
 	Print(MEMORY_Y + MEMORY_PRE_SIZE + 3 + i, MEMORY_X + 32, "W");
       }
-      if (adj_inst_ptr == hardware4Stack.GetHead(HEAD_FLOW).GetPosition() &&
-	  cur_mem_space == hardware4Stack.GetHead(HEAD_FLOW).GetMemSpace()) {
+      if (adj_inst_ptr == hardware4Stack.GetHead(HEAD_FLOW, cur_view_thread).GetPosition() &&
+	  cur_mem_space == hardware4Stack.GetHead(HEAD_FLOW, cur_view_thread).GetMemSpace()) {
 	  Print(MEMORY_Y + MEMORY_PRE_SIZE + 3 + i, MEMORY_X + 33, "F");
       }
     }
@@ -1546,17 +1554,36 @@
   if (mode == ZOOM_MODE_STATS    && DoInputStats(in_char)) return;
   if (mode == ZOOM_MODE_GENOTYPE && DoInputGenotype(in_char)) return;
 
-  cHardware4Stack & hardware4Stack = 
-      (cHardware4Stack &) info.GetActiveCell()->GetOrganism()->GetHardware();
-
+  int num_threads;
+  if(cConfig::GetHardwareType()==HARDWARE_TYPE_CPU_ORIGINAL)
+    {
+       cHardwareCPU & hardwareCPU = 
+      (cHardwareCPU &) info.GetActiveCell()->GetOrganism()->GetHardware();
+       num_threads = hardwareCPU.GetNumThreads();
+    }
+  else if(cConfig::GetHardwareType()==HARDWARE_TYPE_CPU_4STACK)
+    {
+      cHardware4Stack & hardware4Stack = 
+	(cHardware4Stack &) info.GetActiveCell()->GetOrganism()->GetHardware();
+      num_threads = hardware4Stack.GetNumThreads();
+    }
   switch(in_char) {
   case 't':
   case 'T':
-    cur_view_thread=(cur_view_thread+1)%hardware4Stack.GetNumThreads();
-    //ThreadOptions();
-    Update();
+    if(num_threads>1)
+      {
+	memory_offset=0;
+	++cur_view_thread%=num_threads;
+	if(cConfig::GetHardwareType()==HARDWARE_TYPE_CPU_4STACK)
+	  {
+	    cHardware4Stack & hardware4Stack = 
+	      (cHardware4Stack &) info.GetActiveCell()->GetOrganism()->GetHardware();
+	    cur_mem_space=hardware4Stack.IP(cur_view_thread).GetMemSpace();
+	  }
+	//ThreadOptions();
+	Update();
+      }
     break;
-
   /*
     case 'x':
     case 'X':
@@ -1606,6 +1633,7 @@
     if (active_section == ZOOM_SECTION_MAP) {
       mini_center_id += map_x_size;
       mini_center_id %= population.GetSize();
+      cur_view_thread=0;
       if (population.GetCell(mini_center_id).IsOccupied()) {
 	memory_offset = 0;
 	info.SetActiveCell( &(population.GetCell(mini_center_id)));
@@ -1620,6 +1648,7 @@
   case KEY_UP:
     if (active_section == ZOOM_SECTION_MAP) {
       mini_center_id -= map_x_size;
+      cur_view_thread=0;
       if (mini_center_id < 0) mini_center_id += population.GetSize();
       if (population.GetCell(mini_center_id).IsOccupied()) {
 	memory_offset = 0;
@@ -1646,7 +1675,7 @@
       {
 	if(cConfig::GetHardwareType() == HARDWARE_TYPE_CPU_4STACK)
 	  {
-	    cur_mem_space=(cur_mem_space+1)%4;
+	    ++cur_mem_space%=4;
 	  }
       }
     Update(); 
@@ -1664,9 +1693,8 @@
     else if (active_section == ZOOM_SECTION_MEMORY) {
       if(cConfig::GetHardwareType()==HARDWARE_TYPE_CPU_4STACK)
 	{
-	  cur_mem_space--;
-	  if(cur_mem_space<0)
-	    cur_mem_space=3;
+	  cur_mem_space+=3;
+	  cur_mem_space%=4;
 	}
     }
     Update();
@@ -1674,7 +1702,7 @@
   case 'K':
   case 'k':
     if(cConfig::GetHardwareType()==HARDWARE_TYPE_CPU_4STACK) {
-      cur_stack=(cur_stack+1)%4;
+      ++cur_stack%=4;
     }
     Update();
     break;


More information about the Avida-cvs mailing list