[Avida-SVN] r3239 - in development/source: actions cpu main tools viewer-core

hjg at myxo.css.msu.edu hjg at myxo.css.msu.edu
Mon May 18 13:15:08 PDT 2009


Author: hjg
Date: 2009-05-18 16:15:08 -0400 (Mon, 18 May 2009)
New Revision: 3239

Modified:
   development/source/actions/PrintActions.cc
   development/source/cpu/cHardwareCPU.cc
   development/source/cpu/cHardwareCPU.h
   development/source/cpu/cTestCPU.h
   development/source/cpu/cTestCPUInterface.h
   development/source/main/cAvidaConfig.h
   development/source/main/cEnvironment.h
   development/source/main/cOrgInterface.h
   development/source/main/cOrganism.cc
   development/source/main/cOrganism.h
   development/source/main/cPopulationInterface.cc
   development/source/main/cPopulationInterface.h
   development/source/main/cStats.cc
   development/source/main/cStats.h
   development/source/main/cTaskLib.cc
   development/source/main/cTaskLib.h
   development/source/tools/cString.h
   development/source/viewer-core/cCoreView_Info.cc
Log:
A set of instructions, tasks, and stats that support reputation-based altruism. Specifically, they support creating and donating different types of strings. A more thorough description of thier uses can be found in Decomposition Using Indirect Reciprocity in Evolved Populations by Heather Goldsby, Sherri Goings, Jeff Clune, and Charles Ofria. Additionally, a new consistency test that makes sure all the reputation infrastructure is working. 

Modified: development/source/actions/PrintActions.cc
===================================================================
--- development/source/actions/PrintActions.cc	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/actions/PrintActions.cc	2009-05-18 20:15:08 UTC (rev 3239)
@@ -131,6 +131,10 @@
 STATS_OUT_FILE(PrintDynamicMaxMinData,		maxmin.dat			);
 STATS_OUT_FILE(PrintNumOrgsKilledData,      orgs_killed.dat);
 
+// reputation
+STATS_OUT_FILE(PrintReputationData,         reputation.dat);
+STATS_OUT_FILE(PrintDirectReciprocityData,         reciprocity.dat);
+STATS_OUT_FILE(PrintStringMatchData,         stringmatch.dat);
 
 #define POP_OUT_FILE(METHOD, DEFAULT)                                                     /*  1 */ \
 class cAction ## METHOD : public cAction {                                                /*  2 */ \
@@ -3136,6 +3140,11 @@
   action_lib->Register<cActionDumpTaskGrid>("dump_task_grid");
   action_lib->Register<cActionDumpDonorGrid>("dump_donor_grid");
   action_lib->Register<cActionDumpReceiverGrid>("dump_receiver_grid");
+	
+	// Reputation
+  action_lib->Register<cActionPrintReputationData>("PrintReputationData");
+	action_lib->Register<cActionPrintDirectReciprocityData>("PrintDirectReciprocityData");
+  action_lib->Register<cActionPrintStringMatchData>("PrintStringMatchData");
 
   action_lib->Register<cActionSetVerbose>("VERBOSE");
 }

Modified: development/source/cpu/cHardwareCPU.cc
===================================================================
--- development/source/cpu/cHardwareCPU.cc	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/cpu/cHardwareCPU.cc	2009-05-18 20:15:08 UTC (rev 3239)
@@ -542,6 +542,29 @@
 		tInstLibEntry<tMethod>("get-neighborhood", &cHardwareCPU::Inst_GetNeighborhood, nInstFlag::STALL),
 		tInstLibEntry<tMethod>("if-neighborhood-changed", &cHardwareCPU::Inst_IfNeighborhoodChanged, nInstFlag::STALL),
 		
