[Avida-SVN] r2887 - in development/source: cpu main

connel42 at myxo.css.msu.edu connel42 at myxo.css.msu.edu
Mon Oct 27 10:07:01 PDT 2008


Author: connel42
Date: 2008-10-27 13:07:01 -0400 (Mon, 27 Oct 2008)
New Revision: 2887

Modified:
   development/source/cpu/cCPUTestInfo.h
   development/source/cpu/cHardwareCPU.cc
   development/source/cpu/cHardwareCPU.h
   development/source/cpu/cTestCPUInterface.h
   development/source/main/cAvidaConfig.h
   development/source/main/cDeme.cc
   development/source/main/cDeme.h
   development/source/main/cOrgInterface.h
   development/source/main/cOrganism.cc
   development/source/main/cOrganism.h
   development/source/main/cPhenotype.cc
   development/source/main/cPhenotype.h
   development/source/main/cPopulationInterface.cc
   development/source/main/cPopulationInterface.h
Log:
Added code for energy level detection, energy sharing, and broadcast messaging

Modified: development/source/cpu/cCPUTestInfo.h
===================================================================
--- development/source/cpu/cCPUTestInfo.h	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/cpu/cCPUTestInfo.h	2008-10-27 17:07:01 UTC (rev 2887)
@@ -93,8 +93,8 @@
   // Input Setup
   void TraceTaskOrder(bool _trace=true) { trace_task_order = _trace; }
   void UseRandomInputs(bool _rand=true) { use_random_inputs = _rand; use_manual_inputs = false; }
-	void UseManualInputs(tArray<int> inputs) {use_manual_inputs = true; use_random_inputs = false; manual_inputs = inputs;}
-	void ResetInputMode() {use_manual_inputs = false; use_random_inputs = false;}
+  void UseManualInputs(tArray<int> inputs) {use_manual_inputs = true; use_random_inputs = false; manual_inputs = inputs;}
+  void ResetInputMode() {use_manual_inputs = false; use_random_inputs = false;}
   void SetTraceExecution(cHardwareTracer* tracer = NULL) { m_tracer = tracer; }
   void SetInstSet(cInstSet* inst_set = NULL) { m_inst_set = inst_set; }
   void SetResourceOptions(int res_method = RES_INITIAL, std::vector<std::pair<int, std::vector<double> > > * res = NULL, int update = 0, int cpu_cycle_offset = 0)

Modified: development/source/cpu/cHardwareCPU.cc
===================================================================
--- development/source/cpu/cHardwareCPU.cc	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/cpu/cHardwareCPU.cc	2008-10-27 17:07:01 UTC (rev 2887)
@@ -219,6 +219,8 @@
     tInstLibEntry<tMethod>("donate-quantagb",  &cHardwareCPU::Inst_DonateQuantaThreshGreenBeard, nInstFlag::STALL),
     tInstLibEntry<tMethod>("donate-NUL", &cHardwareCPU::Inst_DonateNULL, nInstFlag::STALL),
     tInstLibEntry<tMethod>("donate-facing", &cHardwareCPU::Inst_DonateFacing, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("receive-donated-energy", &cHardwareCPU::Inst_ReceiveDonatedEnergy, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("donate-energy", &cHardwareCPU::Inst_DonateEnergy, nInstFlag::STALL),
     
     tInstLibEntry<tMethod>("IObuf-add1", &cHardwareCPU::Inst_IOBufAdd1, nInstFlag::STALL),
     tInstLibEntry<tMethod>("IObuf-add0", &cHardwareCPU::Inst_IOBufAdd0, nInstFlag::STALL),
@@ -232,7 +234,6 @@
     tInstLibEntry<tMethod>("rotate-to-occupied-cell", &cHardwareCPU::Inst_RotateOccupiedCell, nInstFlag::STALL),
     tInstLibEntry<tMethod>("rotate-to-event-cell", &cHardwareCPU::Inst_RotateEventCell, nInstFlag::STALL),
     
-    
     tInstLibEntry<tMethod>("set-cmut", &cHardwareCPU::Inst_SetCopyMut),
     tInstLibEntry<tMethod>("mod-cmut", &cHardwareCPU::Inst_ModCopyMut),
     tInstLibEntry<tMethod>("get-cell-xy", &cHardwareCPU::Inst_GetCellPosition),
@@ -366,7 +367,15 @@
     tInstLibEntry<tMethod>("relinquishEnergyToNeighborOrganisms", &cHardwareCPU::Inst_RelinquishEnergyToNeighborOrganisms, nInstFlag::STALL),
     tInstLibEntry<tMethod>("relinquishEnergyToOrganismsInDeme", &cHardwareCPU::Inst_RelinquishEnergyToOrganismsInDeme, nInstFlag::STALL),
 
-
+    // Energy level detection
+	  tInstLibEntry<tMethod>("if-energy-low", &cHardwareCPU::Inst_IfEnergyLow, nInstFlag::STALL),
+	  tInstLibEntry<tMethod>("if-energy-not-low", &cHardwareCPU::Inst_IfEnergyNotLow, nInstFlag::STALL),
+  	tInstLibEntry<tMethod>("if-energy-high", &cHardwareCPU::Inst_IfEnergyHigh, nInstFlag::STALL),
+  	tInstLibEntry<tMethod>("if-energy-not-high", &cHardwareCPU::Inst_IfEnergyNotHigh, nInstFlag::STALL),
+  	tInstLibEntry<tMethod>("if-energy-med", &cHardwareCPU::Inst_IfEnergyMed, nInstFlag::STALL),	  
+	  tInstLibEntry<tMethod>("if-energy-in-buffer", &cHardwareCPU::Inst_IfEnergyInBuffer, nInstFlag::STALL),
+	  tInstLibEntry<tMethod>("if-energy-not-in-buffer", &cHardwareCPU::Inst_IfEnergyNotInBuffer, nInstFlag::STALL),
+	  
     // Sleep and time
     tInstLibEntry<tMethod>("sleep", &cHardwareCPU::Inst_Sleep, nInstFlag::STALL),
     tInstLibEntry<tMethod>("sleep1", &cHardwareCPU::Inst_Sleep, nInstFlag::STALL),
@@ -3327,11 +3336,14 @@
 
   // Plug the current merit back into this organism and notify the scheduler.
   organism->UpdateMerit(cur_merit);
+  organism->GetPhenotype().SetIsEnergyDonor();
   
   // Update the merit of the organism being donated to...
   double other_merit = to_org->GetPhenotype().GetMerit().GetDouble();
   other_merit += merit_received;
   to_org->UpdateMerit(other_merit);
+  to_org->GetPhenotype().SetIsEnergyReceiver();
+
 }
 
 void cHardwareCPU::DoEnergyDonate(cOrganism* to_org)
@@ -3345,15 +3357,59 @@
   
   //update energy store and merit of donor
   organism->GetPhenotype().ReduceEnergy(energy_given);
+  organism->GetPhenotype().IncreaseEnergyDonated(energy_given);
   double senderMerit = cMerit::EnergyToMerit(organism->GetPhenotype().GetStoredEnergy()  * organism->GetPhenotype().GetEnergyUsageRatio(), m_world);
   organism->UpdateMerit(senderMerit);
+  organism->GetPhenotype().SetIsEnergyDonor();
   
   // update energy store and merit of donee
   to_org->GetPhenotype().ReduceEnergy(-1.0*energy_given);
+  to_org->GetPhenotype().IncreaseEnergyReceived(energy_given);
   double receiverMerit = cMerit::EnergyToMerit(to_org->GetPhenotype().GetStoredEnergy() * to_org->GetPhenotype().GetEnergyUsageRatio(), m_world);
   to_org->UpdateMerit(receiverMerit);
+  to_org->GetPhenotype().SetIsEnergyReceiver();
 }
 
