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

dk at myxo.css.msu.edu dk at myxo.css.msu.edu
Fri Feb 20 08:10:37 PST 2009


Author: dk
Date: 2009-02-20 11:10:36 -0500 (Fri, 20 Feb 2009)
New Revision: 3151

Modified:
   development/source/cpu/cHardwareCPU.cc
   development/source/cpu/cHardwareCPU.h
   development/source/cpu/cTestCPUInterface.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/cPopulationCell.cc
   development/source/main/cPopulationCell.h
   development/source/main/cPopulationInterface.cc
   development/source/main/cPopulationInterface.h
Log:
Merged instruction-level message broadcasting in with energy-sharing broadcasting.  There are now four different broadcast instructions that vary in terms of how "strong" the broadcast is (that is, how many hops away they'll broadcast to).


Modified: development/source/cpu/cHardwareCPU.cc
===================================================================
--- development/source/cpu/cHardwareCPU.cc	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/cpu/cHardwareCPU.cc	2009-02-20 16:10:36 UTC (rev 3151)
@@ -107,6 +107,20 @@
     tInstLibEntry<tMethod>("if-grt-X", &cHardwareCPU::Inst_IfGrX),
     tInstLibEntry<tMethod>("if-equ-X", &cHardwareCPU::Inst_IfEquX),
 
+		// Probabilistic ifs.
+		tInstLibEntry<tMethod>("if-p-0.125", &cHardwareCPU::Inst_IfP0p125, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("if-p-0.25", &cHardwareCPU::Inst_IfP0p25, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("if-p-0.50", &cHardwareCPU::Inst_IfP0p50, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("if-p-0.75", &cHardwareCPU::Inst_IfP0p75, nInstFlag::STALL),
+				
+		// The below series of conditionals extend the traditional Avida single-instruction-skip
+		// to a block, or series of instructions.
+		tInstLibEntry<tMethod>("if-less.end", &cHardwareCPU::Inst_IfLessEnd, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("if-n-equ.end", &cHardwareCPU::Inst_IfNotEqualEnd, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("if->=.end", &cHardwareCPU::Inst_IfGrtEquEnd, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("else", &cHardwareCPU::Inst_Else, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("end-if", &cHardwareCPU::Inst_EndIf, nInstFlag::STALL),
+
     tInstLibEntry<tMethod>("jump-f", &cHardwareCPU::Inst_JumpF),
     tInstLibEntry<tMethod>("jump-b", &cHardwareCPU::Inst_JumpB),
     tInstLibEntry<tMethod>("call", &cHardwareCPU::Inst_Call),
@@ -453,7 +467,11 @@
     // Messaging
     tInstLibEntry<tMethod>("send-msg", &cHardwareCPU::Inst_SendMessage, nInstFlag::STALL),
     tInstLibEntry<tMethod>("retrieve-msg", &cHardwareCPU::Inst_RetrieveMessage, nInstFlag::STALL),
-
+    tInstLibEntry<tMethod>("bcast1", &cHardwareCPU::Inst_Broadcast1, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("bcast2", &cHardwareCPU::Inst_Broadcast2, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("bcast4", &cHardwareCPU::Inst_Broadcast4, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("bcast8", &cHardwareCPU::Inst_Broadcast8, nInstFlag::STALL),
+		
     // Alarms
     tInstLibEntry<tMethod>("send-alarm-msg-local", &cHardwareCPU::Inst_Alarm_MSG_local, nInstFlag::STALL),
     tInstLibEntry<tMethod>("send-alarm-msg-multihop", &cHardwareCPU::Inst_Alarm_MSG_multihop, nInstFlag::STALL),
@@ -512,6 +530,10 @@
     tInstLibEntry<tMethod>("hard-reset", &cHardwareCPU::Inst_HardReset, nInstFlag::STALL),
     tInstLibEntry<tMethod>("get-cycles", &cHardwareCPU::Inst_GetCycles, nInstFlag::STALL),		
 
+		// Neighborhood-sensing instructions
+		tInstLibEntry<tMethod>("get-neighborhood", &cHardwareCPU::Inst_GetNeighborhood, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("if-neighborhood-changed", &cHardwareCPU::Inst_IfNeighborhoodChanged, nInstFlag::STALL),
+		
     // Must always be the last instruction in the array
     tInstLibEntry<tMethod>("NULL", &cHardwareCPU::Inst_Nop, 0, "True no-operation instruction: does nothing"),
   };
@@ -1947,6 +1969,38 @@
   return true;
 }
 
+
+bool cHardwareCPU::Inst_IfP0p125(cAvidaContext& ctx) {
+	if(m_world->GetRandom().P(0.875)) {
+		IP().Advance();
+	}
+	return true;
+}
+
+
+bool cHardwareCPU::Inst_IfP0p25(cAvidaContext& ctx) {
+	if(m_world->GetRandom().P(0.75)) {
+		IP().Advance();
+	}
+	return true;
+}
+
+
+bool cHardwareCPU::Inst_IfP0p50(cAvidaContext& ctx) {
+	if(m_world->GetRandom().P(0.5)) {
+		IP().Advance();
+	}
+	return true;
+}
+
+
+bool cHardwareCPU::Inst_IfP0p75(cAvidaContext& ctx) {
+	if(m_world->GetRandom().P(0.25)) {
+		IP().Advance();
+	}
+	return true;
+}
+
 bool cHardwareCPU::Inst_JumpF(cAvidaContext& ctx)
 {
   ReadLabel();
@@ -4461,7 +4515,7 @@
   cOrgMessage msg(m_organism);
   // Could set the data field of the message to be the multiplier
   
-  m_organism->BroadcastMessage(ctx, msg);
+  m_organism->BroadcastMessage(ctx, msg, m_world->GetConfig().MESSAGE_BCAST_RADIUS.Get());
   m_organism->GetPhenotype().SetIsEnergyRequestor();
   m_organism->GetPhenotype().IncreaseNumEnergyRequests();
   
@@ -7879,3 +7933,158 @@
   GetRegister(FindModifiedRegister(REG_BX)) = m_cycle_counter;
   return true;
 }
+
+
+//! Loads the current neighborhood into the organism's memory.
+bool cHardwareCPU::Inst_GetNeighborhood(cAvidaContext& ctx) {
+	assert(m_organism != 0);
+	m_organism->LoadNeighborhood();
+	return true;
+}
+
+
+//! Test if the current neighborhood has changed from that in the organism's memory.
+bool cHardwareCPU::Inst_IfNeighborhoodChanged(cAvidaContext& ctx) {
+  assert(m_organism != 0);
+  if(!m_organism->HasNeighborhoodChanged()) {
+		IP().Advance();
+	}
+	
+	return true;
+}
+
+
+/*! Find the first occurence of the passed-in instruction from the IP() forward,
+ wrapping around the genome as required.  If the given instruction is not in the
+ genome, return the starting position.
+ */
+cHeadCPU cHardwareCPU::Find(const char* instr) {
+  cHeadCPU ptr(IP());
+  const int current = ptr.GetPosition();
+  ptr.Advance();
+  while(ptr.GetPosition() != current) {
+    ptr.Advance();
+    if(m_inst_set->GetName(ptr.GetInst())==instr) {
+      break;
+    }
+  }
+	return ptr;
+}
+
+
+bool cHardwareCPU::Inst_IfLessEnd(cAvidaContext& ctx) {
+  const int x = FindModifiedRegister(REG_BX);
+  const int y = FindNextRegister(x);
+	
+  if(GetRegister(x) >= GetRegister(y)) { Else_TopHalf(); }
+  return true;
+}
+
+
+bool cHardwareCPU::Inst_IfNotEqualEnd(cAvidaContext& ctx) {
+  const int x = FindModifiedRegister(REG_BX);
+  const int y = FindNextRegister(x);
+  
+  if(GetRegister(x) == GetRegister(y)) { Else_TopHalf(); }
+  return true;  
+}
+
+
+bool cHardwareCPU::Inst_IfGrtEquEnd(cAvidaContext& ctx) {
+  const int x = FindModifiedRegister(REG_BX);
+  const int y = FindNextRegister(x);
+  
+  if(GetRegister(x) < GetRegister(y)) { Else_TopHalf(); }
+  return true;
+}
+
+
+/*! This is the top-half of the else instruction, meant to be executed if the if
+ condition evaluates to false.
+ */
+void cHardwareCPU::Else_TopHalf() {
+  cHeadCPU else_head = Find("else");
+  cHeadCPU endif_head = Find("endif");  
+	
+  // Condition failed.  If there's an else-clause, jump to it.
+  // If there isn't an else-clause, try to jump to the endif.
+  // Note that the IP is unconditionally advanced *after* this instruction
+  // has executed.  If there is no else or endif, advance one instruction.
+  if(else_head.GetPosition() != IP().GetPosition()) {
+    IP().Set(else_head);
+  } else if(endif_head.GetPosition() != IP().GetPosition()) {
+    IP().Set(endif_head);
+  } else {
+    // No else or endif.  Advance past the next instruction (as normal).
+    IP().Advance();
+  }
+}
+
+
+/*! The only way that this instruction can be executed is if the if passed, or
+ if there was no if.  In both cases, we're going to jump to the first <end-if>, or
+ skip one instruction.
+ */
+bool cHardwareCPU::Inst_Else(cAvidaContext& ctx) {
+  cHeadCPU endif_head = Find("endif");
+  if(endif_head.GetPosition() != IP().GetPosition()) {
+    // If the <end-if> is somewhere else, jump to it.
+    IP().Set(endif_head);
+  } else {
+    // Otherwise, just skip one instruction.
+    IP().Advance();
+  }
+  return true; 
+}
+
+/*! This is just a placeholder; it has no functionality of its own.
+ */
+bool cHardwareCPU::Inst_EndIf(cAvidaContext& ctx) { 
+  return true; 
+}
+
+
+/*! A generic broadcast method, to simplify the development of different range
+ broadcasts.
+ */
+bool cHardwareCPU::BroadcastX(cAvidaContext& ctx, int depth) {
+	const int label_reg = FindModifiedRegister(REG_BX);
+  const int data_reg = FindNextRegister(label_reg);
+  
+  cOrgMessage msg = cOrgMessage(m_organism);
+  msg.SetLabel(GetRegister(label_reg));
+  msg.SetData(GetRegister(data_reg));
+  return m_organism->BroadcastMessage(ctx, msg, depth);
+}
+
+
+/*! A single-hop broadcast instruction - send a message to all 1-hop neighbors
+ of this organism.
+ */
+bool cHardwareCPU::Inst_Broadcast1(cAvidaContext& ctx) {
+  return BroadcastX(ctx, 1);
+}
+
+
+/*! A double-hop broadcast instruction - send a message to all 2-hop neighbors
+ of this organism.
+ */
+bool cHardwareCPU::Inst_Broadcast2(cAvidaContext& ctx) {
+  return BroadcastX(ctx, 2);
+}
+
+
+/*! Another broadcast instruction variant - send a message to all 4-hop neighbors
+ of this organism.
+ */
+bool cHardwareCPU::Inst_Broadcast4(cAvidaContext& ctx) {
+  return BroadcastX(ctx, 4);
+}
+
+
+/*! Another broadcast instruction variant - send a message to all 8-hop neighbors
+ of this organism.
+ */
+bool cHardwareCPU::Inst_Broadcast8(cAvidaContext& ctx) {
+  return BroadcastX(ctx, 8);
+}

Modified: development/source/cpu/cHardwareCPU.h
===================================================================
--- development/source/cpu/cHardwareCPU.h	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/cpu/cHardwareCPU.h	2009-02-20 16:10:36 UTC (rev 3151)
@@ -339,6 +339,21 @@
   bool Inst_IfANotEqC(cAvidaContext& ctx);
   bool Inst_IfGrX(cAvidaContext& ctx);
   bool Inst_IfEquX(cAvidaContext& ctx);
+
+	// Probabilistic ifs.
+	bool Inst_IfP0p125(cAvidaContext& ctx);
+	bool Inst_IfP0p25(cAvidaContext& ctx);
+	bool Inst_IfP0p50(cAvidaContext& ctx);
+	bool Inst_IfP0p75(cAvidaContext& ctx);
+	
+	// If-less-else-if, else, endif
+  cHeadCPU Find(const char* instr);
+  void Else_TopHalf();
+  bool Inst_IfLessEnd(cAvidaContext& ctx);
+  bool Inst_IfNotEqualEnd(cAvidaContext& ctx);
+  bool Inst_IfGrtEquEnd(cAvidaContext& ctx);
+  bool Inst_Else(cAvidaContext& ctx);
+  bool Inst_EndIf(cAvidaContext& ctx);	
   
   bool Inst_JumpF(cAvidaContext& ctx);
   bool Inst_JumpB(cAvidaContext& ctx);
@@ -646,7 +661,7 @@
   bool Inst_Numberate24(cAvidaContext& ctx) { return Do_Numberate(ctx, 24); };
   bool Do_Numberate(cAvidaContext& ctx, int num_bits=0);
 
-    // Helper functions //
+	// Helper functions //
   bool IsActivePromoter();
   void NextPromoter();
   int  Numberate(int _pos, int _dir, int _num_bits = 0);
@@ -663,6 +678,11 @@
   //// Messaging ////
   bool Inst_SendMessage(cAvidaContext& ctx);
   bool Inst_RetrieveMessage(cAvidaContext& ctx);
+  bool BroadcastX(cAvidaContext& ctx, int depth);
+  bool Inst_Broadcast1(cAvidaContext& ctx);
+  bool Inst_Broadcast2(cAvidaContext& ctx);
+  bool Inst_Broadcast4(cAvidaContext& ctx);
+  bool Inst_Broadcast8(cAvidaContext& ctx);
   
   //// Alarm ////
   bool Inst_Alarm_MSG_local(cAvidaContext& ctx);
@@ -672,7 +692,6 @@
   bool Inst_Alarm_Label(cAvidaContext& ctx);
   bool Jump_To_Alarm_Label(int jump_label);
 
-  
   //// Placebo ////
   bool Inst_Skip(cAvidaContext& ctx);
 
@@ -755,6 +774,13 @@
   std::pair<unsigned int, unsigned int> m_flash_info;
   //! Cycle timer; counts the number of cycles this virtual CPU has executed.
   unsigned int m_cycle_counter;	
+		
+	// -------- Neighborhood-sensing support --------
+public:	
+  //! Loads the current neighborhood into the organism's memory.
+  bool Inst_GetNeighborhood(cAvidaContext& ctx);
+	//! Test if the current neighborhood has changed from that in the organism's memory.
+	bool Inst_IfNeighborhoodChanged(cAvidaContext& ctx);
 };
 
 

Modified: development/source/cpu/cTestCPUInterface.h
===================================================================
--- development/source/cpu/cTestCPUInterface.h	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/cpu/cTestCPUInterface.h	2009-02-20 16:10:36 UTC (rev 3151)
@@ -92,7 +92,7 @@
   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 BroadcastMessage(cOrgMessage& msg, int depth) { return false; }
 	bool BcastAlarm(int jump_label, int bcast_range) { return false; }
   void DivideOrgTestamentAmongDeme(double value) {;}
 	void SendFlash() { }

Modified: development/source/main/cDeme.cc
===================================================================
--- development/source/main/cDeme.cc	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cDeme.cc	2009-02-20 16:10:36 UTC (rev 3151)
@@ -812,62 +812,3 @@
   //  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	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cDeme.h	2009-02-20 16:10:36 UTC (rev 3151)
@@ -347,9 +347,6 @@
   void IncreaseEnergyDonated(double amount) { assert(amount >=0); total_energy_donated += amount; }
   void IncreaseEnergyReceived(double amount) { assert(amount >=0); total_energy_received += amount; }
   void IncreaseEnergyApplied(double amount) { assert(amount >=0); total_energy_applied += amount; }
-
-	
-  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	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cOrgInterface.h	2009-02-20 16:10:36 UTC (rev 3151)
@@ -102,7 +102,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 BroadcastMessage(cOrgMessage& msg, int depth) = 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	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cOrganism.cc	2009-02-20 16:10:36 UTC (rev 3151)
@@ -781,31 +781,29 @@
 }
 
 
-// Broadcast a message - slightly modified version of SendMessage
-bool cOrganism::BroadcastMessage(cAvidaContext& ctx, cOrgMessage& msg)
-{
+/*! Broadcast a message to all organisms out to the given depth. */
+bool cOrganism::BroadcastMessage(cAvidaContext& ctx, cOrgMessage& msg, int depth) {
   assert(m_interface);
   InitMessaging();
- 
-  // If we're able to succesfully send the message...
-  if(m_interface->BroadcastMessage(msg)) {
-    // If we're remembering messages
+	
+	if(m_interface->BroadcastMessage(msg, depth)) {
+		// If we're remembering messages
     if (m_world->GetConfig().ORGANISMS_REMEMBER_MESSAGES.Get()) {
       // 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.
       m_msg->sent.back().SetReceiver(0);
-    }
-    // stat-tracking...  NOTE: this has receiver not specified, so may be a problem for predicates
+    }		
+		// 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()
+	
+	return false;
+}
 
 
 void cOrganism::ReceiveMessage(cOrgMessage& msg)
@@ -929,3 +927,40 @@
   m_world->GetStats().SentFlash(*this);
   DoOutput(ctx);
 }
+
+
+cOrganism::Neighborhood cOrganism::GetNeighborhood() {
+	Neighborhood neighbors;
+	for(int i=0; i<GetNeighborhoodSize(); ++i, Rotate(1)) {
+		if(IsNeighborCellOccupied()) {
+			neighbors.insert(GetNeighbor()->GetID());
+		}
+	}	
+	return neighbors;
+}
+
+
+void cOrganism::LoadNeighborhood() {
+	InitNeighborhood();
+	m_neighborhood->neighbors = GetNeighborhood();
+	m_neighborhood->loaded = true;
+}
+
+
+bool cOrganism::HasNeighborhoodChanged() {
+	InitNeighborhood();
+	// Must have loaded the neighborhood first:
+	if(!m_neighborhood->loaded) return false;
+	
+	// Ok, get the symmetric difference between the old neighborhood and the current neighborhood:
+	Neighborhood symdiff;
+	Neighborhood current = GetNeighborhood();	
+	std::set_symmetric_difference(m_neighborhood->neighbors.begin(),
+																m_neighborhood->neighbors.end(),
+																current.begin(),
+																current.end(),
+																std::insert_iterator<Neighborhood>(symdiff, symdiff.begin()));
+	
+	// If the symmetric difference is empty, then nothing has changed -- return 
+	return !symdiff.empty();
+}

Modified: development/source/main/cOrganism.h
===================================================================
--- development/source/main/cOrganism.h	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cOrganism.h	2009-02-20 16:10:36 UTC (rev 3151)
@@ -26,10 +26,11 @@
 #ifndef cOrganism_h
 #define cOrganism_h
 
+#include <deque>
 #include <iostream>
+#include <set>
 #include <string>
 #include <vector>
-#include <deque>
 
 #ifndef cCPUMemory_h
 #include "cCPUMemory.h"
@@ -384,7 +385,8 @@
   
   //! 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 attempts to broadcast a message.
+  bool BroadcastMessage(cAvidaContext& ctx, cOrgMessage& msg, int depth);
   //! 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.
@@ -393,7 +395,9 @@
   const message_list_type& GetReceivedMessages() { InitMessaging(); return m_msg->received; }
   //! Returns the list of all messages sent by this organism.
   const message_list_type& GetSentMessages() { InitMessaging(); return m_msg->sent; }
-  
+	//! Use at your own rish; clear all the message buffers.
+	void FlushMessageBuffers() { InitMessaging(); m_msg->sent.clear(); m_msg->received.clear(); }
+
 private:
   /*! Contains all the different data structures needed to support messaging within
   cOrganism.  Inspired by cNetSupport (above), the idea is to minimize impact on
@@ -487,6 +491,27 @@
   void SendFlash(cAvidaContext& ctx);
   // -------- End of synchronization support --------	
 
+	
+	// -------- Neighborhood support --------
+public:
+	typedef std::set<int> Neighborhood; //!< Typedef for a neighborhood snapshot.
+	//! Get the current neighborhood.
+	Neighborhood GetNeighborhood();
+	//! Loads this organism's current neighborhood into memory.
+	void LoadNeighborhood();
+	//! Has the current neighborhood changed from what is in memory?
+	bool HasNeighborhoodChanged();
+	
+protected:
+	//! Initialize neighborhood support.
+	inline void InitNeighborhood() { if(!m_neighborhood) { m_neighborhood = new cNeighborhoodSupport(); } }
+	//! Container for neighborhood support.
+	struct cNeighborhoodSupport {
+		cNeighborhoodSupport() : loaded(false) { }
+		bool loaded;
+		Neighborhood neighbors;
+	};
+	cNeighborhoodSupport* m_neighborhood; //!< Lazily-initialized pointer to the neighborhood data.
 
 
 	// -------- Internal Support Methods --------

Modified: development/source/main/cPopulationCell.cc
===================================================================
--- development/source/main/cPopulationCell.cc	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cPopulationCell.cc	2009-02-20 16:10:36 UTC (rev 3151)
@@ -116,6 +116,26 @@
   }
 }
 
+/*! This method recursively builds a set of cells that neighbor this cell, out to 
+ the given depth.  The set must be passed in by-reference, as calls to this method 
+ must share a common set of already-visited cells.
+ */
+void cPopulationCell::GetNeighboringCells(std::set<cPopulationCell*>& cell_set, int depth) const {
+	typedef std::set<cPopulationCell*> cell_set_t;
+  
+  // For each cell in our connection list...
+  tConstListIterator<cPopulationCell> i(m_connections);
+  while(!i.AtEnd()) {
+		// store the cell pointer, and check to see if we've already visited that cell...
+    cPopulationCell* cell = i.Next();
+		std::pair<cell_set_t::iterator, bool> ins = cell_set.insert(cell);
+		// and if so, recurse to it...
+		if(ins.second && (depth > 1)) {
+			cell->GetNeighboringCells(cell_set, depth-1);
+		}
+	}
+}
+
 /*! These values are chosen so as to make loops on the facing 'easy'.
 111 = NE
 101 = E

Modified: development/source/main/cPopulationCell.h
===================================================================
--- development/source/main/cPopulationCell.h	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cPopulationCell.h	2009-02-20 16:10:36 UTC (rev 3151)
@@ -27,6 +27,7 @@
 #define cPopulationCell_h
 
 #include <fstream>
+#include <set>
 
 #ifndef cMutationRates_h
 #include "cMutationRates.h"
@@ -95,6 +96,8 @@
   inline cOrganism* GetOrganism() const { return m_organism; }
   inline cHardwareBase* GetHardware() const { return m_hardware; }
   inline tList<cPopulationCell>& ConnectionList() { return m_connections; }
+	//! Recursively build a set of cells that neighbor this one, out to the given depth.
+  void GetNeighboringCells(std::set<cPopulationCell*>& cell_set, int depth) const;
   inline cPopulationCell& GetCellFaced() { return *(m_connections.GetFirst()); }
   int GetFacing();  // Returns the facing of this cell.
   inline void GetPosition(int& x, int& y) { x = m_x; y = m_y; } // Retrieves the position (x,y) coordinates of this cell.

Modified: development/source/main/cPopulationInterface.cc
===================================================================
--- development/source/main/cPopulationInterface.cc	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cPopulationInterface.cc	2009-02-20 16:10:36 UTC (rev 3151)
@@ -287,42 +287,30 @@
   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()
 
+/*! Send a message to the faced organism, failing if this cell does not have 
+ neighbors or if the cell currently faced is not occupied. */
+bool cPopulationInterface::BroadcastMessage(cOrgMessage& msg, int depth) {
+  cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
+  assert(cell.IsOccupied()); // This organism; sanity.
+	
+	// Get the set of cells that are within range.
+	std::set<cPopulationCell*> cell_set;
+	cell.GetNeighboringCells(cell_set, depth);
+	
+	// Remove this cell from the set!
+	cell_set.erase(&cell);
+	
+	// Now, send a message to each organism living in that set of cells.
+	for(std::set<cPopulationCell*>::iterator i=cell_set.begin(); i!=cell_set.end(); ++i) {
+		if((*i)->IsOccupied()) {
+			(*i)->GetOrganism()->ReceiveMessage(msg);
+		}
+	}
+	return true;
+}
 
-// 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	2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cPopulationInterface.h	2009-02-20 16:10:36 UTC (rev 3151)
@@ -107,7 +107,7 @@
   //! Send a message to the faced organism.
   bool SendMessage(cOrgMessage& msg);
   bool SendMessage(cOrganism* recvr, cOrgMessage& msg);
-  bool BroadcastMessage(cOrgMessage& msg);
+  bool BroadcastMessage(cOrgMessage& msg, int depth);
   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