+		
+		// Reputation instructions
+		
+  	tInstLibEntry<tMethod>("donate-frm", &cHardwareCPU::Inst_DonateFacingRawMaterials, nInstFlag::STALL),
+  	tInstLibEntry<tMethod>("donate-spec", &cHardwareCPU::Inst_DonateFacingRawMaterialsOtherSpecies, nInstFlag::STALL),
+  	tInstLibEntry<tMethod>("donate-if-donor", &cHardwareCPU::Inst_DonateIfDonor, nInstFlag::STALL),		
+  	tInstLibEntry<tMethod>("donate-string", &cHardwareCPU::Inst_DonateFacingString, nInstFlag::STALL),		
+		
+    tInstLibEntry<tMethod>("get-neighbors-reputation", &cHardwareCPU::Inst_GetNeighborsReputation, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("get-reputation", &cHardwareCPU::Inst_GetReputation, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("get-raw-mat-amount", &cHardwareCPU::Inst_GetAmountOfRawMaterials, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("get-other-raw-mat-amount", &cHardwareCPU::Inst_GetAmountOfOtherRawMaterials, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("pose", &cHardwareCPU::Inst_Pose, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("rotate-to-rep", &cHardwareCPU::Inst_RotateToGreatestReputation, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("rotate-to-rep-and-donate", &cHardwareCPU::Inst_RotateToGreatestReputationAndDonate, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("rotate-to-rep-tag", &cHardwareCPU::Inst_RotateToGreatestReputationWithDifferentTag, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("rotate-to-rep-lineage", &cHardwareCPU::Inst_RotateToGreatestReputationWithDifferentLineage, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("rotate-to-tag", &cHardwareCPU::Inst_RotateToDifferentTag, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("if-donor",  &cHardwareCPU::Inst_IfDonor, nInstFlag::STALL),
+		tInstLibEntry<tMethod>("prod-string",  &cHardwareCPU::Inst_ProduceString, nInstFlag::STALL),
+		
+		
+		
     // Must always be the last instruction in the array
     tInstLibEntry<tMethod>("NULL", &cHardwareCPU::Inst_Nop, 0, "True no-operation instruction: does nothing"),
   };
@@ -8247,3 +8270,378 @@
 bool cHardwareCPU::Inst_Broadcast8(cAvidaContext& ctx) {
   return BroadcastX(ctx, 8);
 }
+
+
+
+/* Donate if the neighbor previously donated to the organism. */
+bool cHardwareCPU::Inst_DonateIfDonor(cAvidaContext& ctx)
+{
+  cOrganism * neighbor = m_organism->GetNeighbor();
+	if (neighbor != NULL) {
+		// check if the neighbor was a donor
+		if (m_organism->IsDonor(neighbor->GetID())) {
+			m_world->GetStats().IncDonateToDonor();
+			Inst_DonateFacingRawMaterialsOtherSpecies(ctx);	
+		}
+	}
+	return true;
+}
+
+/* Donate raw materials (of one kind) to a neighbor, but 
+ only if the neighbor is of a different species. If the 
+ instruction fails, there is no consequence. */
+bool cHardwareCPU::Inst_DonateFacingRawMaterialsOtherSpecies(cAvidaContext& ctx) 
+{ 
+	cOrganism * neighbor = m_organism->GetNeighbor();
+	if (neighbor != NULL) {
+		
+		int spec_self =  m_organism->GetLineageLabel();
+		int spec_neighbor = neighbor->GetLineageLabel();
+		
+		if (spec_self != spec_neighbor) {
+			Inst_DonateFacingString(ctx);	
+		}
+	}
+	return true;
+}
+
+/* Donate a string that you have produced to the facing organism */
+bool cHardwareCPU::Inst_DonateFacingString(cAvidaContext& ctx)
+{
+	// Get faced neighbor
+  cOrganism * neighbor = m_organism->GetNeighbor();
+	int cost = m_world->GetConfig().ALT_COST.Get(); 
+	int my_string = m_organism->GetLineageLabel();
+	
+	
+  // Donate only if we have found a neighbor.
+  if (neighbor != NULL) {
+		
+    // Check if the organism has enough of this string on hand.
+		if ((m_organism->GetNumberStringsOnHand(my_string) >= cost) && (neighbor->CanReceiveString(my_string, cost))) { 
+			
+			// sometimes the donation will fail. 
+			// get the probability of failure
+			int prob_fail = m_world->GetConfig().DONATION_FAILURE_PERCENT.Get(); 
+			unsigned int rand_num = m_world->GetRandom().GetUInt(0, 100); 
+			// neighbor donates to organism.
+			if (rand_num < prob_fail) { 
+				// EXIT
+				return true; 
+			}
+			
+			
+			m_organism->DonateString(my_string, cost);
+			neighbor->AddOtherRawMaterials(cost, m_organism->GetID()); 
+			neighbor->ReceiveString(my_string, cost, m_organism->GetID()); 
+			neighbor->AddDonatedLineage(m_organism->GetLineageLabel());
+			
+			// track stats
+			m_organism->Donated();
+			
+			ComputeReputation();			
+		}
+  }
+  return true;
+	
+	
+}
+
+/* Donate raw materials to the facing organism. */
+bool cHardwareCPU::Inst_DonateFacingRawMaterials(cAvidaContext& ctx)
+{
+  
+	// Get faced neighbor
+  cOrganism * neighbor = m_organism->GetNeighbor();
+	int cost = m_world->GetConfig().ALT_COST.Get(); 
+	
+	
+  // Donate only if we have found a neighbor.
+  if (neighbor != NULL) {
+		
+    // Subtract raw materials from the organism (currently subtracts 1 resource...)
+		// fails if the organism does not have any more resources
+		if (m_organism->SubtractSelfRawMaterials(cost)) {
+			
+			// sometimes the donation will fail. 
+			// get the probability of failure
+			int prob_fail = m_world->GetConfig().DONATION_FAILURE_PERCENT.Get(); 
+			unsigned int rand_num = m_world->GetRandom().GetUInt(0, 100); 
+			// neighbor donates to organism.
+			if (rand_num < prob_fail) { 
+				// EXIT
+				return true; 
+			}
+			
+			
+			neighbor->AddOtherRawMaterials(cost, m_organism->GetID()); 
+			neighbor->AddDonatedLineage(m_organism->GetLineageLabel());
+			
+			// rotate recipient to face donor 
+			// by rotating until the recipient faces the donor
+			// adding a new comment.
+			if (m_world->GetConfig().ROTATE_ON_DONATE.Get()) {
+				while (neighbor->GetNeighbor() != m_organism) {
+					neighbor->Rotate(1);
+				}
+			}
+			
+			
+			// track stats
+			m_organism->Donated();
+			
+			ComputeReputation();
+			
+		}
+  }
+  return true;
+}  
+
+
+
+
+/* An organism artificially increases its reputation without donating. */
+bool cHardwareCPU::Inst_Pose(cAvidaContext& ctx)
+{
+	// update reputation to include this phony donation.
+	// get the current reputation; increment by 1.	
+	m_organism->SetReputation(m_organism->GetReputation() + 1);
+	
+  return true;
+}
+
+
+
+/*! An organism's reputation is stored as an opinion. This instruction 
+ uses Inst_GetNeighborsOpinion to do the heavy lifting, but includes
+ default behavior suitable for reputations. Specifically, if an 
+ neighbor has no reputation (i.e., it has not donated) or does not
+ exist, then this instruction puts zeros into the registers.
+ */
+bool cHardwareCPU::Inst_GetNeighborsReputation(cAvidaContext& ctx)
+{
+  // Get faced neighbor
+  cOrganism * neighbor = m_organism->GetNeighbor();
+  if (neighbor != NULL) { 
+		const int raw_mat_reg = FindModifiedRegister(REG_AX);
+		GetRegister(raw_mat_reg) = neighbor->GetReputation();	
+	} 
+  return true;
+}
+
+
+/*! An organism's reputation is stored as an opinion. This instruction 
+ uses Inst_GetOpinion to do the heavy lifting, but includes
+ default behavior suitable for reputations. Specifically, if an 
+ organism has no reputation (i.e., it has not donated), then this 
+ instruction puts zeros into the registers.
+ */
+bool cHardwareCPU::Inst_GetReputation(cAvidaContext& ctx)
+{
+	const int opinion_reg = FindModifiedRegister(REG_BX);
+	GetRegister(opinion_reg) = m_organism->GetReputation();
+	return true;
+}
+
+/* Sense the number of raw materials an organism has. Store in
+ ?REG_AX? */
+bool cHardwareCPU::Inst_GetAmountOfRawMaterials(cAvidaContext& ctx)
+{
+	const int raw_mat_reg = FindModifiedRegister(REG_AX);
+	GetRegister(raw_mat_reg) = m_organism->GetNumberStringsOnHand(0);
+	return true;
+}
+
+/* Sense the number of raw materials an organism has. Store in
+ ?REG_BX? */
+bool cHardwareCPU::Inst_GetAmountOfOtherRawMaterials(cAvidaContext& ctx)
+{
+	const int raw_mat_reg = FindModifiedRegister(REG_BX);
+	GetRegister(raw_mat_reg) = m_organism->GetNumberStringsOnHand(1);
+	return true;
+}
+
+
+
+/* Rotate to face the organism with the highest reputation */
+bool cHardwareCPU::Inst_RotateToGreatestReputation(cAvidaContext& ctx) 
+{
+	m_organism->GetOrgInterface().RotateToGreatestReputation();
+	
+	return true;	
+}
+
+/* Rotate to face the organism with the highest reputation that has
+ a different tag. */
+bool cHardwareCPU::Inst_RotateToGreatestReputationWithDifferentTag(cAvidaContext& ctx)
+{
+	m_organism->GetOrgInterface().RotateToGreatestReputationWithDifferentTag(m_organism->GetTagLabel());
+	return true;	
+}
+
+/* Rotate to face the organism with the highest reputation that has
+ a different lineage. */
+bool cHardwareCPU::Inst_RotateToGreatestReputationWithDifferentLineage(cAvidaContext& ctx)
+{
+	m_organism->GetOrgInterface().RotateToGreatestReputationWithDifferentLineage(m_organism->GetLineageLabel());
+	return true;	
+}
+
+
+/* Rotate to face the organism with the highest reputation and then
+ immediately donate */
+bool cHardwareCPU::Inst_RotateToGreatestReputationAndDonate(cAvidaContext& ctx) 
+{
+	Inst_RotateToGreatestReputation(ctx);
+	Inst_DonateFacingRawMaterials(ctx);
+	return true;
+}
+
+
+
+
+bool cHardwareCPU::Inst_RotateToDifferentTag(cAvidaContext& ctx)
+{
+	//get the neighborhood size
+  const int num_neighbors = m_organism->GetNeighborhoodSize();
+	
+  // Turn to face a random neighbor
+  int neighbor_id = ctx.GetRandom().GetInt(num_neighbors);
+  for (int i = 0; i < neighbor_id; i++) m_organism->Rotate(1);
+  cOrganism * neighbor = m_organism->GetNeighbor();
+	
+  int max_id = neighbor_id + num_neighbors;
+	
+  //we have not found a match yet
+  bool found = false;
+	
+  // rotate through orgs in neighborhood  
+  while (neighbor_id < max_id) {
+		neighbor = m_organism->GetNeighbor();
+		
+		//if neighbor exists, do they have a different tag?
+		if (neighbor != NULL) {
+			if (m_organism->GetTagLabel() != neighbor->GetTagLabel()) found = true;
+			
+		}
+		
+		// stop searching through the neighbors if we already found one
+		if (found == true){
+			break;
+		}
+		
+		m_organism->Rotate(1);
+		neighbor_id++;
+	}
+	
+	return true;
+}
+
+
+
+
+/* Execute the next instruction if the neighbor was a donor. */ 
+bool cHardwareCPU::Inst_IfDonor(cAvidaContext& ctx) 
+{
+	bool donor = false;
+	cOrganism * neighbor = m_organism->GetNeighbor();
+	if (neighbor != NULL) {
+		// check if the neighbor was a donor
+		if (m_organism->IsDonor(neighbor->GetID())) {
+			donor = true;
+		}
+	}
+  if (!donor)  IP().Advance();
+	
+  return true; 
+	
+}
+
+
+void cHardwareCPU::ComputeReputation() 
+{
+	cOrganism * neighbor = m_organism->GetNeighbor();
+	
+	// update reputation to include this donation.
+	// get the current reputation; increment by 1.
+	// includes a concept of standing
+	if (m_world->GetConfig().AUTO_REPUTATION.Get() == 1) {
+		int my_rep = m_organism->GetReputation();
+		m_organism->SetReputation(my_rep +1);
+		// get neighbor reputation
+		int rep = neighbor->GetReputation(); 
+		// if the organism has not yet donated, put it into bad standing
+		if (rep == 0) neighbor->SetReputation(-1);
+	} else if (m_world->GetConfig().AUTO_REPUTATION.Get() == 2) {
+		// reputation is proportional to how much you have donated/received
+		int my_rep = m_organism->GetReputation();
+		m_organism->SetReputation(my_rep +1);
+		// get neighbor reputation
+		int rep = neighbor->GetReputation(); 
+		neighbor->SetReputation(rep-1);
+	} else if (m_world->GetConfig().AUTO_REPUTATION.Get() == 3)  {
+		// set rep to 1, since the organism donated
+		m_organism->SetReputation(1);
+		// get neighbor reputation
+		int rep = neighbor->GetReputation(); 
+		// if the organism has not yet donated, put it into bad standing
+		if (rep == 0) neighbor->SetReputation(-1);		
+	} else if (m_world->GetConfig().AUTO_REPUTATION.Get() == 4) {
+		// Similar to 1, except does not include standing.
+		int my_rep = m_organism->GetReputation();
+		m_organism->SetReputation(my_rep +1);
+	}
+	
+}
+
+
+
+
+/* Check if the string in the organisms buffer corresponds to the 
+ string it is producing. If so, -1 out the buffer and increment the 
+ number of raw materials the organism has. Otherwise, do nothing. */
+bool cHardwareCPU::Inst_ProduceString(cAvidaContext& ctx)
+{
+	
+	int num = 0;
+	int max_num = 0; 
+	int max_string = -1;
+	int string_size = 0;
+	bool val; 
+	
+	m_organism->InitStringMap(); 
+	
+	// Figure out if it has produced any of the strings 
+	std::vector < cString > temp_strings = m_world->GetEnvironment().GetMatchStringsFromTask(); 
+	if (temp_strings.size()) string_size = temp_strings[0].GetSize();
+	for (unsigned int i=0; i < temp_strings.size(); i++){
+		num = m_organism->MatchOutputBuffer(temp_strings[i]); 
+		if (num > max_num) { 
+			max_num = num; 
+			max_string = i; 
+		}
+	}
+	
+	// Determine if it has to produce one in particular. 
+	if (m_world->GetConfig().SPECIALISTS.Get()) { 
+		if (m_organism->GetLineageLabel() != max_string) { 
+			max_num = 0;
+		}
+	}
+	
+	
+	// If still ok, add the raw material and clear the buffer
+	if (max_num == string_size) { 
+		// Indicate organism has produced the string
+		val = m_organism->ProduceString(max_string); 
+		
+		// temp until old code is phased out: 
+		m_organism->AddSelfRawMaterials(1); 
+		
+		// Clear buffer if the organism has received credit for the string
+		if (val) m_organism->SetOutputNegative1(); 
+	}
+	
+	return true;
+}
+

Modified: development/source/cpu/cHardwareCPU.h
===================================================================
--- development/source/cpu/cHardwareCPU.h	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/cpu/cHardwareCPU.h	2009-05-18 20:15:08 UTC (rev 3239)
@@ -704,6 +704,54 @@
   bool Inst_Alarm_MSG_Bit_Cons24_multihop(cAvidaContext& ctx);
   bool Inst_Alarm_Label(cAvidaContext& ctx);
   bool Jump_To_Alarm_Label(int jump_label);
+	
+	
+	// -------- Reputation support --------
+  /* These instructions interact with the "reputation" support in cOrganism.h.  They 
+	 are  based on the donate instructions. However, these instructions donate
+	 "raw materials" rather than merit and will eventually be used to support 
+	 reputation based cooperation.
+	 */ 
+  // Donate a raw material to the neighbor
+  bool Inst_DonateFacingRawMaterials(cAvidaContext& ctx);
+	// Donate a raw material to the neighbor if it is another species
+	bool Inst_DonateFacingRawMaterialsOtherSpecies(cAvidaContext& ctx);
+	// Donate a raw material to the neighbor if it was a prior donor
+	bool Inst_DonateIfDonor(cAvidaContext& ctx);	
+	// Donate a string to the neighbor, if it's reputation is > 0
+	bool Inst_DonateStringIfDonorRep(cAvidaContext& ctx);		
+	// Donate a string to a neighbor
+	bool Inst_DonateFacingString(cAvidaContext& ctx);
+	
+	// Rotate to the organims with the greatest reputation
+	bool Inst_RotateToGreatestReputation(cAvidaContext& ctx);	
+	// Rotate to the organims with the greatest reputation that has a different tag
+	bool Inst_RotateToGreatestReputationWithDifferentTag(cAvidaContext& ctx);	
+	// Rotate to the organims with the greatest reputation that has a different tag
+	bool Inst_RotateToGreatestReputationWithDifferentLineage(cAvidaContext& ctx);		
+	// Rotate to an organim with a different tag
+	bool Inst_RotateToDifferentTag(cAvidaContext& ctx);	
+	// Rotate to the organims with the greatest reputation and donate
+	bool Inst_RotateToGreatestReputationAndDonate(cAvidaContext& ctx);	
+  // Get a neighbor's reputation
+  bool Inst_GetNeighborsReputation(cAvidaContext& ctx);
+  // Get the organism's reputation
+  bool Inst_GetReputation(cAvidaContext& ctx);	
+	// Execute the following instruction if the facing neighbor was a donor
+	bool Inst_IfDonor(cAvidaContext& ctx);
+	// Produce string
+	bool Inst_ProduceString(cAvidaContext& ctx);
+  // Get the organism's raw material level
+  bool Inst_GetAmountOfRawMaterials(cAvidaContext& ctx);
+  // Get the number of raw materials the organism 
+	// has gotten from others
+  bool Inst_GetAmountOfOtherRawMaterials(cAvidaContext& ctx);	
+  // Pretend to donate
+  bool Inst_Pose(cAvidaContext& ctx);
+	
+	// Reputation
+	void ComputeReputation();
+	
 
   //// Placebo ////
   bool Inst_Skip(cAvidaContext& ctx);
@@ -794,6 +842,8 @@
   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/cTestCPU.h
===================================================================
--- development/source/cpu/cTestCPU.h	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/cpu/cTestCPU.h	2009-05-18 20:15:08 UTC (rev 3239)
@@ -116,6 +116,8 @@
   // Used by cTestCPUInterface to get/update resources
   void ModifyResources(const tArray<double>& res_change);
   cResourceCount& GetResourceCount() { return m_resource_count; }
+	
+
 };
 
 #ifdef ENABLE_UNIT_TESTS

Modified: development/source/cpu/cTestCPUInterface.h
===================================================================
--- development/source/cpu/cTestCPUInterface.h	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/cpu/cTestCPUInterface.h	2009-05-18 20:15:08 UTC (rev 3239)
@@ -97,6 +97,10 @@
 	bool BcastAlarm(int jump_label, int bcast_range) { return false; }
   void DivideOrgTestamentAmongDeme(double value) {;}
 	void SendFlash() { }
+	
+	void RotateToGreatestReputation(){ }
+	void RotateToGreatestReputationWithDifferentTag(int tag){ }
+	void RotateToGreatestReputationWithDifferentLineage(int tag){ }	
   
   int GetStateGridID(cAvidaContext& ctx);
 };

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cAvidaConfig.h	2009-05-18 20:15:08 UTC (rev 3239)
@@ -619,6 +619,23 @@
 	
   CONFIG_ADD_CUSTOM_FORMAT(INST_SET_NEW, "Instruction Set Definition");
   CONFIG_ADD_FORMAT_VAR(INST, "Instruction entry in the instruction set");
+	
+	
+	//--------- Reputation config options --------------
+	CONFIG_ADD_CUSTOM_FORMAT(REPUTATION_GROUP, "Reputation Settings");
+  CONFIG_ADD_VAR(RAW_MATERIAL_AMOUNT, int, 100, "Number of raw materials an organism starts with");
+  CONFIG_ADD_VAR(AUTO_REPUTATION, int, 0, "Is an organism's reputation automatically computed based on its donations\n0=no\n1=increment for each donation + standing\n2=+1 for donations given -1 for donations received\n3=1 for donors -1 for recivers who have not donated\n4=+1 for donors\n5=+1 for donors during task check");
+  CONFIG_ADD_VAR(ALT_BENEFIT, int, 1.00, "Number multiplied by the number of raw materials received from another organism to compute reward");
+  CONFIG_ADD_VAR(ALT_COST, int, 1.00, "Number multiplied by the number of your raw materials");
+  CONFIG_ADD_VAR(ROTATE_ON_DONATE, int, 0, "Rotate an organism to face its donor 0/1 (off/on)");
+  CONFIG_ADD_VAR(REPUTATION_REWARD, int, 0, "Reward an organism for having a good reputation");
+  CONFIG_ADD_VAR(DONATION_FAILURE_PERCENT, int, 0, "Percentage of times that a donation fails");
+  CONFIG_ADD_VAR(RANDOMIZE_RAW_MATERIAL_AMOUNT, int, 0, "Should all the organisms receive the same amount 0/1 (off/on)");
+  CONFIG_ADD_VAR(DONATION_RESTRICTIONS, int, 0, "0=none\n1=inter-species only\n2=different tag only");
+  CONFIG_ADD_VAR(INHERIT_REPUTATION, int, 0, "0=reputations are not inherited\n1=reputations are inherited\n2=tags are inherited");
+  CONFIG_ADD_VAR(SPECIALISTS, int, 0, "0=generalists allowed\n1=only specialists");
+  CONFIG_ADD_VAR(STRING_AMOUNT_CAP, int, -1, "-1=no cap on string amounts\n#=CAP");
+  CONFIG_ADD_VAR(MATCH_ALREADY_PRODUCED, int, 0, "0=off\n1=on");
   
 #endif
   

Modified: development/source/main/cEnvironment.h
===================================================================
--- development/source/main/cEnvironment.h	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cEnvironment.h	2009-05-18 20:15:08 UTC (rev 3239)
@@ -156,6 +156,9 @@
   const cTaskEntry& GetTask(int id) const { return m_tasklib.GetTask(id); }
   bool UseNeighborInput() const { return m_tasklib.UseNeighborInput(); }
   bool UseNeighborOutput() const { return m_tasklib.UseNeighborOutput(); }
+	vector<cString> GetMatchStringsFromTask() { return m_tasklib.GetMatchStrings(); }
+	cString GetMatchString(int x) { return m_tasklib.GetMatchString(x); }
+	int GetNumberOfMatchStrings() { return m_tasklib.GetNumberOfMatchStrings(); }	
 
   
   int GetNumReactions() const { return reaction_lib.GetSize(); }

Modified: development/source/main/cOrgInterface.h
===================================================================
--- development/source/main/cOrgInterface.h	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cOrgInterface.h	2009-05-18 20:15:08 UTC (rev 3239)
@@ -110,6 +110,10 @@
 	virtual void SendFlash() = 0;
   
   virtual int GetStateGridID(cAvidaContext& ctx) = 0;
+	virtual void RotateToGreatestReputation() =0;
+	virtual void RotateToGreatestReputationWithDifferentTag(int tag) =0;
+	virtual void RotateToGreatestReputationWithDifferentLineage(int line) =0;	
+	
 };
 
 #endif

Modified: development/source/main/cOrganism.cc
===================================================================
--- development/source/main/cOrganism.cc	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cOrganism.cc	2009-05-18 20:15:08 UTC (rev 3239)
@@ -1000,3 +1000,212 @@
 	// If the symmetric difference is empty, then nothing has changed -- return 
 	return !symdiff.empty();
 }
+
+
+/* Called when raw materials are donated to others or when the 
+ raw materials are consumed. Amount is the number of resources 
+ donated. The boolean flag is used to indicate if the donation 
+ was successful... It would fail if the organism did not have 
+ that many resources. */
+bool cOrganism::SubtractSelfRawMaterials (int amount)
+{
+	bool isSuccessful = false;
+	if (amount <= m_self_raw_materials) { 
+		isSuccessful = true; 
+		m_self_raw_materials -= amount;
+	}
+	return isSuccessful;
+}
+
+
+/* Called when other raw materials are consumed. Amount is the 
+ number of resources consumed. The boolean flag is used to 
+ indicate if the donation was successful... It would fail if 
+ the organism did not have that many resources. */
+bool cOrganism::SubtractOtherRawMaterials (int amount)
+{
+	bool isSuccessful = false;
+	if (amount <= m_other_raw_materials) { 
+		isSuccessful = true; 
+		m_other_raw_materials -= amount;
+	}
+	return isSuccessful;
+}
+
+/* Called when raw materials are received from others. Amount 
+ is the number of resources received. The boolean flag is used 
+ to indicate if the reception was successful, which should always
+ be the case... */
+
+bool cOrganism::AddOtherRawMaterials (int amount, int donor_id) {
+	bool isSuccessful = true;
+	m_other_raw_materials += amount;
+	donor_list.insert(donor_id);
+	m_num_donate_received += amount;	
+	m_amount_donate_received++;	
+	return isSuccessful;
+}
+
+/* Called when raw materials are received from others. Amount 
+ is the number of resources received. The boolean flag is used 
+ to indicate if the reception was successful, which should always
+ be the case... 
+ 
+ This version is used if there is only one resource that is both
+ donated and recieved.
+ */
+
+bool cOrganism::AddRawMaterials (int amount, int donor_id) {
+	bool isSuccessful = true;
+	m_self_raw_materials += amount;
+	donor_list.insert(donor_id);	
+	m_num_donate_received += amount;
+	m_amount_donate_received++;
+	return isSuccessful;
+}
+
+
+/* Get an organism's reputation, which is expressed as an 
+ opinion. 0 is the default reputation (this should be refactored
+ to be cleaner). */
+int cOrganism::GetReputation() {
+	int rep =0;
+	if (HasOpinion()) {
+		rep = GetOpinion().first;
+	}
+	return rep;
+}
+
+/* Set an organism's reputation */
+void cOrganism::SetReputation(int rep) {
+	SetOpinion(rep);
+	return;
+}
+
+/* An organism's reputation is based on a running average*/
+void cOrganism::SetAverageReputation(int rep){
+	int current_total = GetReputation() * m_opinion->opinion_list.size(); 
+	int new_rep = (current_total + rep)/(m_opinion->opinion_list.size()+1);
+	SetReputation(new_rep);
+}
+
+
+/* Check if an organism has previously donated to this organism */
+bool cOrganism::IsDonor(int neighbor_id) 
+{
+	bool found = false;
+	if (donor_list.find(neighbor_id) != donor_list.end()) {
+		found = true;
+	}
+	return found;
+}
+
+
+
+/* Update the tag. If the organism was not already tagged, 
+ or the new tag is the same as the old tag, or the number
+ of bits is > than the old tag, update.*/
+void cOrganism::UpdateTag(int new_tag, int bits)
+{
+	unsigned int rand_int = m_world->GetRandom().GetUInt(0, 2);
+	if ((m_tag.first == -1) || 
+			(m_tag.first == new_tag) ||
+			(m_tag.second < bits)) {
+		m_tag = make_pair(new_tag, bits);
+	} else if ((m_tag.second == bits) && rand_int){ 		
+		m_tag = make_pair(new_tag, bits);
+	}
+}
+
+
+/* See if the output buffer matches the string */
+int cOrganism::MatchOutputBuffer(cString string_to_match)
+{
+	tBuffer<int> org_str (GetOutputBuf());
+	int num_matched =0; 
+	for (int j = 0; j < string_to_match.GetSize(); j++)
+	{
+		if (string_to_match[j]=='0' && org_str[j]==0 ||
+				string_to_match[j]=='1' && org_str[j]==1)
+			num_matched++;
+	}
+	return num_matched;
+}
+
+
+void cOrganism::SetOutputNegative1() 
+{ 
+	for (int i=0; i<GetOutputBuf().GetCapacity(); i++) {
+		AddOutput(-1);
+	}
+	m_output_buf.Clear(); 
+}
+
+/* Initialize the string tracking map */
+void cOrganism::InitStringMap() 
+{
+	if (!m_string_map.size()) { 
+		// Get the strings from the task lib. 
+		std::vector < cString > temp_strings = m_world->GetEnvironment().GetMatchStringsFromTask(); 
+		// Create structure for each of them. 
+		for (unsigned int i=0; i < temp_strings.size(); i++){
+			m_string_map[i].m_string = temp_strings[i]; 
+		}
+	}
+}
+
+
+bool cOrganism::ProduceString(int i)  
+{ 
+	bool val = false; 
+	int cap = m_world->GetConfig().STRING_AMOUNT_CAP.Get(); 
+	if ((cap == -1) || (m_string_map[i].on_hand < cap)) 
+	{
+		m_string_map[i].prod_string++; 
+		m_string_map[i].on_hand++;
+		val = true;
+	}
+	return val;
+}
+
+/* Donate a string*/
+bool cOrganism::DonateString(int string_tag, int amount)
+{
+	bool val = false; 
+	if (m_string_map[string_tag].on_hand >= amount) {
+		val = true;
+		m_string_map[string_tag].on_hand -= amount;
+	}
+	return val;
+	
+}
+
+/* Receive a string*/
+bool cOrganism::ReceiveString(int string_tag, int amount, int donor_id)
+{
+	bool val = false; 
+	int cap = m_world->GetConfig().STRING_AMOUNT_CAP.Get(); 
+	if ((cap == -1) || (m_string_map[string_tag].on_hand < cap)) 
+	{
+		m_string_map[string_tag].received_string++; 
+		m_string_map[string_tag].on_hand++;
+		donor_list.insert(donor_id);	
+		m_num_donate_received += amount;
+		m_amount_donate_received++;
+		val = true;
+	}
+	return val;
+}
+
+/* Check to see if this amount is below the organism's cap*/
+bool cOrganism::CanReceiveString(int string_tag, int amount)
+{
+	bool val = false; 
+	int cap = m_world->GetConfig().STRING_AMOUNT_CAP.Get(); 
+	if ((cap == -1) || (m_string_map[string_tag].on_hand < cap)) 
+	{
+		val = true;
+	}
+	return val;
+	
+}

Modified: development/source/main/cOrganism.h
===================================================================
--- development/source/main/cOrganism.h	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cOrganism.h	2009-05-18 20:15:08 UTC (rev 3239)
@@ -31,6 +31,7 @@
 #include <set>
 #include <string>
 #include <vector>
+#include <map>
 
 #ifndef cCPUMemory_h
 #include "cCPUMemory.h"
@@ -516,6 +517,120 @@
 	cNeighborhoodSupport* m_neighborhood; //!< Lazily-initialized pointer to the neighborhood data.
 
 
+  // -------- Reputation support --------	
+public: 
+	// Deduct amount number of self raw materials
+	bool SubtractSelfRawMaterials(int amount); 
+	// Deduct amount number of other raw materials
+	bool SubtractOtherRawMaterials(int amount); 
+	// receive raw materials from others
+	bool AddOtherRawMaterials(int amount, int donor_id);
+	// receive raw materials 
+	bool AddRawMaterials(int amount, int donor_id);
+	// receive raw materials 
+	void AddSelfRawMaterials(int amount) { if (m_self_raw_materials < 10) m_self_raw_materials += amount;}
+	// retrieve the organism's own amount of raw materials
+	int GetSelfRawMaterials() { return m_self_raw_materials; }
+	// retrieve the amount of raw materials collected from others
+	int GetOtherRawMaterials() { return m_other_raw_materials; }
+	// get the organism's reputation
+	int GetReputation(); 
+	// set the organism's reputation
+	void SetReputation(int rep);
+	// update the reputation to be an average on the basis of this new info
+	void SetAverageReputation(int rep);
+	// update the reputation by addint this new information 
+	void AddReputation(int rep) { SetReputation(GetReputation() + rep); }
+	// increment reputation
+	void IncReputation() { SetReputation(GetReputation() + 1); }
+	// get number of donors
+	int GetNumberOfDonors() { return donor_list.size(); }
+	// organism donated
+	void Donated(){m_num_donate++;}
+	// get number of donations
+	int GetNumberOfDonations() { return m_num_donate; }
+	// get number of donations received
+	int GetNumberOfDonationsReceived() { return m_num_donate_received; }
+	// get amout of donations received
+	int GetAmountOfDonationsReceived() { return m_amount_donate_received; }
+	// organism reciprocated
+	void Reciprocated() {m_num_reciprocate++;}
+	// get number of reciprocations
+	int GetNumberOfReciprocations() { return m_num_reciprocate; }
+	// was the organism a donor
+	bool IsDonor(int neighbor_id); 
+	
+	// Check if buffer contains this string; return # bits correct
+	int MatchOutputBuffer(cString string_to_match);
+	
+	// Add a donor
+	void AddDonor(int org_id) { donor_list.insert(org_id); }
+	// Set tag 
+	void SetTag(int new_tag, int bits) { m_tag = make_pair(new_tag, bits); }
+	// Set tag
+	void SetTag(pair < int, int > new_tag)  { m_tag = new_tag; }
+	// Update tag
+	void UpdateTag(int new_tag, int bits); 
+	// Get tag
+	int GetTagLabel() { return m_tag.first; }
+	pair < int, int > GetTag() { return m_tag; }
+	// Get number of failed reputation increases
+	int GetFailedReputationIncreases() { return m_failed_reputation_increases; }
+	
+	// Clear the output buffer
+	void SetOutputNegative1();
+	void AddDonatedLineage(int lin) { donating_lineages.insert(lin); }
+	int GetNumberOfDonatedLineages() { return donating_lineages.size(); }
+	void InitStringMap(); 
+	bool ProduceString(int i);  
+	int GetNumberStringsProduced(int i) { return  m_string_map[i].prod_string; }
+	int GetNumberStringsOnHand(int i) { return m_string_map[i].on_hand; }
+	bool DonateString(int string_tag, int amount); 
+	bool ReceiveString(int string_tag, int amount, int donor_id); 
+	bool CanReceiveString(int string_tag, int amount); 
+	
+protected:
+	// The organism's own raw materials
+	int m_self_raw_materials; 
+	// The raw materials an oranism has collected from others
+	int m_other_raw_materials;
+  // Organisms that have donated to this organism
+	set<int> donor_list;
+	// Strings this organism has received. 
+	set<int> donating_lineages;
+	// number of donations
+	int m_num_donate;
+	// number of donations received
+	int m_num_donate_received;
+	// amount of donations received
+	int m_amount_donate_received;
+	// number of reciprocations
+	int m_num_reciprocate;
+	// reputation minimum for donation/rotation 
+	// based on Nowak89
+	int m_k;
+	// int number of reputation increase failures
+	int m_failed_reputation_increases;
+	std::pair < int, int > m_tag;
+	
+  /*! Contains all the different data structures needed to 
+	 track strings, production of strings, and donation/trade 
+	 of strings. It is inspired by the cMessagingSupport*/
+  struct cStringSupport
+  {
+    cStringSupport() 
+		{ prod_string = 0; received_string = 0; on_hand = 0; }
+		cString m_string; //!< The string being tracked
+		int prod_string; //!< The number of times this string has been produced. 
+		int received_string; //!< The number of times this string has been received.
+		int on_hand; //!< The number of copies of the string this organism has on hand
+  };
+  
+	/* This member variable is a map of tags to strings. It can
+	 be used to track production, consumption, and donation of 
+	 strings. */
+	std::map < int, cStringSupport > m_string_map;
+	
 	// -------- Internal Support Methods --------
 private:
   void initialize(cAvidaContext& ctx);

Modified: development/source/main/cPopulationInterface.cc
===================================================================
--- development/source/main/cPopulationInterface.cc	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cPopulationInterface.cc	2009-05-18 20:15:08 UTC (rev 3239)
@@ -400,3 +400,177 @@
 {
   return ctx.GetRandom().GetUInt(m_world->GetEnvironment().GetNumStateGrids());
 }
+
+/* Rotate an organism to face the neighbor with the highest reputation */
+void cPopulationInterface::RotateToGreatestReputation() 
+{
+	
+	cPopulationCell& cell = m_world->GetPopulation().GetCell(GetCellID());
+	int high_rep=-1; 
+	vector <int> high_rep_orgs;
+	
+	
+	// loop to find the max reputation
+	for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+		const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+		// cell->organism, if occupied, check reputation, etc.
+		if (IsNeighborCellOccupied()) {
+			cOrganism* cur_neighbor = faced_cell->GetOrganism();
+			
+			// if it has high reputation	
+			if (cur_neighbor->GetReputation() >= high_rep) {
+				if (cur_neighbor->GetReputation() > high_rep) {
+					high_rep = cur_neighbor->GetReputation();
+					high_rep_orgs.clear();
+				}
+				high_rep_orgs.push_back(cur_neighbor->GetID()); 
+			} 
+		}
+		
+		// check the next neighbor
+		cell.ConnectionList().CircNext();
+	}
+	
+	// Pick an organism to donate to
+	
+	if (high_rep_orgs.size() > 0) {
+		unsigned int rand_num = m_world->GetRandom().GetUInt(0, high_rep_orgs.size()); 
+		int high_org_id = high_rep_orgs[rand_num];
+		
+		for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+			const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+			
+			if (IsNeighborCellOccupied()) {
+				
+				cOrganism* cur_neighbor = faced_cell->GetOrganism();
+				
+				// if it has high reputation	
+				if (cur_neighbor->GetID() == high_org_id) {
+					break;
+				}
+			}
+			
+			cell.ConnectionList().CircNext();
+			
+		}
+	}
+	
+}
+
+/* Rotate an organism to face the neighbor with the highest reputation 
+ where the neighbor has a different tag than the organism*/
+void cPopulationInterface::RotateToGreatestReputationWithDifferentTag(int tag) 
+{
+	
+	cPopulationCell& cell = m_world->GetPopulation().GetCell(GetCellID());
+	int high_rep=-1; 
+	vector <int> high_rep_orgs;
+	
+	// loop to find the max reputation
+	for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+		const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+		// cell->organism, if occupied, check reputation, etc.
+		if (IsNeighborCellOccupied()) {
+			cOrganism* cur_neighbor = faced_cell->GetOrganism();
+			
+			// if it has high reputation	
+			if ((cur_neighbor->GetTagLabel() != tag) && (cur_neighbor->GetReputation() >= high_rep)) {
+				if (cur_neighbor->GetReputation() > high_rep) {
+					high_rep = cur_neighbor->GetReputation();
+					high_rep_orgs.clear();
+				}
+				high_rep_orgs.push_back(cur_neighbor->GetID()); 
+			} 
+		}
+		
+		// check the next neighbor
+		cell.ConnectionList().CircNext();
+	}
+	
+	// Pick an organism to donate to
+	
+	if (high_rep_orgs.size() > 0) {
+		unsigned int rand_num = m_world->GetRandom().GetUInt(0, high_rep_orgs.size()); 
+		int high_org_id = high_rep_orgs[rand_num];
+
+		for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+			const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+			
+			if (IsNeighborCellOccupied()) {
+				
+				cOrganism* cur_neighbor = faced_cell->GetOrganism();
+				
+				// if it has high reputation	
+				if (cur_neighbor->GetID() == high_org_id) {
+					break;
+				}
+			}
+			
+			cell.ConnectionList().CircNext();
+			
+		}
+		
+		
+		
+	}
+	
+}
+
+/* Rotate an organism to face the neighbor with the highest reputation 
+ where the neighbor has a different tag than the organism*/
+void cPopulationInterface::RotateToGreatestReputationWithDifferentLineage(int line) 
+{
+	
+	cPopulationCell& cell = m_world->GetPopulation().GetCell(GetCellID());
+	int high_rep=-1; 
+	vector <int> high_rep_orgs;
+	
+	// loop to find the max reputation
+	for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+		const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+		// cell->organism, if occupied, check reputation, etc.
+		if (IsNeighborCellOccupied()) {
+			cOrganism* cur_neighbor = faced_cell->GetOrganism();
+			
+			// if it has high reputation	
+			if ((cur_neighbor->GetLineageLabel() != line) && (cur_neighbor->GetReputation() >= high_rep)) {
+				if (cur_neighbor->GetReputation() > high_rep) {
+					high_rep = cur_neighbor->GetReputation();
+					high_rep_orgs.clear();
+				}
+				high_rep_orgs.push_back(cur_neighbor->GetID()); 
+			} 
+		}
+		
+		// check the next neighbor
+		cell.ConnectionList().CircNext();
+	}
+	
+	// Pick an organism to donate to
+	
+	if (high_rep_orgs.size() > 0) {
+		unsigned int rand_num = m_world->GetRandom().GetUInt(0, high_rep_orgs.size()); 
+		int high_org_id = high_rep_orgs[rand_num];
+		
+		for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+			const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+			
+			if (IsNeighborCellOccupied()) {
+				
+				cOrganism* cur_neighbor = faced_cell->GetOrganism();
+				
+				// if it has high reputation	
+				if (cur_neighbor->GetID() == high_org_id) {
+					break;
+				}
+			}
+			
+			cell.ConnectionList().CircNext();
+			
+		}
+		
+		
+		
+	}
+	
+}