+
+// The difference between this version and the previous is that this one allows energy to be placed
+// into the recipient's incoming energy buffer and not be applied immediately.  Also, some of the
+// energy may be lost in transfer
+void cHardwareCPU::DoEnergyDonatePercent(cOrganism* to_org, const double frac_energy_given)
+{
+  double losspct = m_world->GetConfig().ENERGY_SHARING_LOSS.Get();
+  
+  assert(to_org != NULL);
+  assert(frac_energy_given >= 0);
+  assert(frac_energy_given <= 1);
+  assert(losspct >= 0);
+  assert(losspct <= 1);
+    
+  double cur_energy = organism->GetPhenotype().GetStoredEnergy();
+  double energy_given = cur_energy * frac_energy_given;
+  
+  //update energy store and merit of donor
+  organism->GetPhenotype().ReduceEnergy(energy_given);
+  organism->GetPhenotype().IncreaseEnergyDonated(energy_given);
+  double senderMerit = cMerit::EnergyToMerit(organism->GetPhenotype().GetStoredEnergy()  * organism->GetPhenotype().GetEnergyUsageRatio(), m_world);
+  organism->UpdateMerit(senderMerit);
+  
+  //apply loss in transfer
+  energy_given *= (1 - losspct);
+  
+  //place energy into receiver's incoming energy buffer
+  to_org->GetPhenotype().ReceiveDonatedEnergy(energy_given);
+  to_org->GetPhenotype().IncreaseEnergyReceived(energy_given);
+  
+  //if we are using the push energy method, pass the new energy into the receiver's energy store and recalculate merit
+  if(m_world->GetConfig().ENERGY_SHARING_METHOD.Get() == 1) {
+    to_org->GetPhenotype().ApplyDonatedEnergy();
+    double receiverMerit = cMerit::EnergyToMerit(to_org->GetPhenotype().GetStoredEnergy() * to_org->GetPhenotype().GetEnergyUsageRatio(), m_world);
+    to_org->UpdateMerit(receiverMerit);
+  }
+  
+} //End DoEnergyDonatePercent()
+
+
 bool cHardwareCPU::Inst_DonateFacing(cAvidaContext& ctx) {
   if (organism->GetPhenotype().GetCurNumDonates() > m_world->GetConfig().MAX_DONATES.Get()) {
     return false;
@@ -3854,6 +3910,72 @@
 }
 
 
+//Move energy from an organism's received energy buffer into their energy store, recalculate merit
+bool cHardwareCPU::Inst_ReceiveDonatedEnergy(cAvidaContext& ctx)
+{
+  if(organism->GetCellID() < 0) {
+    return false;
+  }	
+  
+  if(organism->GetPhenotype().GetEnergyInBufferAmount() > 0) {
+    organism->GetPhenotype().ApplyDonatedEnergy();
+    organism->GetPhenotype().SetHasUsedDonatedEnergy();
+    double receiverMerit = cMerit::EnergyToMerit(organism->GetPhenotype().GetStoredEnergy() * organism->GetPhenotype().GetEnergyUsageRatio(), m_world);
+    organism->UpdateMerit(receiverMerit);
+  }
+  
+  return true;
+  
+} //End Inst_ReceiveDonatedEnergy()
+
+
+//Donate a fraction of organism's energy to the organism that last requested it.
+bool cHardwareCPU::Inst_DonateEnergy(cAvidaContext& ctx)
+{
+  if(organism->GetCellID() < 0) {
+    return false;
+  }	
+  
+  const cOrgMessage* msg = organism->RetrieveMessage();
+  if(msg == 0) {
+    return false;
+  }
+    
+  cOrganism* receiver = msg->GetSender();
+
+  // If the requestor no longer exists, should the donor still lose energy???
+  if( (receiver == NULL) && (receiver->IsDead()) ) {
+    return false;
+  }
+  
+  //Note: could get fancier about fraction of energy to send
+  DoEnergyDonatePercent(receiver, m_world->GetConfig().MERIT_GIVEN.Get());
+  organism->GetPhenotype().IncDonates();
+  
+  return true;
+  
+} //End Inst_DonateEnergy()
+
+
+//Broadcast a request for energy
+bool cHardwareCPU::Inst_RequestEnergy(cAvidaContext& ctx)
+{
+  if(organism->GetCellID() < 0) {
+    return false;
+  }	
+    
+  //TODO: BDC: somehow use nop modifiers to pick a multiplier for the amount of energy to request
+  
+  cOrgMessage msg = cOrgMessage(organism);
+  // Could set the data field of the message to be the multiplier
+  
+  organism->BroadcastMessage(ctx, msg);
+  
+  return true;
+  
+} //End Inst_RequestEnergy()
+
+
 bool cHardwareCPU::Inst_SearchF(cAvidaContext& ctx)
 {
   ReadLabel();
@@ -4620,6 +4742,120 @@
   return true; 
 }
 
+
+/* Execute the next instruction if the organism's energy level is low */
+bool cHardwareCPU::Inst_IfEnergyLow(cAvidaContext& ctx) {
+  
+  if(organism->GetCellID() < 0) {
+    return false;
+  }	
+	
+  // Note: these instructions should probably also make sure the returned energy level is not -1.
+  if(organism->GetPhenotype().GetDiscreteEnergyLevel() != cPhenotype::ENERGY_LEVEL_LOW) {
+    IP().Advance();
+  }
+	
+  return true;
+	
+} //End Inst_IfEnergyLow()
+
+
+/* Execute the next instruction if the organism's energy level is not low */
+bool cHardwareCPU::Inst_IfEnergyNotLow(cAvidaContext& ctx) {
+  
+  if(organism->GetCellID() < 0) {
+    return false;
+  }	
+	
+  if(organism->GetPhenotype().GetDiscreteEnergyLevel() == cPhenotype::ENERGY_LEVEL_LOW) {
+    IP().Advance();
+  }
+	
+  return true;
+	
+} //End Inst_IfEnergyNotLow()
+
+
+/* Execute the next instruction if the organism's energy level is high */
+bool cHardwareCPU::Inst_IfEnergyHigh(cAvidaContext& ctx) {
+	
+  if(organism->GetCellID() < 0) {
+    return false;
+  }	
+	
+  if(organism->GetPhenotype().GetDiscreteEnergyLevel() != cPhenotype::ENERGY_LEVEL_HIGH) {
+    IP().Advance();
+  }
+	
+  return true;
+	
+} //End Inst_IfEnergyHigh()
+
+
+/* Execute the next instruction if the organism's energy level is not high */
+bool cHardwareCPU::Inst_IfEnergyNotHigh(cAvidaContext& ctx) {
+
+  if(organism->GetCellID() < 0) {
+    return false;
+  }	
+	
+  if(organism->GetPhenotype().GetDiscreteEnergyLevel() == cPhenotype::ENERGY_LEVEL_HIGH) {
+    IP().Advance();
+  }
+	
+  return true;
+	
+} //End Inst_IfEnergyNotHigh()
+
+
+/* Execute the next instruction if the organism's energy level is medium */
+bool cHardwareCPU::Inst_IfEnergyMed(cAvidaContext& ctx) {
+
+  if(organism->GetCellID() < 0) {
+    return false;
+  }	
+
+  if(organism->GetPhenotype().GetDiscreteEnergyLevel() != cPhenotype::ENERGY_LEVEL_MEDIUM) {
+    IP().Advance();
+  }
+		
+  return true;
+	
+} //End Inst_IfEnergyMed()
+
+
+/* Execute the next instruction if the organism has received energy */
+bool cHardwareCPU::Inst_IfEnergyInBuffer(cAvidaContext& ctx) {
+  
+  if(organism->GetCellID() < 0) {
+    return false;
+  }	
+  
+  if(organism->GetPhenotype().GetEnergyInBufferAmount() == 0) {
+    IP().Advance();
+  }
+  
+  return true;
+	
+} //End Inst_IfEnergyInBuffer()
+
+
+/* Execute the next instruction if the organism has not received energy */
+bool cHardwareCPU::Inst_IfEnergyNotInBuffer(cAvidaContext& ctx) {
+  
+  if(organism->GetCellID() < 0) {
+    return false;
+  }	
+  
+  if(organism->GetPhenotype().GetEnergyInBufferAmount() > 0) {
+    IP().Advance();
+  }
+  
+  return true;
+	
+} //End Inst_IfEnergyNotInBuffer()
+
+
 bool cHardwareCPU::Inst_Sleep(cAvidaContext& ctx) {
   cPopulation& pop = m_world->GetPopulation();
   int cellID = organism->GetCellID();
@@ -5315,7 +5551,7 @@
   int cellid = organism->GetCellID();
 	
   if(cellid == -1) {
-    return true;
+    return false;
   }
 	
   cPopulationCell& mycell = pop.GetCell(cellid);
@@ -5371,7 +5607,7 @@
   int cellid = organism->GetCellID(); //absolute id of current cell
 
   if(cellid == -1) {
-    return true;
+    return false;
   }
 
   return DoSensePheromone(ctx, cellid);
@@ -5382,7 +5618,7 @@
   int cellid = organism->GetCellID(); //absolute id of current cell
 
   if(cellid == -1) {
-    return true;
+    return false;
   }
 
   cPopulation& pop = m_world->GetPopulation();
@@ -5403,7 +5639,7 @@
   int cellid = organism->GetCellID();
 
   if(cellid == -1) {
-    return true;
+    return false;
   }
 
   cPopulationCell& mycell = pop.GetCell(cellid);
@@ -5541,7 +5777,7 @@
   int cellid = organism->GetCellID();
 
   if(cellid == -1) {
-    return true;
+    return false;
   }
 
   cPopulationCell& mycell = pop.GetCell(cellid);
@@ -5685,7 +5921,7 @@
   int cellid = organism->GetCellID();
 
   if(cellid == -1) {
-    return true;
+    return false;
   }
 
   cPopulationCell& mycell = pop.GetCell(cellid);
@@ -6053,7 +6289,7 @@
   int cellid = organism->GetCellID();
 
   if(cellid == -1) {
-    return true;
+    return false;
   }
 
   cPopulationCell& mycell = pop.GetCell(cellid);
@@ -6185,7 +6421,7 @@
   int cellid = organism->GetCellID();
 
   if(cellid == -1) {
-    return true;
+    return false;
   }
 
   cPopulationCell& mycell = pop.GetCell(cellid);
@@ -6313,7 +6549,7 @@
   int cellid = organism->GetCellID();
 
   if(cellid == -1) {
-    return true;
+    return false;
   }
 
   cPopulationCell& mycell = pop.GetCell(cellid);

Modified: development/source/cpu/cHardwareCPU.h
===================================================================
--- development/source/cpu/cHardwareCPU.h	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/cpu/cHardwareCPU.h	2008-10-27 17:07:01 UTC (rev 2887)
@@ -469,6 +469,7 @@
 
   void DoDonate(cOrganism * to_org);
   void DoEnergyDonate(cOrganism* to_org);
+  void DoEnergyDonatePercent(cOrganism* to_org, const double frac_energy_given);
   bool Inst_DonateRandom(cAvidaContext& ctx);
   bool Inst_DonateKin(cAvidaContext& ctx);
   bool Inst_DonateEditDist(cAvidaContext& ctx);
@@ -478,7 +479,11 @@
   bool Inst_DonateQuantaThreshGreenBeard(cAvidaContext& ctx);
   bool Inst_DonateNULL(cAvidaContext& ctx);
   bool Inst_DonateFacing(cAvidaContext& ctx);
+  bool Inst_ReceiveDonatedEnergy(cAvidaContext& ctx);
+  bool Inst_DonateEnergy(cAvidaContext& ctx);
+  bool Inst_RequestEnergy(cAvidaContext& ctx);
 
+
   bool Inst_SearchF(cAvidaContext& ctx);
   bool Inst_SearchB(cAvidaContext& ctx);
   bool Inst_MemSize(cAvidaContext& ctx);
@@ -579,6 +584,14 @@
   bool Inst_HeadDivide0_01(cAvidaContext& ctx);
   bool Inst_HeadDivide0_001(cAvidaContext& ctx);
 
+  bool Inst_IfEnergyLow(cAvidaContext& ctx);
+  bool Inst_IfEnergyNotLow(cAvidaContext& ctx);
+  bool Inst_IfEnergyHigh(cAvidaContext& ctx);
+  bool Inst_IfEnergyNotHigh(cAvidaContext& ctx);
+  bool Inst_IfEnergyMed(cAvidaContext& ctx);
+  bool Inst_IfEnergyInBuffer(cAvidaContext& ctx);
+  bool Inst_IfEnergyNotInBuffer(cAvidaContext& ctx);
+	
   bool Inst_Sleep(cAvidaContext& ctx);
   bool Inst_GetUpdate(cAvidaContext& ctx);
 

Modified: development/source/cpu/cTestCPUInterface.h
===================================================================
--- development/source/cpu/cTestCPUInterface.h	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/cpu/cTestCPUInterface.h	2008-10-27 17:07:01 UTC (rev 2887)
@@ -88,6 +88,8 @@
   bool TestOnDivide() { return false; }
   int GetFacing() { return 0; }
   bool SendMessage(cOrgMessage& msg) { return false; }
+  bool SendMessage(cOrganism* recvr, cOrgMessage& msg) { return false; }
+  bool BroadcastMessage(cOrgMessage& msg) { return false; }
 	bool BcastAlarm(int jump_label, int bcast_range) { return false; }
   void DivideOrgTestamentAmongDeme(double value) {;}
 	void SendFlash() { }

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/main/cAvidaConfig.h	2008-10-27 17:07:01 UTC (rev 2887)
@@ -462,6 +462,10 @@
   CONFIG_ADD_VAR(NET_MUT_PROB, double, 0.0, "Message corruption probability");
   CONFIG_ADD_VAR(NET_MUT_TYPE, int, 0, "Type of message corruption.  0 = Random Single Bit, 1 = Always Flip Last");
   CONFIG_ADD_VAR(NET_STYLE, int, 0, "Communication Style.  0 = Random Next, 1 = Receiver Facing");
+	
+  CONFIG_ADD_GROUP(ORGANISM_MESSAGING_GROUP, "Organism Message-Based Communication");
+  CONFIG_ADD_VAR(MESSAGE_TYPE, int, 0, "Messaging Stle. 0=Receiver Facing, 1=Broadcast");
+  CONFIG_ADD_VAR(MESSAGE_BCAST_RADIUS, int, 1, "Broadcast message radius (cells)");
 
   CONFIG_ADD_GROUP(BUY_SELL_GROUP, "Buying and Selling Parameters");
   CONFIG_ADD_VAR(SAVE_RECEIVED, bool, 0, "Enable storage of all inputs bought from other orgs");
@@ -490,7 +494,13 @@
   CONFIG_ADD_VAR(ENERGY_PASSED_ON_DEME_REPLICATION_METHOD, int, 0, "Who get energy passed from a parent deme\n0 = Energy divided among organisms injected to offspring deme\n1 = Energy divided among cells in offspring deme");
   CONFIG_ADD_VAR(INHERIT_EXE_RATE, int, 0, "Inherit energy rate from parent? 0=no  1=yes");
   CONFIG_ADD_VAR(ATTACK_DECAY_RATE, double, 0.0, "Percent of cell's energy decayed by attack");
-
+  CONFIG_ADD_VAR(ENERGY_THRESH_LOW, double, .33, "Threshold percent below which energy level is considered low.  Requires ENERGY_CAP.");
+  CONFIG_ADD_VAR(ENERGY_THRESH_HIGH, double, .75, "Threshold percent above which energy level is considered high.  Requires ENERGY_CAP.");
+  
+  CONFIG_ADD_GROUP(ENERGY_SHARING_GROUP, "Energy Sharing Settings");
+  CONFIG_ADD_VAR(ENERGY_SHARING_METHOD, int, 0, "Method for sharing energy.  0=receiver must actively receive, 1=energy pushed on receiver");
+  CONFIG_ADD_VAR(ENERGY_SHARING_LOSS, double, 0.0, "Percent of shared energy lost in transfer");
+  
   CONFIG_ADD_GROUP(SECOND_PASS_GROUP, "Tracking metrics known after the running experiment previously");
   CONFIG_ADD_VAR(TRACK_CCLADES, int, 0, "Enable tracking of coalescence clades");
   CONFIG_ADD_VAR(TRACK_CCLADES_IDS, cString, "coalescence.ids", "File storing coalescence IDs");

Modified: development/source/main/cDeme.cc
===================================================================
--- development/source/main/cDeme.cc	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/main/cDeme.cc	2008-10-27 17:07:01 UTC (rev 2887)
@@ -795,3 +795,62 @@
 //  assert(false); // slots must be of equal size and fit perfectally in deme lifetime
   return 0;
 }
+
+/* Place the absolute IDs of all cells surrounding the given cell id within the given radius into vector cells */
+void cDeme::GetSurroundingCellIds(tVector<int> &cells, const int absolute_cell_id, const int radius) {
+	assert(cell_ids[0] <= absolute_cell_id);
+	assert(absolute_cell_id <= cell_ids[cell_ids.GetSize()-1]);
+	assert(radius >= 0);
+	
+	const int relative_cell_id = GetRelativeCellID(absolute_cell_id);
+	const int geometry = m_world->GetConfig().WORLD_GEOMETRY.Get();
+	const int width = GetWidth();
+	const int height = GetHeight();
+	const std::pair<int, int> coords = GetCellPosition(absolute_cell_id);
+	const int curr_x = coords.first;
+	const int curr_y = coords.second;
+	int cid, acid;
+	int x2, y2;
+	
+	//Note: this code currently supports a grid or torus
+	assert(geometry == nGeometry::GRID || geometry == nGeometry::TORUS);
+	
+	if(geometry == nGeometry::GRID) {
+		for(int y = curr_y - radius; y <= curr_y + radius; y++) {
+			for(int x = curr_x - radius; x <= curr_x + radius; x++) {
+				cid = y * width + x;
+				acid = GetAbsoluteCellID(cid);
+				if(y >= 0 && y < height && x >= 0 && x < width && cid != relative_cell_id) {
+					cells.Add(acid);
+				}
+			} 
+		}
+	} //End if world is a grid
+	else if(geometry == nGeometry::TORUS) {
+		for(int y = curr_y - radius; y <= curr_y + radius; y++) {
+			for(int x = curr_x - radius; x <= curr_x + radius; x++) {
+				x2 = x; y2 = y;
+				
+				if(x2 < 0) {
+					x2 = x2 + width;
+				} else if(x2 >= width) {
+					x2 = x2 - width;
+				}
+				
+				if(y2 < 0) {
+					y2 = y2 + height;
+				} else if(y2 >= height) {
+					y2 = y2 - height;
+				}
+				
+				cid = y2 * width + x2;
+				acid = GetAbsoluteCellID(cid);
+				
+				if(cid != relative_cell_id) {
+					cells.Add(acid);
+				}
+			} 
+		}
+	} //End if world is a torus
+	
+} //End GetSurroundingCellIds()

Modified: development/source/main/cDeme.h
===================================================================
--- development/source/main/cDeme.h	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/main/cDeme.h	2008-10-27 17:07:01 UTC (rev 2887)
@@ -233,7 +233,8 @@
   void UpdateDemeRes() { deme_resource_count.GetResources(); }
   void Update(double time_step) { deme_resource_count.Update(time_step); }
   int GetRelativeCellID(int absolute_cell_id) const { return absolute_cell_id % GetSize(); } //!< assumes all demes are the same size
-
+  int GetAbsoluteCellID(int relative_cell_id) const { return relative_cell_id + (_id * GetSize()); } //!< assumes all demes are the same size
+	
   void SetCellEventGradient(int x1, int y1, int x2, int y2, int delay, int duration, bool static_pos, int time_to_live);
   int GetNumEvents();
   void SetCellEvent(int x1, int y1, int x2, int y2, int delay, int duration, bool static_position, int total_events);
@@ -286,6 +287,8 @@
 
   // --- Pheromones --- //
   void AddPheromone(int absolute_cell_id, double value);
+	
+  void GetSurroundingCellIds(tVector<int> &cells, const int absolute_cell_id, const int radius);
 };
 
 #endif

