1 /*
2  *  cOrganism.cc
3  *  Avida
4  *
5  *  Called "organism.cc" prior to 12/5/05.
6  *  Copyright 1999-2011 Michigan State University. All rights reserved.
7  *  Copyright 1993-2003 California Institute of Technology.
8  *
9  *
10  *  This file is part of Avida.
11  *
12  *  Avida is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
13  *  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
14  *
15  *  Avida is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public License along with Avida.
19  *  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #include "cOrganism.h"
24 
25 #include "avida/core/WorldDriver.h"
26 
27 #include "cAvidaContext.h"
28 #include "cBioGroup.h"
29 #include "cContextPhenotype.h"
30 #include "cDeme.h"
31 #include "cEnvironment.h"
32 #include "cHardwareBase.h"
33 #include "cHardwareManager.h"
34 #include "cInstSet.h"
35 #include "cOrgSensor.h"
36 #include "cOrgSinkMessage.h"
37 #include "cPopulationCell.h"
38 #include "cStateGrid.h"
39 #include "cStringUtil.h"
40 #include "cTaskContext.h"
41 #include "cWorld.h"
42 #include "cStats.h"
43 #include "nHardware.h"
44 
45 #include <algorithm>
46 #include <iomanip>
47 #include <utility>
48 
49 using namespace std;
50 using namespace Avida;
51 
52 
cOrganism(cWorld * world,cAvidaContext & ctx,const Genome & genome,int parent_generation,eBioUnitSource src,const cString & src_args)53 cOrganism::cOrganism(cWorld* world, cAvidaContext& ctx, const Genome& genome, int parent_generation, eBioUnitSource src,
54                      const cString& src_args)
55 : m_world(world)
56 , m_phenotype(world, parent_generation, world->GetHardwareManager().GetInstSet(genome.GetInstSet()).GetNumNops())
57 , m_src(src)
58 , m_src_args(src_args)
59 , m_initial_genome(genome)
60 , m_interface(NULL)
61 , m_lineage_label(-1)
62 , m_lineage(NULL)
63 , m_org_list_index(-1)
64 , m_org_display(NULL)
65 , m_queued_display_data(NULL)
66 , m_display(false)
67 , m_input_pointer(0)
68 , m_input_buf(world->GetEnvironment().GetInputSize())
69 , m_output_buf(world->GetEnvironment().GetOutputSize())
70 , m_received_messages(RECEIVED_MESSAGES_SIZE)
71 , m_cur_sg(0)
72 , m_sent_value(0)
73 , m_sent_active(false)
74 , m_test_receive_pos(0)
75 , m_pher_drop(false)
76 , frac_energy_donating(m_world->GetConfig().ENERGY_SHARING_PCT.Get())
77 , m_max_executed(-1)
78 , m_is_running(false)
79 , m_is_sleeping(false)
80 , m_is_dead(false)
81 , killed_event(false)
82 , m_net(NULL)
83 , m_msg(0)
84 , m_opinion(0)
85 , m_neighborhood(0)
86 , m_self_raw_materials(world->GetConfig().RAW_MATERIAL_AMOUNT.Get())
87 , m_other_raw_materials(0)
88 , m_num_donate(0)
89 , m_num_donate_received(0)
90 , m_amount_donate_received(0)
91 , m_num_reciprocate(0)
92 , m_failed_reputation_increases(0)
93 , m_tag(make_pair(-1, 0))
94 , m_northerly(0)
95 , m_easterly(0)
96 , m_forage_target(-1)
97 , m_has_set_ft(false)
98 , m_teach(false)
99 , m_parent_teacher(false)
100 , m_parent_ft(-1)
101 , m_parent_group(world->GetConfig().DEFAULT_GROUP.Get())
102 , m_beggar(false)
103 , m_guard(false)
104 , m_num_guard(0)
105 , m_num_deposits(0)
106 , m_amount_deposited(0)
107 , m_num_point_mut(0)
108 , m_av_in_index(-1)
109 , m_av_out_index(-1)
110 {
111 	// initializing this here because it may be needed during hardware creation:
112 	m_id = m_world->GetStats().GetTotCreatures();
113 
114   m_hardware = m_world->GetHardwareManager().Create(ctx, this, m_initial_genome);
115 
116   initialize(ctx);
117 }
118 
119 
120 
initialize(cAvidaContext & ctx)121 void cOrganism::initialize(cAvidaContext& ctx)
122 {
123   m_phenotype.SetInstSetSize(m_hardware->GetInstSet().GetSize());
124 
125   if (m_world->GetConfig().DEATH_METHOD.Get() > DEATH_METHOD_OFF) {
126     m_max_executed = m_world->GetConfig().AGE_LIMIT.Get();
127     if (m_world->GetConfig().AGE_DEVIATION.Get() > 0.0) {
128       m_max_executed += (int) (ctx.GetRandom().GetRandNormal() * m_world->GetConfig().AGE_DEVIATION.Get());
129     }
130     if (m_world->GetConfig().DEATH_METHOD.Get() == DEATH_METHOD_MULTIPLE) {
131       m_max_executed *= m_initial_genome.GetSize();
132     }
133 
134     // m_max_executed must be positive or an organism will not die!
135     if (m_max_executed < 1) m_max_executed = 1;
136   }
137 
138   m_repair = (m_world->GetConfig().POINT_MUT_REPAIR_START.Get());
139 
140   if (m_world->GetConfig().NET_ENABLED.Get()) m_net = new cNetSupport();
141 
142 	// randomize the amout of raw materials an organism has at its
143 	// disposal.
144 	if (m_world->GetConfig().RANDOMIZE_RAW_MATERIAL_AMOUNT.Get()) {
145 		int raw_mat = m_world->GetConfig().RAW_MATERIAL_AMOUNT.Get();
146 		m_self_raw_materials = m_world->GetRandom().GetUInt(0, raw_mat+1);
147 	}
148 }
149 
150 
151 
~cOrganism()152 cOrganism::~cOrganism()
153 {
154   assert(m_is_running == false);
155   delete m_hardware;
156   delete m_interface;
157   if(m_net) delete m_net;
158   if(m_msg) delete m_msg;
159   if(m_opinion) delete m_opinion;
160   for (int i = 0; i < m_parasites.GetSize(); i++) delete m_parasites[i];
161   if (m_neighborhood) delete m_neighborhood;
162   delete m_org_display;
163   delete m_queued_display_data;
164 }
165 
~cNetSupport()166 cOrganism::cNetSupport::~cNetSupport()
167 {
168   while (pending.GetSize()) delete pending.Pop();
169   for (int i = 0; i < received.GetSize(); i++) delete received[i];
170 }
171 
SetOrgInterface(cAvidaContext & ctx,cOrgInterface * org_interface)172 void cOrganism::SetOrgInterface(cAvidaContext& ctx, cOrgInterface* org_interface)
173 {
174   delete m_interface;
175   m_interface = org_interface;
176 
177   HardwareReset(ctx);
178 }
179 
GetStateGrid() const180 const cStateGrid& cOrganism::GetStateGrid() const { return m_world->GetEnvironment().GetStateGrid(m_cur_sg); }
181 
GetVitality() const182 double cOrganism::GetVitality() const {
183   double mean_age = m_world->GetStats().SumCreatureAge().Ave();
184   double age_stddev = m_world->GetStats().SumCreatureAge().StdDeviation();
185   int org_age = m_phenotype.GetAge();
186   const int resource = m_world->GetConfig().COLLECT_SPECIFIC_RESOURCE.Get();
187   double res_level = 0.0;
188   if (resource >= 0)
189     res_level = m_phenotype.GetCurRBinAvail(resource);
190   double vitality = 0.0;
191 
192   if (org_age < (mean_age - age_stddev) || org_age > (mean_age + age_stddev)) {
193     vitality = m_world->GetConfig().VITALITY_BIN_EXTREMES.Get() * res_level;
194   } else {
195     vitality = m_world->GetConfig().VITALITY_BIN_CENTER.Get() * res_level;
196   }
197 
198   return vitality;
199 }
200 
UpdateOrgDisplay()201 bool cOrganism::UpdateOrgDisplay() {
202   if (m_queued_display_data != NULL) {
203     delete m_org_display;
204     m_org_display = m_queued_display_data;
205     m_queued_display_data = NULL;
206     return true;
207   }
208   else return false;
209 }
210 
SetSimpDisplay(int display_part,int value)211 void cOrganism::SetSimpDisplay(int display_part, int value)
212 {
213   if (m_org_display == NULL) {
214     m_org_display = new sOrgDisplay;
215     m_display = true;
216     m_org_display->distance = -99;
217     m_org_display->direction = -99;
218     m_org_display->value = -99;
219     m_org_display->message = -99;
220 
221   }
222   switch (display_part) {
223     case 0:
224       m_org_display->distance = value;
225     case 1:
226       m_org_display->direction = value;
227     case 3:
228       m_org_display->value = value;
229     default:
230       m_org_display->message = value;
231   }
232 }
233 
GetRBinsTotal()234 double cOrganism::GetRBinsTotal()
235 {
236 	double total = 0;
237 	for(int i = 0; i < m_phenotype.GetCurRBinsAvail().GetSize(); i++) {
238     total += m_phenotype.GetCurRBinsAvail()[i];
239   }
240 
241 	return total;
242 }
243 
SetRBins(const tArray<double> & rbins_in)244 void cOrganism::SetRBins(const tArray<double>& rbins_in)
245 {
246 	m_phenotype.SetCurRBinsAvail(rbins_in);
247 }
248 
SetRBin(const int index,const double value)249 void cOrganism::SetRBin(const int index, const double value)
250 {
251 	m_phenotype.SetCurRBinAvail(index, value);
252 }
253 
AddToRBin(const int index,const double value)254 void cOrganism::AddToRBin(const int index, const double value)
255 {
256 	m_phenotype.AddToCurRBinAvail(index, value);
257 	if (value > 0) {
258     m_phenotype.AddToCurRBinTotal(index, value);
259   }
260 }
261 
IncCollectSpecCount(const int spec_id)262 void cOrganism::IncCollectSpecCount(const int spec_id)
263 {
264   int current_count = m_phenotype.GetCurCollectSpecCount(spec_id);
265   m_phenotype.SetCurCollectSpecCount(spec_id, current_count + 1);
266 }
267 
ReceiveValue()268 int cOrganism::ReceiveValue()
269 {
270   assert(m_interface);
271   const int out_value = m_interface->ReceiveValue();
272   return out_value;
273 }
274 
SellValue(const int data,const int label,const int sell_price)275 void cOrganism::SellValue(const int data, const int label, const int sell_price)
276 {
277 	if (m_sold_items.GetSize() < 10)
278 	{
279 		assert (m_interface);
280 		m_interface->SellValue(data, label, sell_price, m_id);
281 		m_world->GetStats().AddMarketItemSold();
282 	}
283 }
284 
BuyValue(const int label,const int buy_price)285 int cOrganism::BuyValue(const int label, const int buy_price)
286 {
287 	assert (m_interface);
288 	const int receive_value = m_interface->BuyValue(label, buy_price);
289 	if (receive_value != 0)
290 	{
291 		// put this value in storage place for recieved values
292 		m_received_messages.Add(receive_value);
293 		// update loss of buy_price to merit
294 		double cur_merit = GetPhenotype().GetMerit().GetDouble();
295 		cur_merit -= buy_price;
296 		UpdateMerit(cur_merit);
297 		m_world->GetStats().AddMarketItemBought();
298 	}
299 	return receive_value;
300 }
301 
302 
DoInput(const int value)303 void cOrganism::DoInput(const int value)
304 {
305   DoInput(m_input_buf, m_output_buf, value);
306 }
307 
308 
DoInput(tBuffer<int> & input_buffer,tBuffer<int> & output_buffer,const int value)309 void cOrganism::DoInput(tBuffer<int>& input_buffer, tBuffer<int>& output_buffer, const int value)
310 {
311   input_buffer.Add(value);
312   m_phenotype.TestInput(input_buffer, output_buffer);
313 }
314 
315 
DoOutput(cAvidaContext & ctx,const bool on_divide,cContextPhenotype * context_phenotype)316 void cOrganism::DoOutput(cAvidaContext& ctx, const bool on_divide, cContextPhenotype* context_phenotype)
317 {
318   if (m_net) m_net->valid = false;
319   if(m_world->GetConfig().USE_AVATARS.Get()) doAVOutput(ctx, m_input_buf, m_output_buf, on_divide, false, context_phenotype);
320   else doOutput(ctx, m_input_buf, m_output_buf, on_divide, false, context_phenotype);
321 }
322 
323 
DoOutput(cAvidaContext & ctx,const int value)324 void cOrganism::DoOutput(cAvidaContext& ctx, const int value)
325 {
326   m_output_buf.Add(value);
327   NetValidate(ctx, value);
328   if(m_world->GetConfig().USE_AVATARS.Get()) doAVOutput(ctx, m_input_buf, m_output_buf, false, false);
329   else doOutput(ctx, m_input_buf, m_output_buf, false, false);
330 }
331 
DoOutput(cAvidaContext & ctx,const int value,bool is_parasite,cContextPhenotype * context_phenotype)332 void cOrganism::DoOutput(cAvidaContext& ctx, const int value, bool is_parasite, cContextPhenotype* context_phenotype)
333 {
334   m_output_buf.Add(value);
335   NetValidate(ctx, value);
336   if(m_world->GetConfig().USE_AVATARS.Get()) doAVOutput(ctx, m_input_buf, m_output_buf, false, (bool)is_parasite, context_phenotype);
337   else doOutput(ctx, m_input_buf, m_output_buf, false, (bool)is_parasite, context_phenotype);
338 }
339 
DoOutput(cAvidaContext & ctx,tBuffer<int> & input_buffer,tBuffer<int> & output_buffer,const int value)340 void cOrganism::DoOutput(cAvidaContext& ctx, tBuffer<int>& input_buffer, tBuffer<int>& output_buffer, const int value)
341 {
342   output_buffer.Add(value);
343   NetValidate(ctx, value);
344   if(m_world->GetConfig().USE_AVATARS.Get()) doAVOutput(ctx, input_buffer, output_buffer, false, false);
345   else doOutput(ctx, input_buffer, output_buffer, false, false);
346 }
347 
348 
doOutput(cAvidaContext & ctx,tBuffer<int> & input_buffer,tBuffer<int> & output_buffer,const bool on_divide,bool is_parasite,cContextPhenotype * context_phenotype)349 void cOrganism::doOutput(cAvidaContext& ctx,
350                          tBuffer<int>& input_buffer,
351                          tBuffer<int>& output_buffer,
352                          const bool on_divide,
353                          bool is_parasite,
354                          cContextPhenotype* context_phenotype)
355 {
356   const int deme_id = m_interface->GetDemeID();
357   const tArray<double> & global_resource_count = m_interface->GetResources(ctx);
358   const tArray<double> & deme_resource_count = m_interface->GetDemeResources(deme_id, ctx);
359   const tArray< tArray<int> > & cell_id_lists = m_interface->GetCellIdLists();
360 
361   tList<tBuffer<int> > other_input_list;
362   tList<tBuffer<int> > other_output_list;
363 
364   // If tasks require us to consider neighbor inputs, collect them...
365   if (m_world->GetEnvironment().UseNeighborInput()) {
366     const int num_neighbors = m_interface->GetNumNeighbors();
367     for (int i = 0; i < num_neighbors; i++) {
368       m_interface->Rotate();
369       cOrganism * cur_neighbor = m_interface->GetNeighbor();
370       if (cur_neighbor == NULL) continue;
371 
372       other_input_list.Push( &(cur_neighbor->m_input_buf) );
373     }
374   }
375 
376   // If tasks require us to consider neighbor outputs, collect them...
377   if (m_world->GetEnvironment().UseNeighborOutput()) {
378     const int num_neighbors = m_interface->GetNumNeighbors();
379     for (int i = 0; i < num_neighbors; i++) {
380       m_interface->Rotate();
381       cOrganism * cur_neighbor = m_interface->GetNeighbor();
382       if (cur_neighbor == NULL) continue;
383 
384       other_output_list.Push( &(cur_neighbor->m_output_buf) );
385     }
386   }
387 
388   // Do the testing of tasks performed...
389 
390 
391   tArray<double> global_res_change(global_resource_count.GetSize());
392   global_res_change.SetAll(0.0);
393   tArray<double> deme_res_change(deme_resource_count.GetSize());
394   deme_res_change.SetAll(0.0);
395   tArray<cString> insts_triggered;
396 
397   tBuffer<int>* received_messages_point = &m_received_messages;
398   if (!m_world->GetConfig().SAVE_RECEIVED.Get()) received_messages_point = NULL;
399 
400   cTaskContext taskctx(this, input_buffer, output_buffer, other_input_list, other_output_list,
401                        m_hardware->GetExtendedMemory(), on_divide, received_messages_point);
402 
403   //combine global and deme resource counts
404   tArray<double> globalAndDeme_resource_count = global_resource_count + deme_resource_count;
405   tArray<double> globalAndDeme_res_change = global_res_change + deme_res_change;
406 
407   // set any resource amount to 0 if a cell cannot access this resource
408   int cell_id=GetCellID();
409   if (cell_id_lists.GetSize())
410   {
411     for (int i=0; i<cell_id_lists.GetSize(); i++)
412     {
413       // if cell_id_lists have been set then we have to check if this cell is in the list
414       if (cell_id_lists[i].GetSize()) {
415         int j;
416         for (j=0; j<cell_id_lists[i].GetSize(); j++)
417         {
418           if (cell_id==cell_id_lists[i][j])
419             break;
420         }
421         if (j==cell_id_lists[i].GetSize())
422           globalAndDeme_resource_count[i]=0;
423       }
424     }
425   }
426 
427   bool task_completed = m_phenotype.TestOutput(ctx, taskctx, globalAndDeme_resource_count,
428                                                m_phenotype.GetCurRBinsAvail(), globalAndDeme_res_change,
429                                                insts_triggered, is_parasite, context_phenotype);
430 
431   // Handle merit increases that take the organism above it's current population merit
432   if (m_world->GetConfig().MERIT_INC_APPLY_IMMEDIATE.Get()) {
433     double cur_merit = m_phenotype.CalcCurrentMerit();
434     if (m_phenotype.GetMerit().GetDouble() < cur_merit) m_interface->UpdateMerit(cur_merit);
435   }
436 
437   //disassemble global and deme resource counts
438   global_res_change = globalAndDeme_res_change.Subset(0, global_res_change.GetSize());
439   deme_res_change = globalAndDeme_res_change.Subset(global_res_change.GetSize(), globalAndDeme_res_change.GetSize());
440 
441   if(m_world->GetConfig().ENERGY_ENABLED.Get() && m_world->GetConfig().APPLY_ENERGY_METHOD.Get() == 1 && task_completed) {
442     m_phenotype.RefreshEnergy();
443     m_phenotype.ApplyToEnergyStore();
444     double newMerit = m_phenotype.ConvertEnergyToMerit(m_phenotype.GetStoredEnergy() * m_phenotype.GetEnergyUsageRatio());
445     m_interface->UpdateMerit(newMerit);
446     if(GetPhenotype().GetMerit().GetDouble() == 0.0) {
447       GetPhenotype().SetToDie();
448     }
449   }
450   m_interface->UpdateResources(ctx, global_res_change);
451 
452   //update deme resources
453   m_interface->UpdateDemeResources(ctx, deme_res_change);
454 
455   for (int i = 0; i < insts_triggered.GetSize(); i++)
456     m_hardware->ProcessBonusInst(ctx, m_hardware->GetInstSet().GetInst(insts_triggered[i]));
457 }
458 
doAVOutput(cAvidaContext & ctx,tBuffer<int> & input_buffer,tBuffer<int> & output_buffer,const bool on_divide,bool is_parasite,cContextPhenotype * context_phenotype)459 void cOrganism::doAVOutput(cAvidaContext& ctx,
460                          tBuffer<int>& input_buffer,
461                          tBuffer<int>& output_buffer,
462                          const bool on_divide,
463                          bool is_parasite,
464                          cContextPhenotype* context_phenotype)
465 {
466   //Avatar output has to be seperate from doOutput to ensure avatars, not the true orgs, are triggering reactions
467 //  const int deme_id = m_interface->GetDemeID();
468   const tArray<double> & avatar_resource_count = m_interface->GetAVResources(ctx);
469 //  const tArray<double> & deme_resource_count = m_interface->GetDemeResources(deme_id, ctx); //todo: DemeAVResources
470   const tArray< tArray<int> > & cell_id_lists = m_interface->GetCellIdLists();
471 
472   tList<tBuffer<int> > other_input_list;
473   tList<tBuffer<int> > other_output_list;
474 
475   // If tasks require us to consider neighbor inputs, collect them...
476   if (m_world->GetEnvironment().UseNeighborInput()) {
477     const int num_neighbors = m_interface->GetAVNumNeighbors();
478     for (int i = 0; i < num_neighbors; i++) {
479       m_interface->Rotate();
480       const tArray<cOrganism*>& cur_neighbors = m_interface->GetFacedAVs();
481       for (int i = 0; i < cur_neighbors.GetSize(); i++) {
482         if (cur_neighbors[i] == NULL) continue;
483         other_input_list.Push( &(cur_neighbors[i]->m_input_buf) );
484       }
485     }
486   }
487 
488   // If tasks require us to consider neighbor outputs, collect them...
489   if (m_world->GetEnvironment().UseNeighborOutput()) {
490     const int num_neighbors = m_interface->GetAVNumNeighbors();
491     for (int i = 0; i < num_neighbors; i++) {
492       m_interface->Rotate();
493       const tArray<cOrganism*>& cur_neighbors = m_interface->GetFacedAVs();
494       for (int i = 0; i < cur_neighbors.GetSize(); i++) {
495         if (cur_neighbors[i] == NULL) continue;
496         other_output_list.Push( &(cur_neighbors[i]->m_output_buf) );
497       }
498     }
499   }
500 
501   // Do the testing of tasks performed...
502   tArray<double> avatar_res_change(avatar_resource_count.GetSize());
503   avatar_res_change.SetAll(0.0);
504 //  tArray<double> deme_res_change(deme_resource_count.GetSize());
505 //  deme_res_change.SetAll(0.0);
506   tArray<cString> insts_triggered;
507 
508   tBuffer<int>* received_messages_point = &m_received_messages;
509   if (!m_world->GetConfig().SAVE_RECEIVED.Get()) received_messages_point = NULL;
510 
511   cTaskContext taskctx(this, input_buffer, output_buffer, other_input_list, other_output_list,
512                        m_hardware->GetExtendedMemory(), on_divide, received_messages_point);
513 
514   //combine global and deme resource counts
515   tArray<double> avatarAndDeme_resource_count = avatar_resource_count; // + deme_resource_count;
516   tArray<double> avatarAndDeme_res_change = avatar_res_change; // + deme_res_change;
517 
518   // set any resource amount to 0 if a cell cannot access this resource
519   int cell_id = m_interface->GetAVCellID();
520   if (cell_id_lists.GetSize())
521   {
522 	  for (int i=0; i<cell_id_lists.GetSize(); i++)
523 	  {
524 		  // if cell_id_lists have been set then we have to check if this cell is in the list
525 		  if (cell_id_lists[i].GetSize()) {
526 			  int j;
527 			  for (j=0; j<cell_id_lists[i].GetSize(); j++)
528 			  {
529 				  if (cell_id==cell_id_lists[i][j])
530 					  break;
531 			  }
532 			  if (j==cell_id_lists[i].GetSize())
533 				  avatarAndDeme_resource_count[i]=0;
534 		  }
535 	  }
536   }
537 
538   bool task_completed = m_phenotype.TestOutput(ctx, taskctx, avatarAndDeme_resource_count,
539                                                m_phenotype.GetCurRBinsAvail(), avatarAndDeme_res_change,
540                                                insts_triggered, is_parasite, context_phenotype);
541 
542   // Handle merit increases that take the organism above it's current population merit
543   if (m_world->GetConfig().MERIT_INC_APPLY_IMMEDIATE.Get()) {
544     double cur_merit = m_phenotype.CalcCurrentMerit();
545     if (m_phenotype.GetMerit().GetDouble() < cur_merit) m_interface->UpdateMerit(cur_merit);
546   }
547 
548   //disassemble avatar and deme resource counts
549   avatar_res_change = avatarAndDeme_res_change.Subset(0, avatar_res_change.GetSize());
550 //  deme_res_change = avatarAndDeme_res_change.Subset(avatar_res_change.GetSize(), avatarAndDeme_res_change.GetSize());
551 
552   if(m_world->GetConfig().ENERGY_ENABLED.Get() && m_world->GetConfig().APPLY_ENERGY_METHOD.Get() == 1 && task_completed) {
553     m_phenotype.RefreshEnergy();
554     m_phenotype.ApplyToEnergyStore();
555     double newMerit = m_phenotype.ConvertEnergyToMerit(m_phenotype.GetStoredEnergy() * m_phenotype.GetEnergyUsageRatio());
556 		m_interface->UpdateMerit(newMerit);
557 		if(GetPhenotype().GetMerit().GetDouble() == 0.0) {
558 			GetPhenotype().SetToDie();
559 		}
560   }
561   m_interface->UpdateAVResources(ctx, avatar_res_change);
562   //update deme resources
563 //  m_interface->UpdateDemeResources(ctx, deme_res_change);
564 
565   for (int i = 0; i < insts_triggered.GetSize(); i++)
566     m_hardware->ProcessBonusInst(ctx, m_hardware->GetInstSet().GetInst(insts_triggered[i]));
567 }
568 
NetGet(cAvidaContext & ctx,int & value,int & seq)569 void cOrganism::NetGet(cAvidaContext& ctx, int& value, int& seq)
570 {
571   assert(m_net);
572   seq = m_net->seq.GetSize();
573   m_net->seq.Resize(seq + 1);
574   value = ctx.GetRandom().GetUInt(1 << 16);
575   m_net->seq[seq].SetValue(value);
576 }
577 
NetSend(cAvidaContext & ctx,int value)578 void cOrganism::NetSend(cAvidaContext& ctx, int value)
579 {
580   assert(m_net);
581   int index = -1;
582 
583   // Search for previously sent value
584   for (int i = m_net->sent.GetSize() - 1; i >= 0; i--) {
585     if (m_net->sent[i].GetValue() == value) {
586       index = i;
587       m_net->sent[i].SetSent();
588       break;
589     }
590   }
591 
592   // If not found, add new message
593   if (index == -1) {
594     index = m_net->sent.GetSize();
595     m_net->sent.Resize(index + 1);
596     m_net->sent[index] = cOrgSourceMessage(value);
597   }
598 
599   // Test if this message will be dropped
600   const double drop_prob = m_world->GetConfig().NET_DROP_PROB.Get();
601   if (drop_prob > 0.0 && ctx.GetRandom().P(drop_prob)) {
602     m_net->sent[index].SetDropped();
603     return;
604   }
605 
606   // Test if this message will be corrupted
607   int actual_value = value;
608   const double mut_prob = m_world->GetConfig().NET_MUT_PROB.Get();
609   if (mut_prob > 0.0 && ctx.GetRandom().P(mut_prob)) {
610     switch (m_world->GetConfig().NET_MUT_TYPE.Get())
611     {
612       case 0: // Flip a single random bit
613         actual_value ^= 1 << ctx.GetRandom().GetUInt(31);
614         m_net->sent[index].SetCorrupted();
615         break;
616       case 1: // Flip the last bit
617         actual_value ^= 1;
618         m_net->sent[index].SetCorrupted();
619         break;
620       default:
621         // invalid selection, no action
622         break;
623     }
624   }
625 
626   assert(m_interface);
627   cOrgSinkMessage* msg = new cOrgSinkMessage(m_interface->GetCellID(), value, actual_value);
628   m_net->pending.Push(msg);
629 }
630 
NetReceive(int & value)631 bool cOrganism::NetReceive(int& value)
632 {
633   assert(m_net && m_interface);
634   cOrgSinkMessage* msg = m_interface->NetReceive();
635   if (msg == NULL) {
636     value = 0;
637     return false;
638   }
639 
640   m_net->received.Push(msg);
641   value = msg->GetActualValue();
642   return true;
643 }
644 
NetValidate(cAvidaContext & ctx,int value)645 void cOrganism::NetValidate(cAvidaContext& ctx, int value)
646 {
647   if (!m_net) return;
648 
649   m_net->valid = false;
650 
651   if (0xFFFF0000 & value) return;
652 
653   for (int i = 0; i < m_net->received.GetSize(); i++) {
654     cOrgSinkMessage* msg = m_net->received[i];
655     if (!msg->GetValidated() && (msg->GetOriginalValue() & 0xFFFF) == value) {
656       msg->SetValidated();
657       assert(m_interface);
658       m_net->valid = m_interface->NetRemoteValidate(ctx, msg);
659       break;
660     }
661   }
662 }
663 
NetRemoteValidate(cAvidaContext & ctx,int value)664 bool cOrganism::NetRemoteValidate(cAvidaContext& ctx, int value)
665 {
666   assert(m_net);
667 
668   bool found = false;
669   for (int i = m_net->last_seq; i < m_net->seq.GetSize(); i++) {
670     cOrgSeqMessage& msg = m_net->seq[i];
671     if (msg.GetValue() == value && !msg.GetReceived()) {
672       m_net->seq[i].SetReceived();
673       found = true;
674       break;
675     }
676   }
677   if (!found) return false;
678 
679   m_net->valid = false;
680   int& completed = m_net->completed;
681   completed = 0;
682   while (m_net->last_seq < m_net->seq.GetSize() && m_net->seq[m_net->last_seq].GetReceived()) {
683     completed++;
684     m_net->last_seq++;
685   }
686 
687   if (completed) {
688     assert(m_interface);
689     const tArray<double>& resource_count = m_interface->GetResources(ctx);
690 
691     tList<tBuffer<int> > other_input_list;
692     tList<tBuffer<int> > other_output_list;
693 
694     // If tasks require us to consider neighbor inputs, collect them...
695     if (m_world->GetEnvironment().UseNeighborInput()) {
696       const int num_neighbors = m_interface->GetNumNeighbors();
697       for (int i = 0; i < num_neighbors; i++) {
698         m_interface->Rotate();
699         cOrganism * cur_neighbor = m_interface->GetNeighbor();
700         if (cur_neighbor == NULL) continue;
701 
702         other_input_list.Push( &(cur_neighbor->m_input_buf) );
703       }
704     }
705 
706     // If tasks require us to consider neighbor outputs, collect them...
707     if (m_world->GetEnvironment().UseNeighborOutput()) {
708       const int num_neighbors = m_interface->GetNumNeighbors();
709       for (int i = 0; i < num_neighbors; i++) {
710         m_interface->Rotate();
711         cOrganism * cur_neighbor = m_interface->GetNeighbor();
712         if (cur_neighbor == NULL) continue;
713 
714         other_output_list.Push( &(cur_neighbor->m_output_buf) );
715       }
716     }
717 
718     // Do the testing of tasks performed...
719     m_output_buf.Add(value);
720     tArray<double> res_change(resource_count.GetSize());
721     tArray<cString> insts_triggered;
722 
723     cTaskContext taskctx(this, m_input_buf, m_output_buf, other_input_list, other_output_list,
724                          m_hardware->GetExtendedMemory());
725     m_phenotype.TestOutput(ctx, taskctx, resource_count, m_phenotype.GetCurRBinsAvail(), res_change, insts_triggered);
726     m_interface->UpdateResources(ctx, res_change);
727 
728     for (int i = 0; i < insts_triggered.GetSize(); i++)
729       m_hardware->ProcessBonusInst(ctx, m_hardware->GetInstSet().GetInst(insts_triggered[i]));
730   }
731 
732   return true;
733 }
734 
HardwareReset(cAvidaContext & ctx)735 void cOrganism::HardwareReset(cAvidaContext& ctx)
736 {
737   if (m_world->GetEnvironment().GetNumStateGrids() > 0 && m_interface) {
738     // Select random state grid in the environment
739     m_cur_sg = m_interface->GetStateGridID(ctx);
740 
741     const cStateGrid& sg = GetStateGrid();
742 
743     tArray<int> sg_state(3 + sg.GetNumStates(), 0);
744 
745     sg_state[0] = sg.GetInitialX();
746     sg_state[1] = sg.GetInitialY();
747     sg_state[2] = sg.GetInitialFacing();
748 
749     m_hardware->SetupExtendedMemory(sg_state);
750   }
751 
752   if (m_net) {
753     while (m_net->pending.GetSize()) delete m_net->pending.Pop();
754     for (int i = 0; i < m_net->received.GetSize(); i++) delete m_net->received[i];
755     m_net->received.Resize(0);
756     m_net->sent.Resize(0);
757     m_net->seq.Resize(0);
758   }
759 
760   if (!m_world->GetConfig().INHERIT_OPINION.Get()) {
761     ClearOpinion();
762   }
763   delete m_org_display;
764   delete m_queued_display_data;
765   m_org_display = NULL;
766   m_queued_display_data = NULL;
767   m_display = false;
768 }
769 
NotifyDeath(cAvidaContext & ctx)770 void cOrganism::NotifyDeath(cAvidaContext& ctx)
771 {
772   // Update Sleeping State
773   if (m_is_sleeping) {
774     m_is_sleeping = false;
775     GetDeme()->DecSleepingCount();
776   }
777 
778   // Return currently stored internal resources to the world
779   if (m_world->GetConfig().USE_RESOURCE_BINS.Get() && m_world->GetConfig().RETURN_STORED_ON_DEATH.Get()) {
780   	m_interface->UpdateResources(ctx, GetRBins());
781   }
782 
783   // Make sure the group composition is updated.
784   if (m_world->GetConfig().USE_FORM_GROUPS.Get() && HasOpinion()) m_interface->LeaveGroup(GetOpinion().first);
785 }
786 
787 
788 
InjectParasite(cBioUnit * parent,const cString & label,const Sequence & injected_code)789 bool cOrganism::InjectParasite(cBioUnit* parent, const cString& label, const Sequence& injected_code)
790 {
791   assert(m_interface);
792   return m_interface->InjectParasite(this, parent, label, injected_code);
793 }
794 
ParasiteInfectHost(cBioUnit * parasite)795 bool cOrganism::ParasiteInfectHost(cBioUnit* parasite)
796 {
797   if (!m_hardware->ParasiteInfectHost(parasite)) return false;
798 
799   m_parasites.Push(parasite);
800   return true;
801 }
802 
ClearParasites()803 void cOrganism::ClearParasites()
804 {
805   for (int i = 0; i < m_parasites.GetSize(); i++) delete m_parasites[i];
806   m_parasites.Resize(0);
807 }
808 
809 
CalcMeritRatio()810 double cOrganism::CalcMeritRatio()
811 {
812   const double age = (double) m_phenotype.GetAge();
813   const double merit = m_phenotype.GetMerit().GetDouble();
814   return (merit > 0.0) ? (age / merit ) : age;
815 }
816 
817 
GetTestOnDivide() const818 bool cOrganism::GetTestOnDivide() const { return m_interface->TestOnDivide(); }
GetSterilizeUnstable() const819 int cOrganism::GetSterilizeUnstable() const { return m_world->GetConfig().STERILIZE_UNSTABLE.Get(); }
820 
GetRevertFatal() const821 bool cOrganism::GetRevertFatal() const { return m_world->GetConfig().REVERT_FATAL.Get(); }
GetRevertNeg() const822 bool cOrganism::GetRevertNeg() const { return m_world->GetConfig().REVERT_DETRIMENTAL.Get(); }
GetRevertNeut() const823 bool cOrganism::GetRevertNeut() const { return m_world->GetConfig().REVERT_NEUTRAL.Get(); }
GetRevertPos() const824 bool cOrganism::GetRevertPos() const { return m_world->GetConfig().REVERT_BENEFICIAL.Get(); }
GetRevertTaskLoss() const825 bool cOrganism::GetRevertTaskLoss() const { return m_world->GetConfig().REVERT_TASKLOSS.Get(); }
GetRevertEquals() const826 bool cOrganism::GetRevertEquals() const { return m_world->GetConfig().REVERT_EQUALS.Get(); }
827 
GetSterilizeFatal() const828 bool cOrganism::GetSterilizeFatal() const { return m_world->GetConfig().STERILIZE_FATAL.Get(); }
GetSterilizeNeg() const829 bool cOrganism::GetSterilizeNeg() const { return m_world->GetConfig().STERILIZE_DETRIMENTAL.Get(); }
GetSterilizeNeut() const830 bool cOrganism::GetSterilizeNeut() const { return m_world->GetConfig().STERILIZE_NEUTRAL.Get(); }
GetSterilizePos() const831 bool cOrganism::GetSterilizePos() const { return m_world->GetConfig().STERILIZE_BENEFICIAL.Get(); }
GetSterilizeTaskLoss() const832 bool cOrganism::GetSterilizeTaskLoss() const { return m_world->GetConfig().STERILIZE_TASKLOSS.Get(); }
GetNeutralMin() const833 double cOrganism::GetNeutralMin() const { return m_world->GetConfig().NEUTRAL_MIN.Get(); }
GetNeutralMax() const834 double cOrganism::GetNeutralMax() const { return m_world->GetConfig().NEUTRAL_MAX.Get(); }
835 
836 
PrintStatus(ostream & fp,const cString & next_name)837 void cOrganism::PrintStatus(ostream& fp, const cString& next_name)
838 {
839   fp << "---------------------------" << endl;
840 	fp << "U:" << m_world->GetStats().GetUpdate() << endl;
841   m_hardware->PrintStatus(fp);
842   m_phenotype.PrintStatus(fp);
843   fp << endl;
844 
845   fp << setbase(16) << setfill('0');
846 
847   fp << "Input (env):";
848   for (int i = 0; i < m_input_buf.GetCapacity(); i++) {
849     int j = i; // temp holder, because GetInputAt self adjusts the input pointer
850     fp << " 0x" << setw(8) << m_interface->GetInputAt(j);
851   }
852   fp << endl;
853 
854   fp << "Input (buf):";
855   for (int i = 0; i < m_hardware->GetInputBuf().GetNumStored(); i++) fp << " 0x" << setw(8) << m_hardware->GetInputBuf()[i];
856   fp << endl;
857 
858   fp << "Output:     ";
859   for (int i = 0; i < m_hardware->GetOutputBuf().GetNumStored(); i++) fp << " 0x" << setw(8) << m_hardware->GetOutputBuf()[i];
860   fp << endl;
861 
862   fp << setfill(' ') << setbase(10);
863 
864   fp << "---------------------------" << endl;
865   fp << "ABOUT TO EXECUTE: " << next_name << endl;
866 }
867 
PrintMiniTraceStatus(cAvidaContext & ctx,ostream & fp,const cString & next_name)868 void cOrganism::PrintMiniTraceStatus(cAvidaContext& ctx, ostream & fp, const cString& next_name)
869 {
870   m_hardware->PrintMiniTraceStatus(ctx, fp, next_name);
871 }
872 
PrintMiniTraceSuccess(ostream & fp,const int exec_success)873 void cOrganism::PrintMiniTraceSuccess(ostream & fp, const int exec_success)
874 {
875   m_hardware->PrintMiniTraceSuccess(fp, exec_success);
876 }
877 
PrintFinalStatus(ostream & fp,int time_used,int time_allocated) const878 void cOrganism::PrintFinalStatus(ostream& fp, int time_used, int time_allocated) const
879 {
880   fp << "---------------------------" << endl;
881   m_phenotype.PrintStatus(fp);
882   fp << endl;
883 
884   if (time_used == time_allocated) {
885     fp << endl << "# TIMEOUT: No offspring produced." << endl;
886   } else if (m_hardware->GetMemory().GetSize() == 0) {
887     fp << endl << "# ORGANISM DEATH: No offspring produced." << endl;
888   } else {
889     fp << endl;
890     fp << "# Final Memory: " << m_hardware->GetMemory().AsString() << endl;
891     fp << "# Child Memory: " << m_offspring_genome.GetSequence().AsString() << endl;
892   }
893 }
894 
Divide_CheckViable(cAvidaContext & ctx)895 bool cOrganism::Divide_CheckViable(cAvidaContext& ctx)
896 {
897   // Make sure required task (if any) has been performed...
898   const int required_task = m_world->GetConfig().REQUIRED_TASK.Get();
899   const int immunity_task = m_world->GetConfig().IMMUNITY_TASK.Get();
900   if (m_world->GetConfig().REQUIRED_PRED_HABITAT.Get() != -1 || m_world->GetConfig().REQUIRED_PREY_HABITAT.Get() != -1) {
901     int habitat_required = -1;
902     double required_value = 0;
903     if (m_forage_target == -2) {
904       habitat_required = m_world->GetConfig().REQUIRED_PRED_HABITAT.Get();
905       required_value = m_world->GetConfig().REQUIRED_PRED_HABITAT_VALUE.Get();
906     }
907     else {
908       habitat_required = m_world->GetConfig().REQUIRED_PREY_HABITAT.Get();
909       required_value = m_world->GetConfig().REQUIRED_PREY_HABITAT_VALUE.Get();
910     }
911     if (habitat_required != -1) {
912       bool has_req_res = false;
913       const cResourceLib& resource_lib = m_world->GetEnvironment().GetResourceLib();
914       tArray<double> resource_count;
915       if (!m_world->GetConfig().USE_AVATARS.Get()) resource_count = m_interface->GetResources(ctx);
916       else resource_count = m_interface->GetAVResources(ctx);
917       for (int i = 0; i < resource_count.GetSize(); i ++) {
918         if (resource_lib.GetResource(i)->GetHabitat() == habitat_required && resource_count[i] >= required_value) {
919           has_req_res = true;
920           break;
921         }
922       }
923       if (!has_req_res) return false;
924     }
925   }
926 
927   if (required_task != -1 && m_phenotype.GetCurTaskCount()[required_task] == 0) {
928     if (immunity_task ==-1 || m_phenotype.GetCurTaskCount()[immunity_task] == 0) {
929       Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
930             cStringUtil::Stringf("Lacks required task (%d)", required_task));
931       return false; //  (divide fails)
932     }
933   }
934 
935   if (GetPhenotype().GetCurBonus() < m_world->GetConfig().REQUIRED_BONUS.Get()) return false;
936 
937   const int required_reaction = m_world->GetConfig().REQUIRED_REACTION.Get();
938   const int immunity_reaction = m_world->GetConfig().IMMUNITY_REACTION.Get();
939   const int single_reaction = m_world->GetConfig().REQUIRE_SINGLE_REACTION.Get();
940 
941   if (single_reaction == 0 && required_reaction != -1 && m_phenotype.GetCurReactionCount()[required_reaction] == 0 && \
942       m_phenotype.GetStolenReactionCount()[required_reaction] == 0)   {
943     if (immunity_reaction == -1 || m_phenotype.GetCurReactionCount()[immunity_reaction] == 0) {
944       Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
945             cStringUtil::Stringf("Lacks required reaction (%d)", required_reaction));
946       return false; //  (divide fails)
947     }
948   }
949 
950   if (single_reaction != 0)
951   {
952     bool toFail = true;
953     tArray<int> reactionCounts = m_phenotype.GetCurReactionCount();
954     for (int i=0; i<reactionCounts.GetSize(); i++) {
955       if (reactionCounts[i] > 0) toFail = false;
956     }
957 
958     if (toFail) {
959       const tArray<int> stolenReactions = m_phenotype.GetStolenReactionCount();
960       for (int i = 0; i < stolenReactions.GetSize(); i++) {
961         if (stolenReactions[i] > 0) toFail = false;
962       }
963     }
964 
965     if (toFail) {
966       Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR, cStringUtil::Stringf("Lacks any reaction required for divide"));
967       return false; //  (divide fails)
968     }
969   }
970 
971   // Test for required resource availability (must be stored in an internal resource bin)
972   const int required_resource = m_world->GetConfig().REQUIRED_RESOURCE.Get();
973   const double required_resource_level = m_world->GetConfig().REQUIRED_RESOURCE_LEVEL.Get();
974   if (required_resource != -1 && required_resource_level > 0.0) {
975     const double resource_level = m_phenotype.GetCurRBinAvail(required_resource);
976     if (resource_level < required_resource_level) return false;
977     else AddToRBin(required_resource, -required_resource_level);
978   }
979 
980   // Make sure the parent is fertile
981   if ( m_phenotype.IsFertile() == false ) {
982     Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR, "Infertile organism");
983     return false; //  (divide fails)
984   }
985 
986   return true;  // Organism has no problem with divide...
987 }
988 
989 
990 // This gets called after a successful divide to deal with the child.
991 // Returns true if parent lives through this process.
992 
ActivateDivide(cAvidaContext & ctx,cContextPhenotype * context_phenotype)993 bool cOrganism::ActivateDivide(cAvidaContext& ctx, cContextPhenotype* context_phenotype)
994 {
995   assert(m_interface);
996   // Test tasks one last time before actually dividing, pass true so
997   // know that should only test "divide" tasks here
998   DoOutput(ctx, true, context_phenotype);
999 
1000   // Activate the child!  (Keep Last: may kill this organism!)
1001   return m_interface->Divide(ctx, this, m_offspring_genome);
1002 }
1003 
1004 
Fault(int fault_loc,int fault_type,cString fault_desc)1005 void cOrganism::Fault(int fault_loc, int fault_type, cString fault_desc)
1006 {
1007   (void) fault_loc;
1008   (void) fault_type;
1009   (void) fault_desc;
1010 
1011   // FATAL_ERRORS
1012 #if 0
1013   if (fault_type == FAULT_TYPE_ERROR) {
1014     m_phenotype.IsFertile() = false;
1015   }
1016 #endif
1017 
1018   // FATAL_WARNINGS
1019 #if 0
1020   if (fault_type == FAULT_TYPE_WARNING) {
1021     m_phenotype.IsFertile() = false;
1022   }
1023 #endif
1024 
1025   // BREAKPOINTS
1026 #if 0
1027   m_phenotype.SetFault(fault_desc);
1028 #endif
1029 
1030   m_phenotype.IncErrors();
1031 }
1032 
NewTrial()1033 void cOrganism::NewTrial()
1034 {
1035   //More should be reset here... @JEB
1036   GetPhenotype().NewTrial();
1037   m_input_pointer = 0;
1038   m_input_buf.Clear();
1039   m_output_buf.Clear();
1040 }
1041 
1042 
1043 /*! Called as the bottom-half of a successfully sent message.
1044  */
MessageSent(cAvidaContext & ctx,cOrgMessage & msg)1045 void cOrganism::MessageSent(cAvidaContext& ctx, cOrgMessage& msg) {
1046   // check to see if we should store it:
1047   const int bsize = m_world->GetConfig().MESSAGE_SEND_BUFFER_SIZE.Get();
1048 
1049   if((bsize > 0) || (bsize == -1)) {
1050     // yep; store it:
1051     m_msg->sent.push_back(msg);
1052     // and set the receiver-pointer of this message to NULL.  We don't want to
1053     // walk this list later thinking that the receivers are still around.
1054     m_msg->sent.back().SetReceiver(0);
1055     // if our buffer is too large, chop off old messages:
1056     while((bsize != -1) && (static_cast<int>(m_msg->sent.size()) > bsize)) {
1057       m_msg->sent.pop_front();
1058     }
1059   }
1060 }
1061 
1062 
1063 /*! Send a message to the currently faced organism.  Stat-tracking is done over
1064  in cPopulationInterface.  Remember that this code WILL be called from within the
1065  test CPU!  (Also, BroadcastMessage funnels down to code in the population interface
1066  too, so this way all the message sending code is in the same place.)
1067  */
SendMessage(cAvidaContext & ctx,cOrgMessage & msg)1068 bool cOrganism::SendMessage(cAvidaContext& ctx, cOrgMessage& msg)
1069 {
1070   assert(m_interface);
1071   InitMessaging();
1072 
1073   // check to see if we've performed any tasks:
1074   if (m_world->GetConfig().CHECK_TASK_ON_SEND.Get()) {
1075     DoOutput(ctx, static_cast<int>(msg.GetData()));
1076   }
1077   // if we sent the message:
1078   if(m_interface->SendMessage(msg)) {
1079     MessageSent(ctx, msg);
1080     return true;
1081   }
1082   // importantly, m_interface->SendMessage() fails if we're running in the test CPU.
1083   return false;
1084 }
1085 
1086 
1087 /*! Broadcast a message to all organisms out to the given depth.
1088  */
BroadcastMessage(cAvidaContext & ctx,cOrgMessage & msg,int depth)1089 bool cOrganism::BroadcastMessage(cAvidaContext& ctx, cOrgMessage& msg, int depth) {
1090   assert(m_interface);
1091   InitMessaging();
1092 
1093 	// if we broadcasted the message:
1094 	if(m_interface->BroadcastMessage(msg, depth)) {
1095 		MessageSent(ctx, msg);
1096     return true;
1097   }
1098 
1099 	// Again, m_interface->BroadcastMessage() fails if we're running in the test CPU.
1100 	return false;
1101 }
1102 
1103 
1104 /*! Called when this organism receives a message from another.
1105  */
ReceiveMessage(cOrgMessage & msg)1106 void cOrganism::ReceiveMessage(cOrgMessage& msg)
1107 {
1108   InitMessaging();
1109 
1110   // don't store more messages than we're configured to.
1111   const int bsize = m_world->GetConfig().MESSAGE_RECV_BUFFER_SIZE.Get();
1112   if((bsize != -1) && (bsize <= static_cast<int>(m_msg->received.size()))) {
1113     switch(m_world->GetConfig().MESSAGE_RECV_BUFFER_BEHAVIOR.Get()) {
1114     case 0: // drop oldest message
1115       m_msg->received.pop_front();
1116       break;
1117     case 1: // drop this message
1118       return;
1119     default: // error
1120       m_world->GetDriver().RaiseFatalException(-1, "MESSAGE_RECV_BUFFER_BEHAVIOR is set to an invalid value.");
1121       assert(false);
1122     }
1123   }
1124 
1125   msg.SetReceiver(this);
1126   m_msg->received.push_back(msg);
1127 
1128   if (m_world->GetConfig().ACTIVE_MESSAGES_ENABLED.Get() > 0) {
1129     // then create new thread and load its registers
1130     m_hardware->InterruptThread(cHardwareBase::MSG_INTERRUPT);
1131   }
1132 }
1133 
1134 
1135 /*! Called to when this organism tries to load its CPU with the contents of a
1136  previously-received message.  In a change from previous versions, pop the message
1137  off the front.
1138 
1139  \return A pair (b, msg): if b is true, then msg was received; if b is false, then msg was not received.
1140  */
RetrieveMessage()1141 std::pair<bool, cOrgMessage> cOrganism::RetrieveMessage() {
1142   InitMessaging();
1143 	std::pair<bool, cOrgMessage> ret = std::make_pair(false, cOrgMessage());
1144 
1145 	if(m_msg->received.size() > 0) {
1146 		ret.second = m_msg->received.front();
1147 		ret.first = true;
1148 		m_msg->received.pop_front();
1149 	}
1150 
1151 	return ret;
1152 }
1153 
Move(cAvidaContext & ctx)1154 bool cOrganism::Move(cAvidaContext& ctx)
1155 {
1156   assert(m_interface);
1157   if (m_is_dead) return false;
1158   /*********************/
1159   // TEMP.  Remove once movement tasks are implemented.
1160   if (GetCellData() < GetFacedCellData()) { // move up gradient
1161     SetGradientMovement(1.0);
1162   } else if(GetCellData() == GetFacedCellData()) {
1163     SetGradientMovement(0.0);
1164   } else { // move down gradient
1165     SetGradientMovement(-1.0);
1166   }
1167   /*********************/
1168 
1169   int fromcellID = GetCellID();
1170   int destcellID = GetFacedCellID();
1171 
1172   int facing = GetFacedDir();
1173 
1174   // Actually perform the move
1175   if (m_interface->Move(ctx, fromcellID, destcellID)) {
1176     //Keep track of successful movement E/W and N/S in support of get-easterly and get-northerly for navigation
1177     //Skip counting if random < chance of miscounting a step.
1178     if (m_world->GetConfig().STEP_COUNTING_ERROR.Get()==0 || m_world->GetRandom().GetInt(0,101) > m_world->GetConfig().STEP_COUNTING_ERROR.Get()) {
1179       if (facing == 0) m_northerly = m_northerly - 1;       // N
1180       else if (facing == 1) {                           // NE
1181         m_northerly = m_northerly - 1;
1182         m_easterly = m_easterly + 1;
1183       }
1184       else if (facing == 2) m_easterly = m_easterly + 1;    // E
1185       else if (facing == 3) {                           // SE
1186         m_northerly = m_northerly + 1;
1187         m_easterly = m_easterly + 1;
1188       }
1189       else if (facing == 4) m_northerly = m_northerly + 1;  // S
1190       else if (facing == 5) {                           // SW
1191         m_northerly = m_northerly + 1;
1192         m_easterly = m_easterly - 1;
1193       }
1194       else if (facing == 6) m_easterly = m_easterly - 1;    // W
1195       else if (facing == 7) {                           // NW
1196         m_northerly = m_northerly - 1;
1197         m_easterly = m_easterly - 1;
1198       }
1199     }
1200   }
1201   else return false;
1202 
1203   // Check to make sure the organism is alive after the move
1204   if (m_phenotype.GetToDelete()) return false;
1205 
1206   // updates movement predicates
1207   m_world->GetStats().Move(*this);
1208 
1209   // Pheromone drop stuff
1210   double pher_amount = 0; // this is used in the logging
1211   int drop_mode = -1;
1212 
1213   // If organism is dropping pheromones, mark the appropriate cell(s)
1214   if (m_world->GetConfig().PHEROMONE_ENABLED.Get() == 1 && GetPheromoneStatus() == true) {
1215     pher_amount = m_world->GetConfig().PHEROMONE_AMOUNT.Get();
1216     drop_mode = m_world->GetConfig().PHEROMONE_DROP_MODE.Get();
1217 
1218     cDeme* deme = GetDeme();
1219 
1220     if (drop_mode == 0) {
1221       deme->AddPheromone(fromcellID, pher_amount / 2, ctx);
1222       deme->AddPheromone(destcellID, pher_amount / 2, ctx);
1223     } else if(drop_mode == 1) {
1224       deme->AddPheromone(fromcellID, pher_amount, ctx);
1225     } else if(drop_mode == 2) {
1226       deme->AddPheromone(destcellID, pher_amount, ctx);
1227     }
1228   } // End laying pheromone
1229 
1230   // Write some logging information if LOG_PHEROMONE is set.  This is done
1231   // out here so that non-pheromone moves are recorded.
1232   if (m_world->GetConfig().LOG_PHEROMONE.Get() == 1 &&
1233       m_world->GetStats().GetUpdate() >= m_world->GetConfig().MOVETARGET_LOG_START.Get()) {
1234     cDataFile& df = m_world->GetDataFile("movelog.dat");
1235 
1236     int rel_srcid = GetDeme()->GetRelativeCellID(fromcellID);
1237     int rel_destid = GetDeme()->GetRelativeCellID(destcellID);
1238 
1239     cString UpdateStr = cStringUtil::Stringf("%d,%d,%d,%d,%d,%f,%d,5",  m_world->GetStats().GetUpdate(), GetID(), GetDeme()->GetDemeID(), rel_srcid, rel_destid, pher_amount, drop_mode);
1240     df.WriteRaw(UpdateStr);
1241   }
1242 
1243   // don't trigger reactions on move if you're not supposed to!
1244   const cEnvironment& env = m_world->GetEnvironment();
1245   const int num_tasks = env.GetNumTasks();
1246   for (int i = 0; i < num_tasks; i++) {
1247     if (env.GetTask(i).GetDesc() == "move_up_gradient" || \
1248         env.GetTask(i).GetDesc() == "move_neutral_gradient" || \
1249         env.GetTask(i).GetDesc() == "move_down_gradient" || \
1250         env.GetTask(i).GetDesc() == "move_not_up_gradient" || \
1251         env.GetTask(i).GetDesc() == "move_to_right_side" || \
1252         env.GetTask(i).GetDesc() == "move_to_left_side" || \
1253         env.GetTask(i).GetDesc() == "move" || \
1254         env.GetTask(i).GetDesc() == "movetotarget" || \
1255         env.GetTask(i).GetDesc() == "movetoevent" || \
1256         env.GetTask(i).GetDesc() == "movebetweenevent" || \
1257         env.GetTask(i).GetDesc() == "move_to_event") {
1258       DoOutput(ctx);
1259       break;
1260     }
1261   }
1262 
1263   if (m_world->GetConfig().ACTIVE_MESSAGES_ENABLED.Get() > 0) {
1264     // then create new thread and load its registers
1265     m_hardware->InterruptThread(cHardwareBase::MOVE_INTERRUPT);
1266   }
1267   return true;
1268 } //End cOrganism::Move()
1269 
BcastAlarmMSG(cAvidaContext & ctx,int jump_label,int bcast_range)1270 bool cOrganism::BcastAlarmMSG(cAvidaContext& ctx, int jump_label, int bcast_range) {
1271   assert(m_interface);
1272 
1273   // If we're able to succesfully send an alarm...
1274   if(m_interface->BcastAlarm(jump_label, bcast_range)) {
1275     // check to see if we've performed any tasks...
1276     DoOutput(ctx);
1277     return true;
1278   }
1279   return false;
1280 }
1281 
moveIPtoAlarmLabel(int jump_label)1282 void cOrganism::moveIPtoAlarmLabel(int jump_label) {
1283   // move IP to alarm_label
1284   m_hardware->Jump_To_Alarm_Label(jump_label);
1285 }
1286 
1287 
1288 /*! Called to set this organism's opinion, which remains valid until a new opinion
1289  is expressed.
1290  */
SetOpinion(const Opinion & opinion)1291 void cOrganism::SetOpinion(const Opinion& opinion) {
1292   InitOpinions();
1293   const int bsize = m_world->GetConfig().OPINION_BUFFER_SIZE.Get();
1294 
1295   if(bsize == 0) {
1296     m_world->GetDriver().RaiseFatalException(-1, "OPINION_BUFFER_SIZE is set to an invalid value.");
1297   }
1298 
1299   if((bsize > 0) || (bsize == -1)) {
1300     m_opinion->opinion_list.push_back(std::make_pair(opinion, m_world->GetStats().GetUpdate()));
1301     // if our buffer is too large, chop off old messages:
1302     while((bsize != -1) && (static_cast<int>(m_opinion->opinion_list.size()) > bsize)) {
1303       m_opinion->opinion_list.pop_front();
1304     }
1305   }
1306   // if using avatars, make sure you swap avatar lists if the org's catorization changes!
1307 }
1308 
1309 // Checks if the organism has an opinion.
HasOpinion()1310 bool cOrganism::HasOpinion() {
1311   InitOpinions();
1312   if (m_opinion->opinion_list.empty()) return false;
1313   else return true;
1314 }
1315 
SetForageTarget(int forage_target)1316 void cOrganism::SetForageTarget(int forage_target) {
1317   // if using avatars, make sure you swap avatar lists if the org type changes!
1318   if (m_world->GetConfig().PRED_PREY_SWITCH.Get() == -2 || m_world->GetConfig().PRED_PREY_SWITCH.Get() > -1) {
1319     if (forage_target <= -2 && m_forage_target > -2) {
1320       m_interface->DecNumPreyOrganisms();
1321       m_interface->IncNumPredOrganisms();
1322     }
1323     else if (forage_target > -2 && m_forage_target <= -2) {
1324       m_interface->IncNumPreyOrganisms();
1325       m_interface->DecNumPredOrganisms();
1326     }
1327   }
1328   m_forage_target = forage_target;
1329 }
1330 
CopyParentFT()1331 void cOrganism::CopyParentFT() {
1332   bool copy_ft = true;
1333   // close potential loop-hole allowing orgs to switch ft to prey at birth, collect res,
1334   // switch ft to pred, and then copy parent to become prey again.
1335   if (m_world->GetConfig().PRED_PREY_SWITCH.Get() <= 0 || m_world->GetConfig().PRED_PREY_SWITCH.Get() == 2) {
1336     if (m_parent_ft != -2 && m_forage_target < -1) {
1337       copy_ft = false;
1338     }
1339   }
1340   if (copy_ft) SetForageTarget(m_parent_ft);
1341 }
1342 
1343 /*! Called when an organism receives a flash from a neighbor. */
ReceiveFlash()1344 void cOrganism::ReceiveFlash() {
1345   m_hardware->ReceiveFlash();
1346 }
1347 
1348 
1349 /*! Called by the "flash" instruction. */
SendFlash(cAvidaContext & ctx)1350 void cOrganism::SendFlash(cAvidaContext& ctx) {
1351   assert(m_interface);
1352 
1353   // Check to see if we should lose the flash:
1354   if((m_world->GetConfig().SYNC_FLASH_LOSSRATE.Get() > 0.0) &&
1355      (m_world->GetRandom().P(m_world->GetConfig().SYNC_FLASH_LOSSRATE.Get()))) {
1356     return;
1357   }
1358 
1359   // Flash not lost; continue.
1360   m_interface->SendFlash();
1361   m_world->GetStats().SentFlash(*this);
1362   DoOutput(ctx);
1363 }
1364 
1365 
GetNeighborhood()1366 cOrganism::Neighborhood cOrganism::GetNeighborhood() {
1367 	Neighborhood neighbors;
1368 	for(int i=0; i<GetNeighborhoodSize(); ++i, Rotate(1)) {
1369 		if(IsNeighborCellOccupied()) {
1370 			neighbors.insert(GetNeighbor()->GetID());
1371 		}
1372 	}
1373 	return neighbors;
1374 }
1375 
1376 
LoadNeighborhood()1377 void cOrganism::LoadNeighborhood() {
1378 	InitNeighborhood();
1379 	m_neighborhood->neighbors = GetNeighborhood();
1380 	m_neighborhood->loaded = true;
1381 }
1382 
1383 
HasNeighborhoodChanged()1384 bool cOrganism::HasNeighborhoodChanged() {
1385 	InitNeighborhood();
1386 	// Must have loaded the neighborhood first:
1387 	if(!m_neighborhood->loaded) return false;
1388 
1389 	// Ok, get the symmetric difference between the old neighborhood and the current neighborhood:
1390 	Neighborhood symdiff;
1391 	Neighborhood current = GetNeighborhood();
1392 	std::set_symmetric_difference(m_neighborhood->neighbors.begin(),
1393 																m_neighborhood->neighbors.end(),
1394 																current.begin(),
1395 																current.end(),
1396 																std::insert_iterator<Neighborhood>(symdiff, symdiff.begin()));
1397 
1398 	// If the symmetric difference is empty, then nothing has changed -- return
1399 	return !symdiff.empty();
1400 }
1401 
1402 
1403 /* Called when raw materials are donated to others or when the
1404  raw materials are consumed. Amount is the number of resources
1405  donated. The boolean flag is used to indicate if the donation
1406  was successful... It would fail if the organism did not have
1407  that many resources. */
SubtractSelfRawMaterials(int amount)1408 bool cOrganism::SubtractSelfRawMaterials (int amount)
1409 {
1410 	bool isSuccessful = false;
1411 	if (amount <= m_self_raw_materials) {
1412 		isSuccessful = true;
1413 		m_self_raw_materials -= amount;
1414 	}
1415 	return isSuccessful;
1416 }
1417 
1418 
1419 /* Called when other raw materials are consumed. Amount is the
1420  number of resources consumed. The boolean flag is used to
1421  indicate if the donation was successful... It would fail if
1422  the organism did not have that many resources. */
SubtractOtherRawMaterials(int amount)1423 bool cOrganism::SubtractOtherRawMaterials (int amount)
1424 {
1425 	bool isSuccessful = false;
1426 	if (amount <= m_other_raw_materials) {
1427 		isSuccessful = true;
1428 		m_other_raw_materials -= amount;
1429 	}
1430 	return isSuccessful;
1431 }
1432 
1433 /* Called when raw materials are received from others. Amount
1434  is the number of resources received. The boolean flag is used
1435  to indicate if the reception was successful, which should always
1436  be the case... */
1437 
AddOtherRawMaterials(int amount,int donor_id)1438 bool cOrganism::AddOtherRawMaterials (int amount, int donor_id) {
1439 	bool isSuccessful = true;
1440 	m_other_raw_materials += amount;
1441 	donor_list.insert(donor_id);
1442 	m_num_donate_received += amount;
1443 	m_amount_donate_received++;
1444 	return isSuccessful;
1445 }
1446 
1447 /* Called when raw materials are received from others. Amount
1448  is the number of resources received. The boolean flag is used
1449  to indicate if the reception was successful, which should always
1450  be the case...
1451 
1452  This version is used if there is only one resource that is both
1453  donated and recieved.
1454  */
1455 
AddRawMaterials(int amount,int donor_id)1456 bool cOrganism::AddRawMaterials (int amount, int donor_id) {
1457 	bool isSuccessful = true;
1458 	m_self_raw_materials += amount;
1459 	donor_list.insert(donor_id);
1460 	m_num_donate_received += amount;
1461 	m_amount_donate_received++;
1462 	return isSuccessful;
1463 }
1464 
1465 
1466 /* Get an organism's reputation, which is expressed as an
1467  opinion. 0 is the default reputation (this should be refactored
1468  to be cleaner). */
GetReputation()1469 int cOrganism::GetReputation() {
1470 	int rep =0;
1471 	if (HasOpinion()) {
1472 		rep = GetOpinion().first;
1473 	}
1474 	return rep;
1475 }
1476 
1477 /* Set an organism's reputation */
SetReputation(int rep)1478 void cOrganism::SetReputation(int rep) {
1479 	SetOpinion(rep);
1480 	return;
1481 }
1482 
1483 /* An organism's reputation is based on a running average*/
SetAverageReputation(int rep)1484 void cOrganism::SetAverageReputation(int rep){
1485 	int current_total = GetReputation() * m_opinion->opinion_list.size();
1486 	int new_rep = (current_total + rep)/(m_opinion->opinion_list.size()+1);
1487 	SetReputation(new_rep);
1488 }
1489 
1490 
1491 /* Check if an organism has previously donated to this organism */
IsDonor(int neighbor_id)1492 bool cOrganism::IsDonor(int neighbor_id)
1493 {
1494 	bool found = false;
1495 	if (donor_list.find(neighbor_id) != donor_list.end()) {
1496 		found = true;
1497 	}
1498 	return found;
1499 }
1500 
1501 
1502 
1503 /* Update the tag. If the organism was not already tagged,
1504  or the new tag is the same as the old tag, or the number
1505  of bits is > than the old tag, update.*/
UpdateTag(int new_tag,int bits)1506 void cOrganism::UpdateTag(int new_tag, int bits)
1507 {
1508 	unsigned int rand_int = m_world->GetRandom().GetUInt(0, 2);
1509 	if ((m_tag.first == -1) ||
1510 			(m_tag.first == new_tag) ||
1511 			(m_tag.second < bits)) {
1512 		m_tag = make_pair(new_tag, bits);
1513 	} else if ((m_tag.second == bits) && rand_int){
1514 		m_tag = make_pair(new_tag, bits);
1515 	}
1516 }
1517 
1518 
1519 /* See if the output buffer matches the string */
MatchOutputBuffer(cString string_to_match)1520 int cOrganism::MatchOutputBuffer(cString string_to_match)
1521 {
1522 	tBuffer<int> org_str (GetOutputBuf());
1523 	int num_matched =0;
1524 	for (int j = 0; j < string_to_match.GetSize(); j++)
1525 	{
1526 		if (string_to_match[j]=='0' && org_str[j]==0 ||
1527 				string_to_match[j]=='1' && org_str[j]==1)
1528 			num_matched++;
1529 	}
1530 	return num_matched;
1531 }
1532 
1533 
SetOutputNegative1()1534 void cOrganism::SetOutputNegative1()
1535 {
1536 	for (int i=0; i<GetOutputBuf().GetCapacity(); i++) {
1537 		AddOutput(-1);
1538 	}
1539 	m_output_buf.Clear();
1540 }
1541 
1542 /* Initialize the string tracking map */
InitStringMap()1543 void cOrganism::InitStringMap()
1544 {
1545 	if (!m_string_map.size()) {
1546 		// Get the strings from the task lib.
1547 		std::vector < cString > temp_strings = m_world->GetEnvironment().GetMatchStringsFromTask();
1548 		// Create structure for each of them.
1549 		for (unsigned int i=0; i < temp_strings.size(); i++){
1550 			m_string_map[i].m_string = temp_strings[i];
1551 		}
1552 	}
1553 }
1554 
1555 
ProduceString(int i)1556 bool cOrganism::ProduceString(int i)
1557 {
1558 	bool val = false;
1559 	int cap = m_world->GetConfig().STRING_AMOUNT_CAP.Get();
1560 	if ((cap == -1) || (m_string_map[i].on_hand < cap))
1561 	{
1562 		m_string_map[i].prod_string++;
1563 		m_string_map[i].on_hand++;
1564 		val = true;
1565 	}
1566 	return val;
1567 }
1568 
1569 /* Donate a string*/
DonateString(int string_tag,int amount)1570 bool cOrganism::DonateString(int string_tag, int amount)
1571 {
1572 	bool val = false;
1573 	if (m_string_map[string_tag].on_hand >= amount) {
1574 		val = true;
1575 		m_string_map[string_tag].on_hand -= amount;
1576 	}
1577 	return val;
1578 
1579 }
1580 
1581 /* Receive a string*/
ReceiveString(int string_tag,int amount,int donor_id)1582 bool cOrganism::ReceiveString(int string_tag, int amount, int donor_id)
1583 {
1584 	bool val = false;
1585 	int cap = m_world->GetConfig().STRING_AMOUNT_CAP.Get();
1586 	if ((cap == -1) || (m_string_map[string_tag].on_hand < cap))
1587 	{
1588 		m_string_map[string_tag].received_string++;
1589 		m_string_map[string_tag].on_hand++;
1590 		donor_list.insert(donor_id);
1591 		m_num_donate_received += amount;
1592 		m_amount_donate_received++;
1593 		val = true;
1594 	}
1595 	return val;
1596 }
1597 
1598 /* Check to see if this amount is below the organism's cap*/
CanReceiveString(int string_tag,int amount)1599 bool cOrganism::CanReceiveString(int string_tag, int amount)
1600 {
1601 	bool val = false;
1602 	int cap = m_world->GetConfig().STRING_AMOUNT_CAP.Get();
1603 	if ((cap == -1) || (m_string_map[string_tag].on_hand < cap))
1604 	{
1605 		val = true;
1606 	}
1607 	return val;
1608 
1609 }
1610 
IsInterrupted()1611 bool cOrganism::IsInterrupted()
1612 {
1613   for (int k = 0; k< GetHardware().GetNumThreads(); ++k) if (GetHardware().GetThreadMessageTriggerType(k) != -1) return true;
1614   return false;
1615 }
1616 
DonateResConsumedToDeme()1617 void cOrganism::DonateResConsumedToDeme()
1618 {
1619 	cDeme* deme = m_interface->GetDeme();
1620 
1621 	if(deme) {
1622 		deme->AddResourcesConsumed(m_phenotype.GetResourcesConsumed());
1623 	}
1624 	return;
1625 }
1626 
MoveAV(cAvidaContext & ctx)1627 bool cOrganism::MoveAV(cAvidaContext& ctx)
1628 {
1629   assert(m_interface);
1630   if (m_is_dead) return false;
1631 
1632   // Actually perform the move
1633   if (m_interface->MoveAV(ctx)) {
1634     //Keep track of successful movement E/W and N/S in support of get-easterly and get-northerly for navigation
1635     //Skip counting if random < chance of miscounting a step.
1636     if (m_world->GetConfig().STEP_COUNTING_ERROR.Get() == 0 || m_world->GetRandom().GetInt(0,101) > m_world->GetConfig().STEP_COUNTING_ERROR.Get()) {
1637       int facing = m_interface->GetAVFacing();
1638 
1639       if (facing == 0)
1640         m_northerly = m_northerly - 1;                  // N
1641       else if (facing == 1) {
1642         m_northerly = m_northerly - 1;                  // NE
1643         m_easterly = m_easterly + 1;
1644       }
1645       else if (facing == 2)
1646         m_easterly = m_easterly + 1;                    // E
1647       else if (facing == 3) {
1648         m_northerly = m_northerly + 1;                  // SE
1649         m_easterly = m_easterly + 1;
1650       }
1651       else if (facing == 4)
1652         m_northerly = m_northerly + 1;                  // S
1653       else if (facing == 5) {
1654         m_northerly = m_northerly + 1;                  // SW
1655         m_easterly = m_easterly - 1;
1656       }
1657       else if (facing == 6)
1658         m_easterly = m_easterly - 1;                    // W
1659       else if (facing == 7) {
1660         m_northerly = m_northerly - 1;                  // NW
1661         m_easterly = m_easterly - 1;
1662       }
1663     }
1664     else return false;
1665   }
1666 
1667   // Check to make sure the organism is alive after the move
1668   if (m_phenotype.GetToDelete()) return false;
1669 
1670   // updates movement predicates
1671   //  m_world->GetStats().Move(*this);
1672 
1673   return true;
1674 }
1675