Modified: development/source/main/cPopulationInterface.h
===================================================================
--- development/source/main/cPopulationInterface.h	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cPopulationInterface.h	2009-05-18 20:15:08 UTC (rev 3239)
@@ -115,6 +115,11 @@
   void SendFlash();
 
   int GetStateGridID(cAvidaContext& ctx);
+	
+	// Reputation
+	void RotateToGreatestReputation();
+	void RotateToGreatestReputationWithDifferentTag(int tag);
+	void RotateToGreatestReputationWithDifferentLineage(int line);	
 };
 
 

Modified: development/source/main/cStats.cc
===================================================================
--- development/source/main/cStats.cc	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cStats.cc	2009-05-18 20:15:08 UTC (rev 3239)
@@ -2067,3 +2067,263 @@
   df.Write(num_orgs_killed, "Num Orgs Killed");
   df.Endl();
 } //End PrintNumOrgsKilledData()
+
+
+/* Print information pertinent to direct reciprocity experiments*/
+void cStats::PrintDirectReciprocityData(const cString& filename){
+	cDataFile& df = m_world->GetDataFile(filename);
+	
+	cDoubleSum donations;
+	cDoubleSum reciprocations; 
+	cDoubleSum donors;
+	cDoubleSum num_donations_received; 
+	
+	cOrganism* org; 
+	
+	int num_alt =0;
+	int num_coop = 0;
+	int num_lin_2 = 0;
+	int num_lin_1 = 0;
+	int total_org = 0;
+	
+	
+	df.WriteComment("Avida organism direct reciprocity information");
+	df.WriteTimeStamp();
+	df.Write(m_update,   "Update [update]");
+	
+	
+  for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
+    cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
+		org = cell.GetOrganism();
+		
+    if(cell.IsOccupied()) {
+			donations.Add(org->GetNumberOfDonations());
+			num_donations_received.Add(org->GetNumberOfDonationsReceived());
+			reciprocations.Add(org->GetNumberOfReciprocations());
+			donors.Add(org->GetNumberOfDonors());
+			if (org->GetNumberOfDonations() > 0) num_alt++;
+			if ((org->GetNumberOfDonationsReceived() && org->GetNumberOfDonations()) > 0) num_coop++;
+			if (org->GetLineageLabel() == 1) num_lin_1++;
+			if (org->GetLineageLabel() == 2) num_lin_2++;
+			total_org++;
+	  }
+	}
+	
+	df.Write(donations.Average(), "Avg. donations [donation]");
+	df.Write(num_donations_received.Average(), "Avg. donations received [received]");
+	df.Write(donors.Average(), "Avg. number of donor partners [partners]");	
+	df.Write(num_alt, "Number of altruists [altruists]");
+	df.Write(num_coop, "Number of cooperators [cooperators]");
+	df.Write(num_lin_1, "Number of organisms of lineage 1 [lineage1]");
+	df.Write(num_lin_2, "Number of organisms of lineage 2 [lineage2]");
+	df.Write(total_org, "Number of organisms in population [popsize]");
+	
+  df.Endl();
+	
+	
+}
+
+
+/* Print information about the string matching... */
+void cStats::PrintStringMatchData(const cString& filename){
+	cDataFile& df = m_world->GetDataFile(filename);
+	df.WriteComment("Avida organism string donation information");
+	df.WriteTimeStamp();
+	df.Write(m_update,   "Update [update]");
+	cOrganism* org; 
+	
+	
+	/*
+	 // Interate through map of information.
+	 map<cString,cDoubleSum>::iterator iter2;   
+	 for(iter2 = m_string_bits_matched.begin(); iter2 != m_string_bits_matched.end(); iter2++ ) {
+	 df.Write(iter2->second.Average(), iter2->first); 
+	 }
+	 
+	 
+	 // Create a map of the current tags in the population .
+	 for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
+	 cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
+	 org = cell.GetOrganism();
+	 
+	 if(cell.IsOccupied()) {
+	 // Get tag and increment number of orgs. 
+	 m_tags[org->GetTagLabel()]++;
+	 }
+	 }
+	 
+	 // print the tags
+	 map<int, int>::iterator iter;   
+	 stringstream ss; 
+	 for(iter = m_tags.begin(); iter != m_tags.end(); iter++ ) {
+	 ss << iter->first; 
+	 string name = ss.str(); 
+	 df.Write(iter->second, name.c_str()); 
+	 iter->second = 0;
+	 }*/
+	
+	
+	// Print data about strings: 
+	std::map <int, cDoubleSum> m_strings_stored; 
+	std::map <int, cDoubleSum> m_strings_produced; 
+	cDoubleSum total; 
+	int min = -1; 
+	int onhand = 0;
+	int instant_perfect_match = 0;
+	int instant_perfect_match_org = 0;
+	int nothing  =0;
+	int specialists = 0; 
+	int generalists = 0;
+	int type_prod = 0;
+	
+	// Get the number of strings
+	int num = m_world->GetEnvironment().GetNumberOfMatchStrings();
+	for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
+    cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
+		org = cell.GetOrganism();
+		min = -1; 
+		onhand = 0;
+		type_prod = 0;
+		
+    if(cell.IsOccupied()) {
+			for (int j = 0; j<num; j++) {
+				onhand = org->GetNumberStringsOnHand(j);
+				if ((min == -1) || (onhand < min)){
+					min = onhand;
+				}
+				m_strings_stored[j].Add(onhand); 
+				total.Add(onhand);
+				m_strings_produced[j].Add(org->GetNumberStringsProduced(j)); 
+				
+				if (org->GetNumberStringsProduced(j)) type_prod++;
+				
+			}
+			
+			instant_perfect_match += min;
+			if (min > 0) instant_perfect_match_org++;
+			if (type_prod ==0) nothing++;
+			if (type_prod == 1) specialists++;
+			if (type_prod > 1) generalists++;
+		}
+		
+	}
+	
+	// print the string info
+	for (int k=0; k<num; k++) {
+		string name = m_world->GetEnvironment().GetMatchString(k).GetData(); 
+		name = "produced" + name;
+		df.Write(m_strings_produced[k].Average(), name.c_str()); 
+		
+		name = m_world->GetEnvironment().GetMatchString(k).GetData(); 
+		name = "stored" + name;
+		df.Write(m_strings_stored[k].Average(), name.c_str()); 
+		
+	}
+	df.Write(total.Average(), "totalStoredAverage");
+	
+	// Print number of perfect matches
+	df.Write(m_perfect_match.Sum(), "PerfectMatchStringElapse[ps]"); 
+	m_perfect_match.Clear();
+	// Print number of perfect matches
+	df.Write(m_perfect_match_org.Sum(), "PerfectMatchOrgElapse[pso]"); 
+	m_perfect_match_org.Clear();
+	df.Write(instant_perfect_match, "PerfectMatchStringInstant[psi]"); 
+	// Print number of perfect matches
+	df.Write(instant_perfect_match_org, "PerfectMatchOrgInstant[psoi]"); 
+	df.Write(nothing, "Producednothing[nothing]"); 
+	df.Write(generalists, "Generalists[generalists]"); 
+	df.Write(specialists, "Specialists[specialists]"); 
+	
+	
+  df.Endl();
+}
+
+/* Print information about the reputation... */
+void cStats::PrintReputationData(const cString& filename){
+	cDataFile& df = m_world->GetDataFile(filename);
+	
+	cDoubleSum reputations;
+	cDoubleSum donations;
+	cDoubleSum reciprocations; 
+	cDoubleSum donors;
+	cDoubleSum k;
+	cDoubleSum num_donations_received; 
+	cDoubleSum amount_donations_received;
+	cDoubleSum num_failed_reputation_inc;
+	cDoubleSum own_raw_mat; 
+	cDoubleSum other_raw_mat;
+	
+	
+	// difference between how many an organism donated & how many it received
+	cDoubleSum disparity;
+	
+	cOrganism* org; 
+	int min_rep = 100; 
+	int max_rep = 0;
+	int cur_rep;
+	int num_alt =0;
+	int num_coop = 0;
+	
+	
+	
+	df.WriteComment("Avida organism reputation information -- average donations, min donations, max donations");
+	df.WriteTimeStamp();
+	df.Write(m_update,   "Update [update]");
+	
+	
+  for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
+    cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
+		org = cell.GetOrganism();
+		
+    if(cell.IsOccupied()) {
+			cur_rep = org->GetReputation();
+			
+			if (cur_rep < min_rep) min_rep = cur_rep;
+			if (max_rep < cur_rep) max_rep = cur_rep;
+			reputations.Add(cur_rep);
+			donations.Add(org->GetNumberOfDonations());
+			num_donations_received.Add(org->GetNumberOfDonationsReceived());
+			amount_donations_received.Add(org->GetAmountOfDonationsReceived());
+			own_raw_mat.Add(org->GetSelfRawMaterials());
+			other_raw_mat.Add(org->GetOtherRawMaterials());
+			
+			reciprocations.Add(org->GetNumberOfReciprocations());
+			donors.Add(org->GetNumberOfDonors());
+			num_failed_reputation_inc.Add(org->GetFailedReputationIncreases());
+//			k.Add(org->GetK());
+			
+			disparity.Add(org->GetNumberOfDonations() - org->GetOtherRawMaterials()); 
+			
+			if (org->GetNumberOfDonations() > 0) num_alt++;
+			if ((org->GetNumberOfDonationsReceived() && org->GetNumberOfDonations()) > 0) num_coop++;
+			
+			
+	  }
+	}
+	df.Write(reputations.Average(), "Avg. reputation [reputation]");
+	//	df.Write(reputations.StdDeviation(), "Standard Deviation [repstddev]");
+	//	df.Write(min_rep, "Minimum reputation");
+	//	df.Write(max_rep, "Maximum reputation");	
+	df.Write(donations.Average(), "Avg. donations [donation]");
+	//	df.Write(num_donations_received.Average(), "Avg. donations received [received]");
+	//	df.Write(amount_donations_received.Average(), "Avg. number donations received [amount]");
+	//	df.Write(reciprocations.Average(), "Avg. reciprocations [reciprocation]");
+	//	df.Write(disparity.Average(), "Disparity between donations and collections [disparity]");
+	df.Write(donors.Average(), "Avg. number of donor partners [partners]");
+	//	df.Write(num_failed_reputation_inc.Average(), "Avg. number of reputation increase failures [failure]");	
+	//	df.Write(recip_prob_change.Average(), "Avg. change in reciprocation probability [recipprob]");
+	
+	df.Write(num_alt, "Number of altruists [altruists]");
+	df.Write(num_coop, "Number of cooperators [cooperators]");
+	df.Write(own_raw_mat.Average(), "Avg. own raw mat [ownrawmat]");
+	df.Write(other_raw_mat.Average(), "Avg. other raw mat [otherrawmat]");
+	//	df.Write(num_all_strings, "Number of orgs with all strings [allstrings]");
+	
+	//	df.Write(k.Average(), "Avg. k of organisms [k]");
+	//	df.Write(m_donate_to_donor, "Number of donate to donor [donatedonor]");
+	//	df.Write(m_donate_to_facing, "Number of donate to facing [donatefacing]");
+	
+	
+	
+  df.Endl();
+} 