Modified: development/source/main/cOrgInterface.h
===================================================================
--- development/source/main/cOrgInterface.h	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/main/cOrgInterface.h	2008-10-27 17:07:01 UTC (rev 2887)
@@ -98,6 +98,7 @@
   virtual bool UpdateMerit(double new_merit) = 0;
   virtual bool TestOnDivide() = 0;
   virtual bool SendMessage(cOrgMessage& msg) = 0;
+  virtual bool BroadcastMessage(cOrgMessage& msg) = 0;
   virtual bool BcastAlarm(int jump_jabel, int bcast_range) = 0;
   virtual void DivideOrgTestamentAmongDeme(double value) = 0;
 	virtual void SendFlash() = 0;

Modified: development/source/main/cOrganism.cc
===================================================================
--- development/source/main/cOrganism.cc	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/main/cOrganism.cc	2008-10-27 17:07:01 UTC (rev 2887)
@@ -689,6 +689,31 @@
 }
 
 
+// Broadcast a message - slightly modified version of SendMessage
+bool cOrganism::BroadcastMessage(cAvidaContext& ctx, cOrgMessage& msg)
+{
+  assert(m_interface);
+  InitMessaging();
+ 
+  // If we're able to succesfully send the message...
+  if(m_interface->BroadcastMessage(msg)) {
+    // save it...
+    m_msg->sent.push_back(msg);
+    // and set the receiver-pointer of this message to NULL.  We don't want to
+    // walk this list later thinking that the receivers are still around.
+    // Also, a broadcast message may have >1 receiver
+    m_msg->sent.back().SetReceiver(0);
+    // stat-tracking...  NOTE: this has receiver not specified, so may be a problem for predicates
+    m_world->GetStats().SentMessage(msg);
+    // check to see if we've performed any tasks...NOTE: this has receiver not specified, so may be a problem for tasks that care
+    DoOutput(ctx);
+    return true;
+  }
+  
+  return false;
+} //End BroadcastMessage()
+
+
 void cOrganism::ReceiveMessage(cOrgMessage& msg)
 {
   InitMessaging();
@@ -708,7 +733,7 @@
   return 0;
 }
 