Modified: development/source/main/cStats.h
===================================================================
--- development/source/main/cStats.h	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cStats.h	2009-05-18 20:15:08 UTC (rev 3239)
@@ -904,9 +904,34 @@
 protected:
   int m_flash_count; //!< Number of flashes that have occured since last PrintSynchronizationData.
 	PopulationFlashes m_flash_times; //!< For tracking flashes that have occurred throughout this population.
+
+// -------- Reputation support ---------
+public: 
+	// Print statistics about reputation
+	void PrintReputationData(const cString& filename);
+	void PrintDirectReciprocityData(const cString& filename);
+	void IncDonateToDonor() { m_donate_to_donor++; } 
+	void IncDonateToFacing() { m_donate_to_facing++; }
+	void PrintStringMatchData(const cString& filename);
+	void AddStringBitsMatchedValue(cString name, int value) { m_string_bits_matched[name].Add(value); }
+	void AddTag(int tag, int value) { m_tags[tag] = m_tags[tag] + value; }
+	void IncPerfectMatch(int amount) { m_perfect_match.Add(amount); }
+	void IncPerfectMatchOrg() { m_perfect_match_org.Add(1); }
+	
+protected: 
+	int m_donate_to_donor; 
+	int m_donate_to_facing;
+	std::map <cString, cDoubleSum> m_string_bits_matched;
+	cDoubleSum m_perfect_match;
+	cDoubleSum m_perfect_match_org;
+	std::map <int, int> m_tags;
+	
+
 };
 
 