-// Brian Movement
+
 void cOrganism::Move(cAvidaContext& ctx)
 {
   assert(m_interface);

Modified: development/source/main/cOrganism.h
===================================================================
--- development/source/main/cOrganism.h	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/main/cOrganism.h	2008-10-27 17:07:01 UTC (rev 2887)
@@ -344,6 +344,7 @@
   
   //! Called when this organism attempts to send a message.
   bool SendMessage(cAvidaContext& ctx, cOrgMessage& msg);
+  bool BroadcastMessage(cAvidaContext& ctx, cOrgMessage& msg);
   //! Called when this organism has been sent a message.
   void ReceiveMessage(cOrgMessage& msg);
   //! Called when this organism attempts to move a received message into its CPU.

Modified: development/source/main/cPhenotype.cc
===================================================================
--- development/source/main/cPhenotype.cc	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/main/cPhenotype.cc	2008-10-27 17:07:01 UTC (rev 2887)
@@ -88,6 +88,7 @@
   energy_store             = in_phen.energy_store;    
   energy_tobe_applied      = in_phen.energy_tobe_applied;
   energy_testament         = in_phen.energy_testament;
+  energy_received_buffer   = in_phen.energy_received_buffer;
   genome_length            = in_phen.genome_length;        
   bonus_instruction_count  = in_phen.bonus_instruction_count; 
   copied_size              = in_phen.copied_size;          
@@ -142,6 +143,8 @@
   last_sense_count         = in_phen.last_sense_count;   
   last_fitness             = in_phen.last_fitness;            
   last_child_germline_propensity = in_phen.last_child_germline_propensity;
+  total_energy_donated     = in_phen.total_energy_donated;
+  total_energy_received    = in_phen.total_energy_received;
 
   // 4. Records from this organisms life...
   num_divides              = in_phen.num_divides;      
@@ -202,6 +205,12 @@
   parent_true             = in_phen.parent_true;     
   parent_sex              = in_phen.parent_sex;      
   parent_cross_num        = in_phen.parent_cross_num; 
+  
+  is_energy_donor         = in_phen.is_energy_donor;
+  is_energy_receiver      = in_phen.is_energy_receiver;
+  has_used_donated_energy = in_phen.has_used_donated_energy;
+  total_energy_donated    = in_phen.total_energy_donated;
+  total_energy_received   = in_phen.total_energy_received;
 
   // 6. Child information...
   copy_true               = in_phen.copy_true;       
@@ -240,6 +249,7 @@
   assert(time_used >= 0);
   assert(age >= 0);
   assert(child_copied_size >= 0);
+  assert(energy_received_buffer >= 0);
   // assert(to_die == false);
   return (m_world);
 }
@@ -267,6 +277,7 @@
   energy_store    = min(energy_store, (double) m_world->GetConfig().ENERGY_CAP.Get());
   energy_tobe_applied = 0.0;
   energy_testament = 0.0;
+  energy_received_buffer = 0.0;
   genome_length   = _genome.GetSize();
   copied_size     = parent_phenotype.child_copied_size;
   executed_size   = parent_phenotype.executed_size;
@@ -382,6 +393,12 @@
   to_die = false;
   to_delete = false;
 
+  is_energy_donor = false;
+  is_energy_receiver = false;
+  has_used_donated_energy = false;
+  total_energy_donated = 0.0;
+  total_energy_received = 0.0;  
+
   // Setup child info...
   copy_true          = false;
   divide_sex         = false;
@@ -417,6 +434,7 @@
   energy_store    = min(m_world->GetConfig().ENERGY_GIVEN_ON_INJECT.Get(), m_world->GetConfig().ENERGY_CAP.Get());
   energy_tobe_applied = 0.0;
   energy_testament = 0.0;
+  energy_received_buffer = 0.0;
   executionRatio = 1.0;
   gestation_time  = 0;
   gestation_start = 0;
@@ -519,6 +537,12 @@
   parent_cross_num    = 0;
   to_die = false;
   to_delete = false;