+
+
 #ifdef ENABLE_UNIT_TESTS
 namespace nStats {
   /**

Modified: development/source/main/cTaskLib.cc
===================================================================
--- development/source/main/cTaskLib.cc	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cTaskLib.cc	2009-05-18 20:15:08 UTC (rev 3239)
@@ -356,6 +356,9 @@
     Load_MatchStr(name, info, envreqs, errors);
   else if (name == "match_number")
     Load_MatchNumber(name, info, envreqs, errors);
+	else if (name == "matchprodstr") 
+    Load_MatchProdStr(name, info, envreqs, errors);
+
   
   // Sequence Tasks
   if (name == "sort_inputs")
@@ -419,7 +422,11 @@
   else if (name == "movetoevent")
     NewTask(name, "Move to a target area", &cTaskLib::Task_MoveToMovementEvent);
   else if (name == "movebetweenevent")
-    NewTask(name, "Move to a target area", &cTaskLib::Task_MoveBetweenMovementEvent);  
+    NewTask(name, "Move to a target area", &cTaskLib::Task_MoveBetweenMovementEvent); 
+	
+	// reputation based tasks
+	else if(name == "perfect_strings") 
+		NewTask(name, "Produce and store perfect strings", &cTaskLib::Task_CreatePerfectStrings);		
 
   // event tasks
   if(name == "move_to_event")
@@ -1998,8 +2005,138 @@
   return bonus;
 }
 
+vector<cString> cTaskLib::GetMatchStrings()
+{
+	return m_strings;
+}
 
+cString cTaskLib::GetMatchString(int x)
+{ 
+	cString s; 
+	if (x >= 0 && x < m_strings.size()){
+		s = m_strings[x]; 
+	} else { 
+		s = cString("");
+	}
+	
+	return s;
+	
+}
 
+
+void cTaskLib::Load_MatchProdStr(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors)
+{
+  cArgSchema schema;
+  schema.AddEntry("string", 0, cArgSchema::SCHEMA_STRING);		
+  schema.AddEntry("partial",0, 0);
+  schema.AddEntry("binary",1,1);
+  schema.AddEntry("pow",0,2.0);
+	schema.AddEntry("tag",2,-1);
+  cArgContainer* args = cArgContainer::Load(argstr, schema, errors);	
+  envreqs.SetMinOutputs(args->GetString(0).GetSize());
+	m_strings.push_back(args->GetString(0));
+  if (args) NewTask(name, "MatchProdStr", &cTaskLib::Task_MatchStr, 0, args);
+}
+
+
+double cTaskLib::Task_MatchProdStr(cTaskContext& ctx) const
+{
+	
+	
+	// These even out the stats tracking.
+	m_world->GetStats().AddTag(ctx.GetTaskEntry()->GetArguments().GetInt(2), 0);
+	m_world->GetStats().AddTag(-1, 0);
+	
+	tBuffer<int> temp_buf(ctx.GetOutputBuffer());
+	
+	const cString& string_to_match = ctx.GetTaskEntry()->GetArguments().GetString(0);
+  int partial = ctx.GetTaskEntry()->GetArguments().GetInt(0);
+  int binary = ctx.GetTaskEntry()->GetArguments().GetInt(1);
+  double mypow = ctx.GetTaskEntry()->GetArguments().GetDouble(0);
+  int string_index;
+  int num_matched = 0;
+  int test_output;
+  int max_num_matched = 0;
+  int num_real=0;
+	
+  if (!binary)
+  {
+    if (temp_buf.GetNumStored() > 0) {
+      test_output = temp_buf[0];
+			
+      for (int j = 0; j < string_to_match.GetSize(); j++) {  
+				string_index = string_to_match.GetSize() - j - 1; // start with last char in string
+				int k = 1 << j;
+				if ((string_to_match[string_index] == '0' && !(test_output & k)) ||
+						(string_to_match[string_index] == '1' && (test_output & k))) num_matched++;
+      }
+      max_num_matched = num_matched;
+    }
+  }
+  else
+  {
+    for (int j = 0; j < string_to_match.GetSize(); j++)
+    {
+			if (string_to_match[j]!='9')
+				num_real++;
+			if (string_to_match[j]=='0' && temp_buf[j]==0 ||
+					string_to_match[j]=='1' && temp_buf[j]==1)
+				num_matched++;
+    }
+    max_num_matched = num_matched;
+		
+  }
+	
+	// Check if the organism already produced this string. 
+	// If so, it receives a perfect score for this task.
+	int tag = ctx.GetTaskEntry()->GetArguments().GetInt(2);
+	
+	if (m_world->GetConfig().MATCH_ALREADY_PRODUCED.Get()) {
+		int prod = ctx.GetOrganism()->GetNumberStringsProduced(tag); 
+		if (prod) max_num_matched = string_to_match.GetSize();
+	}
+	
+	
+	// Update the organism's tag. 
+	ctx.GetOrganism()->UpdateTag(tag, max_num_matched);
+	if (ctx.GetOrganism()->GetTagLabel() == tag) {
+		ctx.GetOrganism()->SetLineageLabel(ctx.GetTaskEntry()->GetArguments().GetInt(2));
+	} 
+	
+	
+	// Update stats
+	cString name;
+	name = "[produced"; 
+	name += string_to_match;
+	name += "]";
+	m_world->GetStats().AddStringBitsMatchedValue(name, max_num_matched);
+	
+	// if the organism hasn't donated, then zero out its reputation. 
+	if ((ctx.GetOrganism()->GetReputation() > 0) && 
+			(ctx.GetOrganism()->GetNumberOfDonations() == 0)) {
+		ctx.GetOrganism()->SetReputation(0);
+	}
+	
+	
+	
+	double bonus = 0.0;
+	double base_bonus = 0.0; 
+	
+	base_bonus = static_cast<double>(max_num_matched) * 2.0 / static_cast<double>(string_to_match.GetSize()) - 1;
+	
+  if (partial)
+  {
+    base_bonus=double(max_num_matched)*2/double(num_real) -1;
+  }
+	
+  if (base_bonus > 0.0) {
+    bonus = pow(base_bonus,mypow);
+  }
+  return bonus;
+	
+}
+
+
 void cTaskLib::Load_MatchNumber(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors)
 {
   cArgSchema schema;
@@ -3211,3 +3348,38 @@
   
   return quality;
 }  
+
+
+/* This task provides major points for perfect strings and some points for just
+ storing stuff. */
+double cTaskLib::Task_CreatePerfectStrings(cTaskContext& ctx) const {
+	double bonus = 0.0;
+	int min = -1;
+	int temp = 0;
+	for (unsigned int i = 0; i<m_strings.size(); i++) {
+		temp = ctx.GetOrganism()->GetNumberStringsOnHand(i); 
+		
+		// Figure out what the minimum amount of a string is.
+		if ((min == -1) || (temp < min)){
+			min = temp;
+		}
+	}
+	
+	// Bonus for creating perfect strings!
+	bonus = min; 
+	
+	// Add in some value for just creating stuff
+	for (unsigned int i = 0; i<m_strings.size(); i++) {
+		temp = ctx.GetOrganism()->GetNumberStringsOnHand(i); 
+		
+		if (temp > min) { 
+			bonus += (temp - min); 
+		}
+	} 
+	
+	// Update stats
+	m_world->GetStats().IncPerfectMatch(min);
+	if (min > 0) m_world->GetStats().IncPerfectMatchOrg();
+	
+	return bonus; 
+}
\ No newline at end of file

Modified: development/source/main/cTaskLib.h
===================================================================
--- development/source/main/cTaskLib.h	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cTaskLib.h	2009-05-18 20:15:08 UTC (rev 3239)
@@ -86,6 +86,15 @@
 
   bool UseNeighborInput() const { return use_neighbor_input; }
   bool UseNeighborOutput() const { return use_neighbor_output; }
+	
+	// Get the strings that parameterize the MatchString tasks
+	vector<cString> GetMatchStrings(); 
+	cString GetMatchString(int x);
+	int GetNumberOfMatchStrings() { return m_strings.size(); } 
+
+private: 
+	// Store the strings used by the MatchString tasks
+	vector<cString> m_strings; 
   
   
 private:
@@ -242,6 +251,8 @@
   // Matching Tasks
   void Load_MatchStr(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors);
   double Task_MatchStr(cTaskContext& ctx) const;
+	void Load_MatchProdStr(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors);
+  double Task_MatchProdStr(cTaskContext& ctx) const;
   void Load_MatchNumber(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors);
   double Task_MatchNumber(cTaskContext& ctx) const;
 
@@ -303,6 +314,9 @@
   // State Grid Tasks
   void Load_SGPathTraversal(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors);
   double Task_SGPathTraversal(cTaskContext& ctx) const;  
+	
+	// reputation
+	double Task_CreatePerfectStrings(cTaskContext& ctx) const; 
 };
 
 

Modified: development/source/tools/cString.h
===================================================================
--- development/source/tools/cString.h	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/tools/cString.h	2009-05-18 20:15:08 UTC (rev 3239)
@@ -175,7 +175,12 @@
    **/
   int GetSize() const { return value->GetSize(); }
 
+	/**
+	 *  Get the string
+	 **/
+	const char* GetData() const { return value->GetData(); }
 
+
   // Comparisons
   int Compare(const char * in) const;  // strcmp like function
   bool operator== (const char * in)    const { return (Compare(in)==0); }

Modified: development/source/viewer-core/cCoreView_Info.cc
===================================================================
--- development/source/viewer-core/cCoreView_Info.cc	2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/viewer-core/cCoreView_Info.cc	2009-05-18 20:15:08 UTC (rev 3239)
@@ -24,7 +24,7 @@
 
 #include "cCoreView_Info.h"
 
-#include "cBitArray.h"
+//#include "cBitArray.h"
 #include "cClassificationManager.h"
 #include "cGenotype.h"
 #include "cPopulation.h"




More information about the Avida-cvs mailing list