+  
+  is_energy_donor = false;
+  is_energy_receiver = false;
+  has_used_donated_energy = false;
+  total_energy_donated = 0.0;
+  total_energy_received = 0.0;
 
   // Setup child info...
   copy_true         = false;
@@ -558,7 +582,7 @@
   SetEnergy(energy_store + cur_energy_bonus);
   m_world->GetStats().SumEnergyTestamentAcceptedByOrganisms().Add(energy_testament);
   energy_testament = 0.0;
-
+  energy_received_buffer = 0.0;  // If donated energy not applied, it's lost here
   
   genome_length   = _genome.GetSize();
   (void) copied_size;          // Unchanged
@@ -833,6 +857,7 @@
   energy_store    = clone_phenotype.energy_store;
   energy_tobe_applied = 0.0;
   energy_testament = 0.0;
+  energy_received_buffer = 0.0;
 
   if(m_world->GetConfig().INHERIT_EXE_RATE.Get() == 0)
     executionRatio = 1.0;
@@ -949,6 +974,9 @@
   parent_cross_num    = clone_phenotype.cross_num;
   to_die = false;
   to_delete = false;
+  is_energy_donor = false;
+  is_energy_receiver = false;
+  has_used_donated_energy = false;
 
   // Setup child info...
   copy_true          = false;
@@ -1242,6 +1270,20 @@
   energy_testament += value;
 } //! external energy given to organism
 
+
+void cPhenotype::ApplyDonatedEnergy() {
+  SetEnergy(energy_store + energy_received_buffer);
+  energy_received_buffer = 0.0;
+} //End AppplyDonatedEnergy()
+
+
+void cPhenotype::ReceiveDonatedEnergy(const double donation) {
+  assert(donation >= 0.0);  
+  energy_received_buffer += donation;
+  is_energy_receiver = true;
+} //End ReceiveDonatedEnergy()
+
+
 double cPhenotype::ExtractParentEnergy() {
   assert(m_world->GetConfig().ENERGY_ENABLED.Get() > 0);
   // energy model config variables
@@ -1399,6 +1441,8 @@
   is_receiver_threshgb = false;
   is_receiver_quanta_threshgb_last = is_receiver_quanta_threshgb;
   is_receiver_quanta_threshgb = false;
+  is_energy_donor = false;
+  is_energy_receiver = false;
   (void) is_modifier;
   (void) is_modified;
   (void) is_fertile;
@@ -1514,3 +1558,28 @@
   
   return false;
 }
+
+// Return an integer classifying the organism's energy level as -1=error,0=low,1=med,2=high
+int cPhenotype::GetDiscreteEnergyLevel() const {
+  double max_energy = m_world->GetConfig().ENERGY_CAP.Get();
+  double high_pct = m_world->GetConfig().ENERGY_THRESH_HIGH.Get();
+  double low_pct = m_world->GetConfig().ENERGY_THRESH_LOW.Get();
+	
+  assert(max_energy >= 0);
+  assert(high_pct <= 1);
+  assert(high_pct >= 0);
+  assert(low_pct <= 1);
+  assert(low_pct >= 0);
+  assert(low_pct <= high_pct);
+	
+  if (energy_store < (low_pct * max_energy)) {
+    return ENERGY_LEVEL_LOW;
+  } else if ( (energy_store >= (low_pct * max_energy)) && (energy_store <= (high_pct * max_energy)) ) {
+    return ENERGY_LEVEL_MEDIUM;
+  } else if (energy_store > (high_pct * max_energy)) {
+    return ENERGY_LEVEL_HIGH;
+  } else {
+    return -1;
+  }			 
+	
+} //End GetDiscreteEnergyLevel()

Modified: development/source/main/cPhenotype.h
===================================================================
--- development/source/main/cPhenotype.h	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/main/cPhenotype.h	2008-10-27 17:07:01 UTC (rev 2887)
@@ -110,6 +110,9 @@
   double cur_energy_bonus;                    // Current energy bonus
   double energy_tobe_applied;                 // Energy that has not yet been added to energy store.
   double energy_testament;
+  double energy_received_buffer;              // Energy received through donation, but not yet applied to energy store
+  double total_energy_donated;                // Tota amount of energy that has been donated
+  double total_energy_received;               // Total amount of energy received through donations
   int cur_num_errors;                         // Total instructions executed illeagally.
   int cur_num_donates;                        // Number of donations so far
   tArray<int> cur_task_count;                 // Total times each task was performed
@@ -180,6 +183,9 @@
   bool is_donor_threshgb_last;// Did this org's parent threshgbg_donate? 
   bool is_donor_quanta_threshgb;  // Has this organism quanta_threshgb_donated (true green beard)? 
   bool is_donor_quanta_threshgb_last;// Did this org's parent quanta_threshgbg_donate? 
+  bool is_energy_donor; // Has this organism donated energy?
+  bool is_energy_receiver;  // Has this organism received an energy donation?
+  bool has_used_donated_energy; // Has the organism actively used an energy donation?
   int num_thresh_gb_donations;  // Num times this organism threshgb_donated (thresh green beard)? 
   int num_thresh_gb_donations_last; // Num times this org's parent thresh_donated? 
   int num_quanta_thresh_gb_donations;  // Num times this organism threshgb_donated (thresh green beard)? 
@@ -233,7 +239,8 @@
   cPhenotype& operator=(const cPhenotype&); 
   ~cPhenotype();
   
-
+  enum energy_levels {ENERGY_LEVEL_LOW = 0, ENERGY_LEVEL_MEDIUM, ENERGY_LEVEL_HIGH};
+	
   bool OK();
 
   // Run when being setup *as* and offspring.
@@ -295,6 +302,8 @@
   double GetCurMeritBase() const { assert(initialized == true); return CalcSizeMerit(); }
   double GetStoredEnergy() const { return energy_store; }
   double GetEnergyBonus() const { assert(initialized == true); return cur_energy_bonus; }
+  int GetDiscreteEnergyLevel() const;
+  double GetEnergyInBufferAmount() const { return energy_received_buffer; }
   
   bool GetToDie() const { assert(initialized == true); return to_die; }
   bool GetToDelete() const { assert(initialized == true); return to_delete; }
@@ -363,6 +372,9 @@
   bool IsDonorThreshGbLast() const { assert(initialized == true); return is_donor_threshgb_last; }
   bool IsDonorQuantaThreshGb() const { assert(initialized == true); return is_donor_quanta_threshgb; }
   bool IsDonorQuantaThreshGbLast() const { assert(initialized == true); return is_donor_quanta_threshgb_last; }
+  bool IsEnergyDonor() const { assert(initialized == true); return is_energy_donor; }
+  bool IsEnergyReceiver() const { assert(initialized == true); return is_energy_receiver; }
+  bool HasUsedEnergyDonation() const { assert(initialized == true); return has_used_donated_energy; }
   bool IsReceiver() const { assert(initialized == true); return is_receiver; }
   bool IsReceiverLast() const { assert(initialized == true); return is_receiver_last; }
   bool IsReceiverRand() const { assert(initialized == true); return is_receiver_rand; }
@@ -415,7 +427,9 @@
   void SetCrossNum(int _cross_num) { cross_num = _cross_num; }
   void SetToDie() { to_die = true; }
   void SetToDelete() { to_delete = true; }
-
+  void IncreaseEnergyDonated(double amount) { assert(amount >=0); total_energy_donated += amount; }
+  void IncreaseEnergyReceived(double amount) { assert(amount >=0); total_energy_received += amount; }
+  
   void SetIsDonorCur() { is_donor_cur = true; } 
   void SetIsDonorRand() { SetIsDonorCur(); is_donor_rand = true; }
   void SetIsDonorKin() { SetIsDonorCur(); is_donor_kin = true; }
@@ -433,6 +447,9 @@
   void SetIsReceiverTrueGb() { SetIsReceiver(); is_receiver_truegb = true; } 
   void SetIsReceiverThreshGb() { SetIsReceiver(); is_receiver_threshgb = true; } 
   void SetIsReceiverQuantaThreshGb() { SetIsReceiver(); is_receiver_quanta_threshgb = true; } 
+  void SetIsEnergyDonor() { is_energy_donor = true; }
+  void SetIsEnergyReceiver() { is_energy_receiver = true; }
+  void SetHasUsedDonatedEnergy() {has_used_donated_energy = true; }
   
   void SetCurBonus(double _bonus) { cur_bonus = _bonus; }
   void SetCurBonusInstCount(int _num_bonus_inst) {bonus_instruction_count = _num_bonus_inst;}
@@ -473,6 +490,8 @@
   void RefreshEnergy();
   void ApplyToEnergyStore();
   void EnergyTestament(const double value); //! external energy given to organism
+  void ApplyDonatedEnergy();
+  void ReceiveDonatedEnergy(const double value);
   double ExtractParentEnergy();
   
   bool operator<(const cPhenotype& rhs) const;

Modified: development/source/main/cPopulationInterface.cc
===================================================================
--- development/source/main/cPopulationInterface.cc	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/main/cPopulationInterface.cc	2008-10-27 17:07:01 UTC (rev 2887)
@@ -275,7 +275,42 @@
   return true;
 }
 
+/* Send a message to the given organism */
+bool cPopulationInterface::SendMessage(cOrganism* recvr, cOrgMessage& msg) {
+  assert(recvr != NULL);
+  recvr->ReceiveMessage(msg);
+  return true;
+} //End SendMessage()
 
+
+// Broadcast the message to all living organisms within range
+bool cPopulationInterface::BroadcastMessage(cOrgMessage& msg) {
+  bool all_sent = true;
+  const int bcast_range = m_world->GetConfig().MESSAGE_BCAST_RADIUS.Get();
+  assert(bcast_range >= 0);
+  tVector<int> neighbors;
+  neighbors.Clear();
+  
+  cDeme& deme = m_world->GetPopulation().GetDeme(GetDemeID());
+  deme.GetSurroundingCellIds(neighbors, GetCellID(), bcast_range);
+  
+  for(int i = 0; i < neighbors.Size(); i++) {
+    cPopulationCell& rcell = m_world->GetPopulation().GetCell(neighbors[i]);
+    if(rcell.IsOccupied()) {
+      cOrganism* neighbor = rcell.GetOrganism();
+      assert(neighbor != NULL);
+      
+      if(!SendMessage(neighbor, msg)) {
+        all_sent = false; 
+      }
+    }
+  }
+  
+  return all_sent;
+  
+} //End BroadcastMessage
+
+
 bool cPopulationInterface::BcastAlarm(int jump_label, int bcast_range) {
   bool successfully_sent(false);
   cPopulationCell& scell = m_world->GetPopulation().GetCell(m_cell_id);

Modified: development/source/main/cPopulationInterface.h
===================================================================
--- development/source/main/cPopulationInterface.h	2008-10-27 16:54:45 UTC (rev 2886)
+++ development/source/main/cPopulationInterface.h	2008-10-27 17:07:01 UTC (rev 2887)
@@ -105,6 +105,8 @@
   bool TestOnDivide();
   //! Send a message to the faced organism.
   bool SendMessage(cOrgMessage& msg);
+  bool SendMessage(cOrganism* recvr, cOrgMessage& msg);
+  bool BroadcastMessage(cOrgMessage& msg);
   bool BcastAlarm(int jump_label, int bcast_range);  
   void DivideOrgTestamentAmongDeme(double value);
 	//! Send a flash to all neighboring organisms.




More information about the Avida-cvs mailing list