1 /*
2  *  cPopulationInterface.cc
3  *  Avida
4  *
5  *  Called "pop_interface.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 "cPopulationInterface.h"
24 
25 #include "apto/platform.h"
26 
27 #include "cDeme.h"
28 #include "cEnvironment.h"
29 #include "cHardwareManager.h"
30 #include "cOrganism.h"
31 #include "cOrgSinkMessage.h"
32 #include "cOrgMessage.h"
33 #include "cPopulation.h"
34 #include "cStats.h"
35 #include "cTestCPU.h"
36 #include "cRandom.h"
37 #include "cInstSet.h"
38 
39 #include <cassert>
40 #include <algorithm>
41 #include <iterator>
42 
43 #ifndef NULL
44 #define NULL 0
45 #endif
46 
47 #if APTO_PLATFORM_WINDOWS
48 namespace std
49 {
50   /*inline __int64  abs(__int64 i) { return _abs64(i); }*/
51 }
52 #endif
53 
54 
cPopulationInterface(cWorld * world)55 cPopulationInterface::cPopulationInterface(cWorld* world)
56 : m_world(world)
57 , m_cell_id(-1)
58 , m_deme_id(-1)
59 , m_prevseen_cell_id(-1)
60 , m_prev_task_cell(-1)
61 , m_num_task_cells(0)
62 , m_hgt_support(NULL)
63 {
64 }
65 
~cPopulationInterface()66 cPopulationInterface::~cPopulationInterface() {
67 	if(m_hgt_support) {
68 		delete m_hgt_support;
69 	}
70 }
71 
GetOrganism()72 cOrganism* cPopulationInterface::GetOrganism() {
73 	return GetCell()->GetOrganism();
74 }
75 
GetLiveOrgList() const76 const tSmartArray <cOrganism*> cPopulationInterface::GetLiveOrgList() const {
77   return m_world->GetPopulation().GetLiveOrgList();
78 }
79 
GetCell()80 cPopulationCell* cPopulationInterface::GetCell() {
81 	return &m_world->GetPopulation().GetCell(m_cell_id);
82 }
83 
GetCell(int cell_id)84 cPopulationCell* cPopulationInterface::GetCell(int cell_id) {
85 	return &m_world->GetPopulation().GetCell(cell_id);
86 }
87 
GetCellXPosition()88 int cPopulationInterface::GetCellXPosition()
89 {
90   const int absolute_cell_ID = GetCellID();
91   const int deme_id = GetDemeID();
92   std::pair<int, int> pos = m_world->GetPopulation().GetDeme(deme_id).GetCellPosition(absolute_cell_ID);
93   return pos.first;
94 }
95 
GetCellYPosition()96 int cPopulationInterface::GetCellYPosition()
97 {
98   const int absolute_cell_ID = GetCellID();
99   const int deme_id = GetDemeID();
100   std::pair<int, int> pos = m_world->GetPopulation().GetDeme(deme_id).GetCellPosition(absolute_cell_ID);
101   return pos.second;
102 }
103 
GetCellFaced()104 cPopulationCell* cPopulationInterface::GetCellFaced() {
105 	return &GetCell()->GetCellFaced();
106 }
107 
GetDeme()108 cDeme* cPopulationInterface::GetDeme() {
109   return &m_world->GetPopulation().GetDeme(m_deme_id);
110 }
111 
GetCellData()112 int cPopulationInterface::GetCellData() {
113   m_world->GetPopulation().GetCell(m_cell_id).UpdateCellDataExpired();
114   return m_world->GetPopulation().GetCell(m_cell_id).GetCellData();
115 }
116 
GetCellDataOrgID()117 int cPopulationInterface::GetCellDataOrgID() {
118   m_world->GetPopulation().GetCell(m_cell_id).UpdateCellDataExpired();
119   return m_world->GetPopulation().GetCell(m_cell_id).GetCellDataOrgID();
120 }
121 
GetCellDataUpdate()122 int cPopulationInterface::GetCellDataUpdate() {
123   m_world->GetPopulation().GetCell(m_cell_id).UpdateCellDataExpired();
124   return m_world->GetPopulation().GetCell(m_cell_id).GetCellDataUpdate();
125 }
126 
GetCellDataTerritory()127 int cPopulationInterface::GetCellDataTerritory() {
128   m_world->GetPopulation().GetCell(m_cell_id).UpdateCellDataExpired();
129   return m_world->GetPopulation().GetCell(m_cell_id).GetCellDataTerritory();
130 }
131 
GetCellDataForagerType()132 int cPopulationInterface::GetCellDataForagerType() {
133   m_world->GetPopulation().GetCell(m_cell_id).UpdateCellDataExpired();
134   return m_world->GetPopulation().GetCell(m_cell_id).GetCellDataForagerType();
135 }
136 
GetFacedCellData()137 int cPopulationInterface::GetFacedCellData() {
138   return m_world->GetPopulation().GetCell(m_cell_id).GetCellFaced().GetCellData();
139 }
140 
GetFacedCellDataOrgID()141 int cPopulationInterface::GetFacedCellDataOrgID() {
142   return m_world->GetPopulation().GetCell(m_cell_id).GetCellFaced().GetCellDataOrgID();
143 }
144 
GetFacedCellDataUpdate()145 int cPopulationInterface::GetFacedCellDataUpdate() {
146   return m_world->GetPopulation().GetCell(m_cell_id).GetCellFaced().GetCellDataUpdate();
147 }
148 
GetFacedCellDataTerritory()149 int cPopulationInterface::GetFacedCellDataTerritory() {
150   return m_world->GetPopulation().GetCell(m_cell_id).GetCellFaced().GetCellDataTerritory();
151 }
152 
SetCellData(const int newData)153 void cPopulationInterface::SetCellData(const int newData) {
154   cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
155   cell.SetCellData(newData, cell.GetOrganism()->GetID());
156 }
157 
GetLGTFragment(cAvidaContext & ctx,int region,const Genome & dest_genome,Sequence & seq)158 bool cPopulationInterface::GetLGTFragment(cAvidaContext& ctx, int region, const Genome& dest_genome, Sequence& seq)
159 {
160   const int MAX_POP_SAMPLES = 10;
161   const Sequence* src_seq = NULL;
162 
163   switch (region) {
164       // Local Neighborhood
165     case 0:
166     {
167       Apto::Array<cPopulationCell*> occupied_cells;
168       GetCell()->GetOccupiedNeighboringCells(occupied_cells);
169 
170       int num_cells = occupied_cells.GetSize();
171       for (int i = 0; i < num_cells;) {
172         const Genome* cell_genome = &occupied_cells[i]->GetOrganism()->GetGenome();
173         if (cell_genome->GetHardwareType() != dest_genome.GetHardwareType() ||
174             cell_genome->GetInstSet() != dest_genome.GetInstSet()) {
175           // Organism type mis-match, remove from consideration;
176           num_cells--;
177           occupied_cells[i] = occupied_cells[num_cells];
178         } else {
179           i++;
180         }
181       }
182 
183       if (num_cells == 0) return false;
184 
185       int cell_idx = ctx.GetRandom().GetInt(num_cells);
186       src_seq = &occupied_cells[cell_idx]->GetOrganism()->GetGenome().GetSequence();
187     }
188       break;
189 
190       // Entire Population
191     case 1:
192     {
193       const tSmartArray<cOrganism*>& live_org_list = m_world->GetPopulation().GetLiveOrgList();
194       for (int i = 0; i < MAX_POP_SAMPLES; i++) {
195         int org_idx = ctx.GetRandom().GetInt(live_org_list.GetSize());
196         const Genome* org_genome = &live_org_list[org_idx]->GetGenome();
197         if (org_genome->GetHardwareType() != dest_genome.GetHardwareType() ||
198             org_genome->GetInstSet() != dest_genome.GetInstSet()) {
199           src_seq = &org_genome->GetSequence();
200           break;
201         }
202       }
203 
204       if (!src_seq) return false;
205     }
206       break;
207 
208     default:
209       return false;
210   }
211 
212   assert(src_seq);
213 
214   // Select random start and end point
215   int from = ctx.GetRandom().GetInt(src_seq->GetSize());
216   int to = ctx.GetRandom().GetInt(src_seq->GetSize());
217 
218   // Order from and to indices
219   if (from > to) {
220     int tmp = to;
221     to = from;
222     from = tmp;
223   }
224 
225   // Resize outgoing sequence and copy over the fragment
226   int new_size = to - from;
227   if (new_size == 0) {
228     // zero size treated as transfer of the whole genome
229     seq = (*src_seq);
230   } else {
231     seq.Resize(new_size);
232     for (int i = from; i < to; i++) {
233       seq[i - from] = (*src_seq)[i];
234     }
235   }
236 
237   return true;
238 }
239 
240 
Divide(cAvidaContext & ctx,cOrganism * parent,const Genome & offspring_genome)241 bool cPopulationInterface::Divide(cAvidaContext& ctx, cOrganism* parent, const Genome& offspring_genome)
242 {
243   assert(parent != NULL);
244   assert(m_world->GetPopulation().GetCell(m_cell_id).GetOrganism() == parent);
245   return m_world->GetPopulation().ActivateOffspring(ctx, offspring_genome, parent);
246 }
247 
GetNeighbor()248 cOrganism* cPopulationInterface::GetNeighbor()
249 {
250   cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
251   assert(cell.IsOccupied());
252 
253   return cell.ConnectionList().GetFirst()->GetOrganism();
254 }
255 
IsNeighborCellOccupied()256 bool cPopulationInterface::IsNeighborCellOccupied() {
257   cPopulationCell & cell = m_world->GetPopulation().GetCell(m_cell_id);
258   return cell.ConnectionList().GetFirst()->IsOccupied();
259 }
260 
GetNumNeighbors()261 int cPopulationInterface::GetNumNeighbors()
262 {
263   cPopulationCell & cell = m_world->GetPopulation().GetCell(m_cell_id);
264   assert(cell.IsOccupied());
265 
266   return cell.ConnectionList().GetSize();
267 }
268 
GetNeighborhoodCellIDs(tArray<int> & list)269 void cPopulationInterface::GetNeighborhoodCellIDs(tArray<int>& list)
270 {
271   cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
272   assert(cell.IsOccupied());
273 
274   list.Resize(cell.ConnectionList().GetSize());
275   tConstListIterator<cPopulationCell> it(cell.ConnectionList());
276   int i = 0;
277   while (it.Next() != NULL) list[i++] = it.Get()->GetID();
278 }
279 
GetFacing()280 int cPopulationInterface::GetFacing()
281 {
282 	cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
283 	assert(cell.IsOccupied());
284 	return cell.GetFacing();
285 }
286 
GetFacedCellID()287 int cPopulationInterface::GetFacedCellID()
288 {
289 	cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id).GetCellFaced();
290 	return cell.GetID();
291 }
292 
GetFacedDir()293 int cPopulationInterface::GetFacedDir()
294 {
295 	cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
296 	assert(cell.IsOccupied());
297 	return cell.GetFacedDir();
298 }
299 
GetNeighborCellContents()300 int cPopulationInterface::GetNeighborCellContents() {
301   cPopulationCell & cell = m_world->GetPopulation().GetCell(m_cell_id);
302   return cell.ConnectionList().GetFirst()->GetCellData();
303 }
304 
Rotate(int direction)305 void cPopulationInterface::Rotate(int direction)
306 {
307   cPopulationCell & cell = m_world->GetPopulation().GetCell(m_cell_id);
308   assert(cell.IsOccupied());
309 
310   if (m_world->GetConfig().USE_AVATARS.Get()) {
311     if (direction >= 0) RotateAV(1);
312     else RotateAV(-1);
313   }
314   else {
315     if (direction >= 0) cell.ConnectionList().CircNext();
316     else cell.ConnectionList().CircPrev();
317   }
318 }
319 
GetInputAt(int & input_pointer)320 int cPopulationInterface::GetInputAt(int& input_pointer)
321 {
322   cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
323   //assert(cell.IsOccupied());
324   return cell.GetInputAt(input_pointer);
325 }
326 
ResetInputs(cAvidaContext & ctx)327 void cPopulationInterface::ResetInputs(cAvidaContext& ctx)
328 {
329   m_world->GetPopulation().GetCell(m_cell_id).ResetInputs(ctx);
330 }
331 
GetInputs() const332 const tArray<int>& cPopulationInterface::GetInputs() const
333 {
334   return m_world->GetPopulation().GetCell(m_cell_id).GetInputs();
335 }
336 
GetResources(cAvidaContext & ctx)337 const tArray<double>& cPopulationInterface::GetResources(cAvidaContext& ctx)
338 {
339   return m_world->GetPopulation().GetCellResources(m_cell_id, ctx);
340 }
341 
GetFacedCellResources(cAvidaContext & ctx)342 const tArray<double>& cPopulationInterface::GetFacedCellResources(cAvidaContext& ctx)
343 {
344   return m_world->GetPopulation().GetCellResources(GetCell()->GetCellFaced().GetID(), ctx);
345 }
346 
GetCellResources(int cell_id,cAvidaContext & ctx)347 const tArray<double>& cPopulationInterface::GetCellResources(int cell_id, cAvidaContext& ctx)
348 {
349   return m_world->GetPopulation().GetCellResources(cell_id, ctx);
350 }
351 
GetFrozenResources(cAvidaContext & ctx,int cell_id)352 const tArray<double>& cPopulationInterface::GetFrozenResources(cAvidaContext& ctx, int cell_id)
353 {
354   return m_world->GetPopulation().GetFrozenResources(ctx, cell_id);
355 }
356 
GetResourceCount()357 cResourceCount* cPopulationInterface::GetResourceCount()
358 {
359   return &m_world->GetPopulation().GetResourceCount();
360 }
361 
GetDemeResources(int deme_id,cAvidaContext & ctx)362 const tArray<double>& cPopulationInterface::GetDemeResources(int deme_id, cAvidaContext& ctx)
363 {
364   return m_world->GetPopulation().GetDemeCellResources(deme_id, m_cell_id, ctx);
365 }
366 
GetCellIdLists()367 const tArray< tArray<int> >& cPopulationInterface::GetCellIdLists()
368 {
369 	return m_world->GetPopulation().GetCellIdLists();
370 }
371 
GetCurrPeakX(cAvidaContext & ctx,int res_id)372 int cPopulationInterface::GetCurrPeakX(cAvidaContext& ctx, int res_id)
373 {
374   return m_world->GetPopulation().GetCurrPeakX(ctx, res_id);
375 }
376 
GetCurrPeakY(cAvidaContext & ctx,int res_id)377 int cPopulationInterface::GetCurrPeakY(cAvidaContext& ctx, int res_id)
378 {
379   return m_world->GetPopulation().GetCurrPeakY(ctx, res_id);
380 }
381 
GetFrozenPeakX(cAvidaContext & ctx,int res_id)382 int cPopulationInterface::GetFrozenPeakX(cAvidaContext& ctx, int res_id)
383 {
384   return m_world->GetPopulation().GetFrozenPeakX(ctx, res_id);
385 }
386 
GetFrozenPeakY(cAvidaContext & ctx,int res_id)387 int cPopulationInterface::GetFrozenPeakY(cAvidaContext& ctx, int res_id)
388 {
389   return m_world->GetPopulation().GetFrozenPeakY(ctx, res_id);
390 }
391 
TriggerDoUpdates(cAvidaContext & ctx)392 void cPopulationInterface::TriggerDoUpdates(cAvidaContext& ctx)
393 {
394   m_world->GetPopulation().TriggerDoUpdates(ctx);
395 }
396 
UpdateResources(cAvidaContext & ctx,const tArray<double> & res_change)397 void cPopulationInterface::UpdateResources(cAvidaContext& ctx, const tArray<double>& res_change)
398 {
399   return m_world->GetPopulation().UpdateCellResources(ctx, res_change, m_cell_id);
400 }
401 
UpdateDemeResources(cAvidaContext & ctx,const tArray<double> & res_change)402 void cPopulationInterface::UpdateDemeResources(cAvidaContext& ctx, const tArray<double>& res_change)
403 {
404   return m_world->GetPopulation().UpdateDemeCellResources(ctx, res_change, m_cell_id);
405 }
406 
Die(cAvidaContext & ctx)407 void cPopulationInterface::Die(cAvidaContext& ctx)
408 {
409   cPopulationCell & cell = m_world->GetPopulation().GetCell(m_cell_id);
410   m_world->GetPopulation().KillOrganism(cell, ctx);
411 }
412 
KillCellID(int target,cAvidaContext & ctx)413 void cPopulationInterface::KillCellID(int target, cAvidaContext& ctx)
414 {
415   cPopulationCell & cell = m_world->GetPopulation().GetCell(target);
416   m_world->GetPopulation().KillOrganism(cell, ctx);
417 }
418 
Kaboom(int distance,cAvidaContext & ctx)419 void cPopulationInterface::Kaboom(int distance, cAvidaContext& ctx)
420 {
421   cPopulationCell & cell = m_world->GetPopulation().GetCell(m_cell_id);
422   m_world->GetPopulation().Kaboom(cell, ctx, distance);
423 }
424 
SpawnDeme(cAvidaContext & ctx)425 void cPopulationInterface::SpawnDeme(cAvidaContext& ctx)
426 {
427   // const int num_demes = m_world->GetPopulation().GetNumDemes();
428 
429   // Spawn the current deme; no target ID will put it into a random deme.
430   const int deme_id = m_world->GetPopulation().GetCell(m_cell_id).GetDemeID();
431 
432   m_world->GetPopulation().SpawnDeme(deme_id, ctx);
433 }
434 
NetReceive()435 cOrgSinkMessage* cPopulationInterface::NetReceive()
436 {
437   cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
438   assert(cell.IsOccupied());
439 
440   switch(m_world->GetConfig().NET_STYLE.Get())
441   {
442 		case 1: // Receiver Facing
443     {
444       cOrganism* cur_neighbor = cell.ConnectionList().GetFirst()->GetOrganism();
445       cOrgSinkMessage* msg = NULL;
446       if (cur_neighbor != NULL && (msg = cur_neighbor->NetPop()) != NULL) return msg;
447     }
448 			break;
449 
450 		case 0: // Random Next - First Available
451 		default:
452     {
453       const int num_neighbors = cell.ConnectionList().GetSize();
454       for (int i = 0; i < num_neighbors; i++) {
455         cell.ConnectionList().CircNext();
456 
457         cOrganism* cur_neighbor = cell.ConnectionList().GetFirst()->GetOrganism();
458         cOrgSinkMessage* msg = NULL;
459         if (cur_neighbor != NULL && (msg = cur_neighbor->NetPop()) != NULL ) return msg;
460       }
461     }
462 			break;
463   }
464 
465   return NULL;
466 }
467 
NetRemoteValidate(cAvidaContext & ctx,cOrgSinkMessage * msg)468 bool cPopulationInterface::NetRemoteValidate(cAvidaContext& ctx, cOrgSinkMessage* msg)
469 {
470   cOrganism* org = m_world->GetPopulation().GetCell(msg->GetSourceID()).GetOrganism();
471   return (org != NULL && org->NetRemoteValidate(ctx, msg->GetOriginalValue()));
472 }
473 
ReceiveValue()474 int cPopulationInterface::ReceiveValue()
475 {
476   cPopulationCell & cell = m_world->GetPopulation().GetCell(m_cell_id);
477   assert(cell.IsOccupied());
478 
479   const int num_neighbors = cell.ConnectionList().GetSize();
480   for (int i = 0; i < num_neighbors; i++) {
481     cell.ConnectionList().CircNext();
482 
483     cOrganism* cur_neighbor = cell.ConnectionList().GetFirst()->GetOrganism();
484     if (cur_neighbor == NULL || cur_neighbor->GetSentActive() == false) {
485       continue;
486     }
487 
488     return cur_neighbor->RetrieveSentValue();
489   }
490 
491   return 0;
492 }
493 
SellValue(const int data,const int label,const int sell_price,const int org_id)494 void cPopulationInterface::SellValue(const int data, const int label, const int sell_price, const int org_id)
495 {
496 	m_world->GetPopulation().AddSellValue(data, label, sell_price, org_id, m_cell_id);
497 }
498 
BuyValue(const int label,const int buy_price)499 int cPopulationInterface::BuyValue(const int label, const int buy_price)
500 {
501 	int value = m_world->GetPopulation().BuyValue(label, buy_price, m_cell_id);
502 	return value;
503 }
504 
InjectParasite(cOrganism * host,cBioUnit * parent,const cString & label,const Sequence & injected_code)505 bool cPopulationInterface::InjectParasite(cOrganism* host, cBioUnit* parent, const cString& label, const Sequence& injected_code)
506 {
507   assert(parent != NULL);
508   assert(m_world->GetPopulation().GetCell(m_cell_id).GetOrganism() == host);
509 
510   return m_world->GetPopulation().ActivateParasite(host, parent, label, injected_code);
511 }
512 
UpdateMerit(double new_merit)513 bool cPopulationInterface::UpdateMerit(double new_merit)
514 {
515   return m_world->GetPopulation().UpdateMerit(m_cell_id, new_merit);
516 }
517 
TestOnDivide()518 bool cPopulationInterface::TestOnDivide()
519 {
520   return m_world->GetTestOnDivide();
521 }
522 
523 
524 /*! Internal-use method to consolidate message-sending code.
525  */
SendMessage(cOrgMessage & msg,cPopulationCell & rcell)526 bool cPopulationInterface::SendMessage(cOrgMessage& msg, cPopulationCell& rcell) //**
527 {
528   bool dropped = false;
529   bool lost = false;
530 
531   static const double drop_prob = m_world->GetConfig().NET_DROP_PROB.Get();
532   if ((drop_prob > 0.0) && m_world->GetRandom().P(drop_prob)) {
533     // message dropped
534     GetDeme()->messageDropped();
535     GetDeme()->messageSendFailed();
536     dropped = true;
537   }
538 
539   if (!m_world->GetConfig().NEURAL_NETWORKING.Get() || m_world->GetConfig().USE_AVATARS.Get() != 2) {
540     // Not using neural networking avatars..
541     // Fail if the cell we're facing is not occupied.
542     if(!rcell.IsOccupied()) lost = true;
543   } else {
544     // If neural networking with avatars check for input avatars in this cell
545     if (!rcell.GetNumAVInputs()) lost = true;
546     // If self communication is not allowed, must check for an input avatar for another organism
547     else if (!m_world->GetConfig().SELF_COMMUNICATION.Get()) {
548       lost = true;
549       cOrganism* sender = GetOrganism();
550       for (int i = 0; i < rcell.GetNumAVInputs(); i++) {
551         if (sender != rcell.GetCellInputAVs()[i]) lost = false;
552       }
553     }
554   }
555 
556   if (lost) GetDeme()->messageSendFailed();
557 
558   // record this message, regardless of whether it's actually received.
559   if(m_world->GetConfig().NET_LOG_MESSAGES.Get()) m_world->GetStats().LogMessage(msg, dropped, lost);
560 
561   if(dropped || lost) return false;
562 
563   if (!m_world->GetConfig().NEURAL_NETWORKING.Get() || m_world->GetConfig().USE_AVATARS.Get() != 2) {
564     // Not using neural networking avatars..
565     cOrganism* recvr = rcell.GetOrganism();
566     assert(recvr != 0);
567     recvr->ReceiveMessage(msg);
568     m_world->GetStats().SentMessage(msg);
569     GetDeme()->MessageSuccessfullySent();
570   } else {
571     // If using neural networking avatars, message must be sent to all orgs with input avatars in the cell. @JJB
572     cOrganism* sender = GetOrganism();
573     for (int i = 0; i < rcell.GetNumAVInputs(); i++) {
574       cOrganism* recvr = rcell.GetCellInputAVs()[i];
575       assert(recvr != 0);
576       if ((sender != recvr) || m_world->GetConfig().SELF_COMMUNICATION.Get()) {
577         recvr->ReceiveMessage(msg);
578         m_world->GetStats().SentMessage(msg);
579         GetDeme()->MessageSuccessfullySent();
580       }
581     }
582   }
583   return true;
584 }
585 
SendMessage(cOrgMessage & msg,int cellid)586 bool cPopulationInterface::SendMessage(cOrgMessage& msg, int cellid) {
587   cPopulationCell& cell = m_world->GetPopulation().GetCell(cellid);
588   if (m_world->GetConfig().NEURAL_NETWORKING.Get() && m_world->GetConfig().USE_AVATARS.Get() == 2) {
589     msg.SetTransCellID(cellid);
590   }
591   return SendMessage(msg, cell);
592 }
593 
594 /*! Send a message to the faced organism, failing if this cell does not have
595  neighbors or if the cell currently faced is not occupied.
596  */
SendMessage(cOrgMessage & msg)597 bool cPopulationInterface::SendMessage(cOrgMessage& msg) {
598   cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
599   assert(cell.IsOccupied()); // This organism; sanity.
600 
601   if (m_world->GetConfig().USE_AVATARS.Get() == 2 && m_world->GetConfig().NEURAL_NETWORKING.Get()) {
602     //assert(m_avatars);
603     bool message_sent = false;
604     for (int i = 0; i < getNumAV(); i++) {
605       if (m_avatars[i].av_output) {
606         message_sent = (message_sent || SendMessage(msg, m_avatars[i].av_cell_id));
607       }
608     }
609     return message_sent;
610   } else {
611     cPopulationCell* rcell = cell.ConnectionList().GetFirst();
612     assert(rcell != 0); // Cells should never be null.
613     return SendMessage(msg, *rcell);
614   }
615 }
616 
617 
618 /*! Send a message to the faced organism, failing if this cell does not have
619  neighbors or if the cell currently faced is not occupied. */
BroadcastMessage(cOrgMessage & msg,int depth)620 bool cPopulationInterface::BroadcastMessage(cOrgMessage& msg, int depth) {
621   cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
622   assert(cell.IsOccupied()); // This organism; sanity.
623 
624 	// Get the set of cells that are within range.
625 	std::set<cPopulationCell*> cell_set;
626 	cell.GetNeighboringCells(cell_set, depth);
627 
628 	// Remove this cell from the set!
629 	cell_set.erase(&cell);
630 
631 	// Now, send a message towards each cell:
632 	for(std::set<cPopulationCell*>::iterator i=cell_set.begin(); i!=cell_set.end(); ++i) {
633 		SendMessage(msg, **i);
634 	}
635 	return true;
636 }
637 
638 
BcastAlarm(int jump_label,int bcast_range)639 bool cPopulationInterface::BcastAlarm(int jump_label, int bcast_range) {
640   bool successfully_sent(false);
641   cPopulationCell& scell = m_world->GetPopulation().GetCell(m_cell_id);
642   assert(scell.IsOccupied()); // This organism; sanity.
643 
644   const int ALARM_SELF = m_world->GetConfig().ALARM_SELF.Get(); // does an alarm affect the sender; 0=no  non-0=yes
645 
646   if(bcast_range > 1) { // multi-hop messaging
647     cDeme& deme = m_world->GetPopulation().GetDeme(GetDemeID());
648     for(int i = 0; i < deme.GetSize(); i++) {
649       int possible_receiver_id = deme.GetCellID(i);
650       cPopulationCell& rcell = m_world->GetPopulation().GetCell(possible_receiver_id);
651 
652       if(rcell.IsOccupied() && possible_receiver_id != GetCellID()) {
653         //check distance
654         pair<int, int> sender_pos = deme.GetCellPosition(GetCellID());
655         pair<int, int> possible_receiver_pos = deme.GetCellPosition(possible_receiver_id);
656         int hop_distance = max( abs(sender_pos.first  - possible_receiver_pos.first),
657 															 abs(sender_pos.second - possible_receiver_pos.second));
658         if(hop_distance <= bcast_range) {
659           // send alarm to organisms
660           cOrganism* recvr = rcell.GetOrganism();
661           assert(recvr != NULL);
662           recvr->moveIPtoAlarmLabel(jump_label);
663           successfully_sent = true;
664         }
665       }
666     }
667   } else { // single hop messaging
668     for(int i = 0; i < scell.ConnectionList().GetSize(); i++) {
669       cPopulationCell* rcell = scell.ConnectionList().GetPos(i);
670       assert(rcell != NULL); // Cells should never be null.
671 
672       // Fail if the cell we're facing is not occupied.
673       if(!rcell->IsOccupied())
674         continue;
675       cOrganism* recvr = rcell->GetOrganism();
676       assert(recvr != NULL);
677       recvr->moveIPtoAlarmLabel(jump_label);
678       successfully_sent = true;
679     }
680   }
681 
682   if(ALARM_SELF) {
683     scell.GetOrganism()->moveIPtoAlarmLabel(jump_label);
684   }
685   return successfully_sent;
686 }
687 
DivideOrgTestamentAmongDeme(double value)688 void cPopulationInterface::DivideOrgTestamentAmongDeme(double value){
689   cDeme* deme = GetDeme();
690   for(int i = 0; i < deme->GetSize(); i++) {
691     cPopulationCell& cell = deme->GetCell(i);
692     if(cell.IsOccupied()) {
693       cOrganism* org = cell.GetOrganism();
694       org->GetPhenotype().EnergyTestament(value/deme->GetOrgCount());
695     }
696   }
697 }
698 
699 /*! Send a flash to all neighboring organisms. */
SendFlash()700 void cPopulationInterface::SendFlash() {
701   cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
702   assert(cell.IsOccupied());
703 
704   for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
705     cPopulationCell* neighbor = cell.ConnectionList().GetFirst();
706     if(neighbor->IsOccupied()) {
707       neighbor->GetOrganism()->ReceiveFlash();
708     }
709     cell.ConnectionList().CircNext();
710   }
711 }
712 
GetStateGridID(cAvidaContext & ctx)713 int cPopulationInterface::GetStateGridID(cAvidaContext& ctx)
714 {
715   return ctx.GetRandom().GetUInt(m_world->GetEnvironment().GetNumStateGrids());
716 }
717 
718 /* Rotate an organism to face the neighbor with the highest reputation */
RotateToGreatestReputation()719 void cPopulationInterface::RotateToGreatestReputation()
720 {
721 
722 	cPopulationCell& cell = m_world->GetPopulation().GetCell(GetCellID());
723 	int high_rep=-1;
724 	vector <int> high_rep_orgs;
725 
726 
727 	// loop to find the max reputation
728 	for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
729 		const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
730 		// cell->organism, if occupied, check reputation, etc.
731 		if (IsNeighborCellOccupied()) {
732 			cOrganism* cur_neighbor = faced_cell->GetOrganism();
733 
734 			// if it has high reputation
735 			if (cur_neighbor->GetReputation() >= high_rep) {
736 				if (cur_neighbor->GetReputation() > high_rep) {
737 					high_rep = cur_neighbor->GetReputation();
738 					high_rep_orgs.clear();
739 				}
740 				high_rep_orgs.push_back(cur_neighbor->GetID());
741 			}
742 		}
743 
744 		// check the next neighbor
745 		cell.ConnectionList().CircNext();
746 	}
747 
748 	// Pick an organism to donate to
749 
750 	if (high_rep_orgs.size() > 0) {
751 		unsigned int rand_num = m_world->GetRandom().GetUInt(0, high_rep_orgs.size());
752 		int high_org_id = high_rep_orgs[rand_num];
753 
754 		for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
755 			const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
756 
757 			if (IsNeighborCellOccupied()) {
758 
759 				cOrganism* cur_neighbor = faced_cell->GetOrganism();
760 
761 				// if it has high reputation
762 				if (cur_neighbor->GetID() == high_org_id) {
763 					break;
764 				}
765 			}
766 
767 			cell.ConnectionList().CircNext();
768 
769 		}
770 	}
771 
772 }
773 
774 /* Rotate an organism to face the neighbor with the highest reputation
775  where the neighbor has a different tag than the organism*/
RotateToGreatestReputationWithDifferentTag(int tag)776 void cPopulationInterface::RotateToGreatestReputationWithDifferentTag(int tag)
777 {
778 
779 	cPopulationCell& cell = m_world->GetPopulation().GetCell(GetCellID());
780 	int high_rep=-1;
781 	vector <int> high_rep_orgs;
782 
783 	// loop to find the max reputation
784 	for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
785 		const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
786 		// cell->organism, if occupied, check reputation, etc.
787 		if (IsNeighborCellOccupied()) {
788 			cOrganism* cur_neighbor = faced_cell->GetOrganism();
789 
790 			// if it has high reputation
791 			if ((cur_neighbor->GetTagLabel() != tag) && (cur_neighbor->GetReputation() >= high_rep)) {
792 				if (cur_neighbor->GetReputation() > high_rep) {
793 					high_rep = cur_neighbor->GetReputation();
794 					high_rep_orgs.clear();
795 				}
796 				high_rep_orgs.push_back(cur_neighbor->GetID());
797 			}
798 		}
799 
800 		// check the next neighbor
801 		cell.ConnectionList().CircNext();
802 	}
803 
804 	// Pick an organism to donate to
805 
806 	if (high_rep_orgs.size() > 0) {
807 		unsigned int rand_num = m_world->GetRandom().GetUInt(0, high_rep_orgs.size());
808 		int high_org_id = high_rep_orgs[rand_num];
809 
810 		for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
811 			const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
812 
813 			if (IsNeighborCellOccupied()) {
814 
815 				cOrganism* cur_neighbor = faced_cell->GetOrganism();
816 
817 				// if it has high reputation
818 				if (cur_neighbor->GetID() == high_org_id) {
819 					break;
820 				}
821 			}
822 
823 			cell.ConnectionList().CircNext();
824 
825 		}
826 
827 
828 
829 	}
830 
831 }
832 
833 /* Rotate an organism to face the neighbor with the highest reputation
834  where the neighbor has a different tag than the organism*/
RotateToGreatestReputationWithDifferentLineage(int line)835 void cPopulationInterface::RotateToGreatestReputationWithDifferentLineage(int line)
836 {
837 
838 	cPopulationCell& cell = m_world->GetPopulation().GetCell(GetCellID());
839 	int high_rep=-1;
840 	vector <int> high_rep_orgs;
841 
842 	// loop to find the max reputation
843 	for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
844 		const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
845 		// cell->organism, if occupied, check reputation, etc.
846 		if (IsNeighborCellOccupied()) {
847 			cOrganism* cur_neighbor = faced_cell->GetOrganism();
848 
849 			// if it has high reputation
850 			if ((cur_neighbor->GetLineageLabel() != line) && (cur_neighbor->GetReputation() >= high_rep)) {
851 				if (cur_neighbor->GetReputation() > high_rep) {
852 					high_rep = cur_neighbor->GetReputation();
853 					high_rep_orgs.clear();
854 				}
855 				high_rep_orgs.push_back(cur_neighbor->GetID());
856 			}
857 		}
858 
859 		// check the next neighbor
860 		cell.ConnectionList().CircNext();
861 	}
862 
863 	// Pick an organism to donate to
864 
865 	if (high_rep_orgs.size() > 0) {
866 		unsigned int rand_num = m_world->GetRandom().GetUInt(0, high_rep_orgs.size());
867 		int high_org_id = high_rep_orgs[rand_num];
868 
869 		for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
870 			const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
871 
872 			if (IsNeighborCellOccupied()) {
873 
874 				cOrganism* cur_neighbor = faced_cell->GetOrganism();
875 
876 				// if it has high reputation
877 				if (cur_neighbor->GetID() == high_org_id) {
878 					break;
879 				}
880 			}
881 
882 			cell.ConnectionList().CircNext();
883 
884 		}
885 	}
886 }
887 
888 /*! Link this organism's cell to the cell it is currently facing.
889  */
CreateLinkByFacing(double weight)890 void cPopulationInterface::CreateLinkByFacing(double weight) {
891 	cDeme* deme = GetDeme(); assert(deme);
892 	cPopulationCell* this_cell = GetCell(); assert(this_cell);
893 	cPopulationCell* that_cell = GetCellFaced(); assert(that_cell);
894 	deme->GetNetwork().Connect(*this_cell, *that_cell, weight);
895 }
896 
897 /*! Link this organism's cell to the cell with coordinates (x,y).
898  */
CreateLinkByXY(int x,int y,double weight)899 void cPopulationInterface::CreateLinkByXY(int x, int y, double weight) {
900 	cDeme* deme = GetDeme(); assert(deme);
901 	cPopulationCell* this_cell = GetCell(); assert(this_cell);
902 	// the static casts here are to fix a problem with -2^31 being sent in as a
903 	// cell coordinate.  the problem is that a 2s-complement int can hold a negative
904 	// number whose absolute value is too large for the int to hold.  when this happens,
905 	// abs returns the value unmodified.
906 	int cellx = llabs(static_cast<long long int>(x)) % deme->GetWidth();
907 	int celly = llabs(static_cast<long long int>(y)) % deme->GetHeight();
908 	assert(cellx >= 0);
909 	assert(cellx < deme->GetWidth());
910 	assert(celly >= 0);
911 	assert(celly < deme->GetHeight());
912 	deme->GetNetwork().Connect(*this_cell, deme->GetCell(cellx, celly), weight);
913 }
914 
915 /*! Link this organism's cell to the cell with index idx.
916  */
CreateLinkByIndex(int idx,double weight)917 void cPopulationInterface::CreateLinkByIndex(int idx, double weight) {
918 	cDeme* deme = GetDeme(); assert(deme);
919 	cPopulationCell* this_cell = GetCell(); assert(this_cell);
920 	// the static casts here are to fix a problem with -2^31 being sent in as a
921 	// cell coordinate.  the problem is that a 2s-complement int can hold a negative
922 	// number whose absolute value is too large for the int to hold.  when this happens,
923 	// abs returns the value unmodified.
924 	int that_cell = llabs(static_cast<long long int>(idx)) % deme->GetSize();
925 	assert(that_cell >= 0);
926 	assert(that_cell < deme->GetSize());
927 	deme->GetNetwork().Connect(*this_cell, deme->GetCell(that_cell), weight);
928 }
929 
930 /*! Broadcast a message to all organisms that are connected by this network.
931  */
NetworkBroadcast(cOrgMessage & msg)932 bool cPopulationInterface::NetworkBroadcast(cOrgMessage& msg) {
933 	cDeme* deme = GetDeme(); assert(deme);
934 	cPopulationCell* this_cell = GetCell(); assert(this_cell);
935 	deme->GetNetwork().BroadcastToNeighbors(*this_cell, msg, this);
936 	return true;
937 }
938 
939 /*! Unicast a message to the current selected organism.
940  */
NetworkUnicast(cOrgMessage & msg)941 bool cPopulationInterface::NetworkUnicast(cOrgMessage& msg) {
942 	cDeme* deme = GetDeme(); assert(deme);
943 	cPopulationCell* this_cell = GetCell(); assert(this_cell);
944 	deme->GetNetwork().Unicast(*this_cell, msg, this);
945 	return true;
946 }
947 
948 /*! Rotate to select a new network link.
949  */
NetworkRotate(int x)950 bool cPopulationInterface::NetworkRotate(int x) {
951 	cDeme* deme = GetDeme(); assert(deme);
952 	cPopulationCell* this_cell = GetCell(); assert(this_cell);
953 	deme->GetNetwork().Rotate(*this_cell, x);
954 	return true;
955 }
956 
957 /*! Select a new network link.
958  */
NetworkSelect(int x)959 bool cPopulationInterface::NetworkSelect(int x) {
960 	cDeme* deme = GetDeme(); assert(deme);
961 	cPopulationCell* this_cell = GetCell(); assert(this_cell);
962 	deme->GetNetwork().Select(*this_cell, x);
963 	return true;
964 }
965 
966 // If the cell is turned on for deme input, retrieves the deme's next input value. @JJB
GetNextDemeInput(cAvidaContext & ctx)967 int cPopulationInterface::GetNextDemeInput(cAvidaContext& ctx)
968 {
969   if (m_world->GetPopulation().GetCell(m_cell_id).GetCanInput()) {
970     return GetDeme()->GetNextDemeInput(ctx);
971   }
972   return -1;
973 }
974 
975 // If the cell is turned on for deme input, adds the value to the deme's input buffer. @JJB
DoDemeInput(int value)976 void cPopulationInterface::DoDemeInput(int value)
977 {
978   if (m_world->GetPopulation().GetCell(m_cell_id).GetCanInput()) {
979     GetDeme()->DoDemeInput(value);
980   }
981 }
982 
983 // If the cell is turned on for deme output, adds the value to the deme's output buffer. @JJB
DoDemeOutput(cAvidaContext & ctx,int value)984 void cPopulationInterface::DoDemeOutput(cAvidaContext& ctx, int value)
985 {
986   if (m_world->GetPopulation().GetCell(m_cell_id).GetCanOutput()) {
987     GetDeme()->DoDemeOutput(ctx, value);
988   }
989 }
990 
991 
992 /*! Called when this individual is the donor organism during conjugation.
993 
994  This method causes this individual to "donate" a fragment of its own genome to
995  another organism selected from the population.
996  */
DoHGTDonation(cAvidaContext & ctx)997 void cPopulationInterface::DoHGTDonation(cAvidaContext& ctx) {
998 	cPopulationCell* target=0;
999 
1000 	switch(m_world->GetConfig().HGT_CONJUGATION_METHOD.Get()) {
1001 		case 0: { // selected at random from neighborhood
1002 			std::set<cPopulationCell*> occupied_cell_set;
1003 			GetCell()->GetOccupiedNeighboringCells(occupied_cell_set, 1);
1004 			if(occupied_cell_set.size()==0) {
1005 				// nothing to do here, there are no neighbors
1006 				return;
1007 			}
1008 			std::set<cPopulationCell*>::iterator selected=occupied_cell_set.begin();
1009 			std::advance(selected, ctx.GetRandom().GetInt(occupied_cell_set.size()));
1010 			target = *selected;
1011 			break;
1012 		}
1013 		case 1: { // faced individual
1014 			target = GetCellFaced();
1015 			if(!target->IsOccupied()) {
1016 				// nothing to do, we're facing an empty cell.
1017 				return;
1018 			}
1019 			break;
1020 		}
1021 		default: {
1022 			m_world->GetDriver().RaiseFatalException(1, "HGT_CONJUGATION_METHOD is set to an invalid value.");
1023 			break;
1024 		}
1025 	}
1026 	assert(target != 0);
1027 	fragment_list_type fragments;
1028 	cGenomeUtil::RandomSplit(ctx,
1029 													 m_world->GetConfig().HGT_FRAGMENT_SIZE_MEAN.Get(),
1030 													 m_world->GetConfig().HGT_FRAGMENT_SIZE_VARIANCE.Get(),
1031 													 GetOrganism()->GetGenome().GetSequence(),
1032 													 fragments);
1033 	target->GetOrganism()->GetOrgInterface().ReceiveHGTDonation(fragments[ctx.GetRandom().GetInt(fragments.size())]);
1034 }
1035 
1036 
1037 /*! Called when this organism "requests" an HGT conjugation.
1038 
1039  Technically, organisms don't request an HGT conjugation.  However, this provides
1040  an alternative to population-level conjugational events.  Specifically, whenever
1041  an organism replicates, there is the possibility that its offspring conjugates
1042  with another organism in the population -- that is what we check here.
1043 
1044  This method is closely related to HGT donation, except here we're looking for
1045  the donatOR, instead of the donatEE.
1046  */
DoHGTConjugation(cAvidaContext & ctx)1047 void cPopulationInterface::DoHGTConjugation(cAvidaContext& ctx) {
1048 	cPopulationCell* source=0;
1049 
1050 	switch(m_world->GetConfig().HGT_CONJUGATION_METHOD.Get()) {
1051 		case 0: { // selected at random from neighborhood
1052 			std::set<cPopulationCell*> occupied_cell_set;
1053 			GetCell()->GetOccupiedNeighboringCells(occupied_cell_set, 1);
1054 			if(occupied_cell_set.size()==0) {
1055 				// nothing to do here, there are no neighbors
1056 				return;
1057 			}
1058 			std::set<cPopulationCell*>::iterator selected=occupied_cell_set.begin();
1059 			std::advance(selected, ctx.GetRandom().GetInt(occupied_cell_set.size()));
1060 			source = *selected;
1061 			break;
1062 		}
1063 		case 1: { // faced individual
1064 			source = GetCellFaced();
1065 			if(!source->IsOccupied()) {
1066 				// nothing to do, we're facing an empty cell.
1067 				return;
1068 			}
1069 			break;
1070 		}
1071 		default: {
1072 			m_world->GetDriver().RaiseFatalException(1, "HGT_CONJUGATION_METHOD is set to an invalid value.");
1073 			break;
1074 		}
1075 	}
1076 	assert(source != 0);
1077 	fragment_list_type fragments;
1078 	cGenomeUtil::RandomSplit(ctx,
1079 													 m_world->GetConfig().HGT_FRAGMENT_SIZE_MEAN.Get(),
1080 													 m_world->GetConfig().HGT_FRAGMENT_SIZE_VARIANCE.Get(),
1081 													 source->GetOrganism()->GetGenome().GetSequence(),
1082 													 fragments);
1083 	ReceiveHGTDonation(fragments[ctx.GetRandom().GetInt(fragments.size())]);
1084 }
1085 
1086 
1087 /*! Perform an HGT mutation on this offspring.
1088 
1089  HGT mutations are location-dependent, hence they are piped through the population
1090  interface as opposed to being implemented in the CPU or organism.
1091 
1092  There is the possibility that more than one HGT mutation occurs when this method
1093  is called.
1094  */
DoHGTMutation(cAvidaContext & ctx,Genome & offspring)1095 void cPopulationInterface::DoHGTMutation(cAvidaContext& ctx, Genome& offspring) {
1096 	InitHGTSupport();
1097 
1098 	// first, gather up all the fragments that we're going to be inserting into this offspring:
1099 	// these come from a per-replication conjugational event:
1100 	if((m_world->GetConfig().HGT_CONJUGATION_P.Get() > 0.0)
1101 		 && (ctx.GetRandom().P(m_world->GetConfig().HGT_CONJUGATION_P.Get()))) {
1102 		DoHGTConjugation(ctx);
1103 	}
1104 
1105 	// the pending list includes both the fragments selected via the above process,
1106 	// as well as from population-level conjugational events (see cPopulationActions.cc:cActionAvidianConjugation).
1107 	fragment_list_type& fragments = m_hgt_support->_pending;
1108 
1109 	// these come from "natural" competence (ie, eating the dead):
1110 	if((m_world->GetConfig().HGT_COMPETENCE_P.Get() > 0.0)
1111 		 && (ctx.GetRandom().P(m_world->GetConfig().HGT_COMPETENCE_P.Get()))) {
1112 
1113 		// get this organism's cell:
1114 		cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
1115 
1116 		// the hgt source controls where the genetic material for HGT comes from.
1117 		switch(m_world->GetConfig().HGT_SOURCE.Get()) {
1118 			case 0: { // source is other genomes, nothing to do here (default)
1119 				break;
1120 			}
1121 			case 1: { // source is the parent (a control)
1122 				// this is a little hackish, but this is the cleanest way to make sure
1123 				// that all downstream stuff works right.
1124 				cell.ClearFragments(ctx);
1125 				cell.AddGenomeFragments(ctx, cell.GetOrganism()->GetGenome().GetSequence());
1126 				break;
1127 			}
1128 			default: { // error
1129 				m_world->GetDriver().RaiseFatalException(1, "HGT_SOURCE is set to an invalid value.");
1130 				break;
1131 			}
1132 		}
1133 
1134 		// do we have any fragments available?
1135 		if(cell.CountGenomeFragments() > 0) {
1136 			// add a randomly-selected fragment to the list of fragments to be HGT'd,
1137 			// remove it from the cell, and adjust the level of HGT resource.
1138 			fragment_list_type::iterator selected=cell.GetFragments().begin();
1139 			std::advance(selected, ctx.GetRandom().GetInt(cell.GetFragments().size()));
1140 			fragments.insert(fragments.end(), *selected);
1141 			m_world->GetPopulation().AdjustHGTResource(ctx, -selected->GetSize());
1142 			cell.GetFragments().erase(selected);
1143 		}
1144 	}
1145 
1146 	// now, for each fragment being HGT'd, figure out where to put it:
1147 	for(fragment_list_type::iterator i=fragments.begin(); i!=fragments.end(); ++i) {
1148 		cGenomeUtil::substring_match location;
1149 		switch(m_world->GetConfig().HGT_FRAGMENT_SELECTION.Get()) {
1150 			case 0: { // match placement
1151 				HGTMatchPlacement(ctx, offspring.GetSequence(), i, location);
1152 				break;
1153 			}
1154 			case 1: { // match placement with redundant instruction trimming
1155 				HGTTrimmedPlacement(ctx, offspring.GetSequence(), i, location);
1156 				break;
1157 			}
1158 			case 2: { // random placement
1159 				HGTRandomPlacement(ctx, offspring.GetSequence(), i, location);
1160 				break;
1161 			}
1162 			default: { // error
1163 				m_world->GetDriver().RaiseFatalException(1, "HGT_FRAGMENT_SELECTION is set to an invalid value.");
1164 				break;
1165 			}
1166 		}
1167 
1168 		// at this stage, we have a fragment and a location we're going to put it.
1169 		// there are various transformations to this fragment that we could perform,
1170 		// more as controls than anything else.
1171 		switch(m_world->GetConfig().HGT_FRAGMENT_XFORM.Get()) {
1172 			case 0: { // no transformation.
1173 				break;
1174 			}
1175 			case 1: { // random shuffle of the instructions in the fragment.
1176 				cGenomeUtil::RandomShuffle(ctx, *i);
1177 				break;
1178 			}
1179 			case 2: { // replace the instructions in the fragment with random instructions.
1180 				const cInstSet& instset = m_world->GetHardwareManager().GetInstSet(offspring.GetInstSet());
1181 				for(int j=0; j<i->GetSize(); ++j) {
1182 					(*i)[j] = instset.GetRandomInst(ctx);
1183 				}
1184 				break;
1185 			}
1186 			default: { // error
1187 				m_world->GetDriver().RaiseFatalException(1, "HGT_FRAGMENT_XFORM is set to an invalid value.");
1188 				break;
1189 			}
1190 		}
1191 
1192 		// do the mutation; we currently support insertions and replacements, but this can
1193 		// be extended in the same way as fragment selection if need be.
1194 		if(ctx.GetRandom().P(m_world->GetConfig().HGT_INSERTION_MUT_P.Get())) {
1195 			// insert the fragment just after the final location:
1196 			offspring.GetSequence().Insert(location.end, *i);
1197 		} else {
1198 			// replacement: replace [begin,end) instructions in the genome with the fragment,
1199 			// respecting circularity.
1200 			offspring.GetSequence().Replace(*i, location.begin, location.end);
1201 		}
1202 
1203 		// stats tracking:
1204 		m_world->GetStats().GenomeFragmentInserted(GetOrganism(), *i, location);
1205 	}
1206 
1207 	// clean-up; be sure to empty the pending list so that we don't end up doing an HGT
1208 	// operation multiple times on the same fragment.
1209 	fragments.clear();
1210 }
1211 
1212 
1213 /*! Place the fragment at the location of best match.
1214  */
HGTMatchPlacement(cAvidaContext & ctx,const Sequence & offspring,fragment_list_type::iterator & selected,substring_match & location)1215 void cPopulationInterface::HGTMatchPlacement(cAvidaContext& ctx, const Sequence& offspring,
1216 																						 fragment_list_type::iterator& selected,
1217 																						 substring_match& location) {
1218 	// find the location within the offspring's genome that best matches the selected fragment:
1219 	location = cGenomeUtil::FindUnbiasedCircularMatch(ctx, offspring, *selected);
1220 }
1221 
1222 
1223 /*! Place the fragment at the location of best match, with redundant instructions trimmed.
1224 
1225  In this fragment selection method, the
1226  match location within the genome is calculated on a "trimmed" fragment.  Specifically,
1227  the trimmed fragment has all duplicate instructions at its end removed prior to the match.
1228 
1229  Mutations to the offspring are still performed using the entire fragment, so this effectively
1230  increases the insertion rate.  E.g., hgt(abcde, abcccc) -> abccccde.
1231  */
HGTTrimmedPlacement(cAvidaContext & ctx,const Sequence & offspring,fragment_list_type::iterator & selected,substring_match & location)1232 void cPopulationInterface::HGTTrimmedPlacement(cAvidaContext& ctx, const Sequence& offspring,
1233 																											 fragment_list_type::iterator& selected,
1234 																											 substring_match& location) {
1235 	// copy the selected fragment, trimming redundant instructions at the end:
1236 	Sequence trimmed(*selected);
1237 	while((trimmed.GetSize() >= 2) && (trimmed[trimmed.GetSize()-1] == trimmed[trimmed.GetSize()-2])) {
1238 		trimmed.Remove(trimmed.GetSize()-1);
1239 	}
1240 
1241 	// find the location within the offspring's genome that best matches the selected fragment:
1242 	location = cGenomeUtil::FindUnbiasedCircularMatch(ctx, offspring, trimmed);
1243 }
1244 
1245 
1246 /*! Place the fragment at a random location.
1247 
1248  Here we select a random location for the fragment within the offspring.
1249  The beginning of the fragment location is selected at random, while the end is selected a
1250  random distance (up to the length of the selected fragment * 2) instructions away.
1251  */
HGTRandomPlacement(cAvidaContext & ctx,const Sequence & offspring,fragment_list_type::iterator & selected,substring_match & location)1252 void cPopulationInterface::HGTRandomPlacement(cAvidaContext& ctx, const Sequence& offspring,
1253 																											fragment_list_type::iterator& selected,
1254 																											substring_match& location) {
1255 	// select a random location within the offspring's genome for this fragment to be
1256 	// inserted:
1257 	location.begin = ctx.GetRandom().GetUInt(offspring.GetSize());
1258 	location.end = location.begin + ctx.GetRandom().GetUInt(selected->GetSize()*2);
1259 	location.size = offspring.GetSize();
1260 	location.resize(offspring.GetSize());
1261 }
1262 
1263 /*! Called when this organism is the receiver of an HGT donation.
1264  */
ReceiveHGTDonation(const Sequence & fragment)1265 void cPopulationInterface::ReceiveHGTDonation(const Sequence& fragment) {
1266 	InitHGTSupport();
1267 	m_hgt_support->_pending.push_back(fragment);
1268 }
1269 
1270 
Move(cAvidaContext & ctx,int src_id,int dest_id)1271 bool cPopulationInterface::Move(cAvidaContext& ctx, int src_id, int dest_id)
1272 {
1273   return m_world->GetPopulation().MoveOrganisms(ctx, src_id, dest_id, -1);
1274 }
1275 
AddLiveOrg()1276 void cPopulationInterface::AddLiveOrg()
1277 {
1278   m_world->GetPopulation().AddLiveOrg(GetOrganism());
1279 }
1280 
RemoveLiveOrg()1281 void cPopulationInterface::RemoveLiveOrg()
1282 {
1283   m_world->GetPopulation().RemoveLiveOrg(GetOrganism());
1284 }
1285 
HasOpinion(cOrganism * in_organism)1286 bool cPopulationInterface::HasOpinion(cOrganism* in_organism)
1287 {
1288   return in_organism->HasOpinion();
1289 }
1290 
SetOpinion(int opinion,cOrganism * in_organism)1291 void cPopulationInterface::SetOpinion(int opinion, cOrganism* in_organism)
1292 {
1293   in_organism->SetOpinion(opinion);
1294 }
1295 
ClearOpinion(cOrganism * in_organism)1296 void cPopulationInterface::ClearOpinion(cOrganism* in_organism)
1297 {
1298   in_organism->ClearOpinion();
1299 }
1300 
JoinGroup(int group_id)1301 void cPopulationInterface::JoinGroup(int group_id)
1302 {
1303   m_world->GetPopulation().JoinGroup(GetOrganism(), group_id);
1304 }
1305 
MakeGroup()1306 void cPopulationInterface::MakeGroup()
1307 {
1308   m_world->GetPopulation().MakeGroup(GetOrganism());
1309 }
1310 
LeaveGroup(int group_id)1311 void cPopulationInterface::LeaveGroup(int group_id)
1312 {
1313   m_world->GetPopulation().LeaveGroup(GetOrganism(), group_id);
1314 }
1315 
NumberOfOrganismsInGroup(int group_id)1316 int cPopulationInterface::NumberOfOrganismsInGroup(int group_id)
1317 {
1318   return m_world->GetPopulation().NumberOfOrganismsInGroup(group_id);
1319 }
1320 
NumberGroupFemales(int group_id)1321 int cPopulationInterface::NumberGroupFemales(int group_id)
1322 {
1323   return m_world->GetPopulation().NumberGroupFemales(group_id);
1324 }
1325 
NumberGroupMales(int group_id)1326 int cPopulationInterface::NumberGroupMales(int group_id)
1327 {
1328   return m_world->GetPopulation().NumberGroupMales(group_id);
1329 }
1330 
NumberGroupJuvs(int group_id)1331 int cPopulationInterface::NumberGroupJuvs(int group_id)
1332 {
1333   return m_world->GetPopulation().NumberGroupJuvs(group_id);
1334 }
1335 
ChangeGroupMatingTypes(cOrganism * org,int group_id,int old_type,int new_type)1336 void cPopulationInterface::ChangeGroupMatingTypes(cOrganism* org, int group_id, int old_type, int new_type)
1337 {
1338   m_world->GetPopulation().ChangeGroupMatingTypes(org, group_id, old_type, new_type);
1339 }
1340 
1341 /* Increases tolerance towards the addition of members to the group.
1342  * toleranceType:
1343  *    0: increases tolerance towards immigrants
1344  *    1: increases tolerance towards own offspring
1345  *    2: increases tolerance towards other offspring of the group
1346  * Removes the most recent record of dec-tolerance
1347  * Returns the modified tolerance total.
1348  */
IncTolerance(const int tolerance_type,cAvidaContext & ctx)1349 int cPopulationInterface::IncTolerance(const int tolerance_type, cAvidaContext &ctx)
1350 {
1351   int group_id = GetOrganism()->GetOpinion().first;
1352 
1353   if (tolerance_type == 0) {
1354     // Modify tolerance towards immigrants
1355     PushToleranceInstExe(0, ctx);
1356 
1357     // Update tolerance list by removing the most recent dec_tolerance record
1358     delete GetOrganism()->GetPhenotype().GetToleranceImmigrants().Pop();
1359 
1360     // If not at individual's max tolerance, adjust both caches
1361     if (GetOrganism()->GetPhenotype().GetIntolerances()[0].second != 0) {
1362       GetOrganism()->GetPhenotype().GetIntolerances()[0].second--;
1363       GetGroupIntolerances(group_id, 0, -1)--;
1364       if (m_world->GetConfig().TOLERANCE_VARIATIONS.Get() == 2) {
1365         if (GetOrganism()->GetPhenotype().GetMatingType() == MATING_TYPE_FEMALE) GetGroupIntolerances(group_id, 0, 0)--;
1366         else if (GetOrganism()->GetPhenotype().GetMatingType() == MATING_TYPE_MALE) GetGroupIntolerances(group_id, 0, 1)--;
1367         else if (GetOrganism()->GetPhenotype().GetMatingType() == MATING_TYPE_JUVENILE) GetGroupIntolerances(group_id, 0, 2)--;
1368       }
1369     }
1370     // Retrieve modified tolerance total for immigrants
1371     return GetOrganism()->GetPhenotype().CalcToleranceImmigrants();
1372   }
1373   if (tolerance_type == 1) {
1374     // Modify tolerance towards own offspring
1375     PushToleranceInstExe(1, ctx);
1376 
1377     // Update tolerance list by removing the most recent dec_tolerance record
1378     delete  GetOrganism()->GetPhenotype().GetToleranceOffspringOwn().Pop();
1379 
1380     // If not at max tolerance, decrease the intolerance cache
1381     if (GetOrganism()->GetPhenotype().GetIntolerances()[1].second != 0) {
1382       GetOrganism()->GetPhenotype().GetIntolerances()[1].second--;
1383     }
1384     // Retrieve modified tolerance total for own offspring.
1385     return GetOrganism()->GetPhenotype().CalcToleranceOffspringOwn();
1386   }
1387   if (tolerance_type == 2) {
1388     // Modify tolerance towards other offspring of the group
1389     PushToleranceInstExe(2, ctx);
1390 
1391     // Update tolerance list by removing the most recent dec_tolerance record
1392     delete GetOrganism()->GetPhenotype().GetToleranceOffspringOthers().Pop();
1393 
1394     // If not at max tolerance, decrease the intolerance cache
1395     if (GetOrganism()->GetPhenotype().GetIntolerances()[2].second != 0) {
1396       GetOrganism()->GetPhenotype().GetIntolerances()[2].second--;
1397       GetGroupIntolerances(group_id, 1, -1)--;
1398     }
1399     // Retrieve modified tolerance total for other offspring in group.
1400     return GetOrganism()->GetPhenotype().CalcToleranceOffspringOthers();
1401   }
1402   return -1;
1403 }
1404 
1405 /* Decreases tolerance towards the addition of members to the group.
1406  * toleranceType:
1407  *    0: decreases tolerance towards immigrants
1408  *    1: decreases tolerance towards own offspring
1409  *    2: decreases tolerance towards other offspring of the group
1410  * Records the update during which dec-tolerance was executed
1411  * Returns the modified tolerance total.
1412  */
DecTolerance(const int tolerance_type,cAvidaContext & ctx)1413 int cPopulationInterface::DecTolerance(const int tolerance_type, cAvidaContext &ctx)
1414 {
1415   const int cur_update = m_world->GetStats().GetUpdate();
1416   const int tolerance_max = m_world->GetConfig().MAX_TOLERANCE.Get();
1417   int group_id = GetOrganism()->GetOpinion().first;
1418 
1419   if (tolerance_type == 0) {
1420     // Modify tolerance towards immigrants
1421     PushToleranceInstExe(3, ctx);
1422 
1423     // Update tolerance list by inserting new record (at the front)
1424     tList<int>& tolerance_list = GetOrganism()->GetPhenotype().GetToleranceImmigrants();
1425     tolerance_list.Push(new int(cur_update));
1426     if (tolerance_list.GetSize() > tolerance_max) delete tolerance_list.PopRear();
1427 
1428     // If not at min tolerance, increase the intolerance cache
1429     if (GetOrganism()->GetPhenotype().GetIntolerances()[0].second != tolerance_max) {
1430       GetOrganism()->GetPhenotype().GetIntolerances()[0].second++;
1431       GetGroupIntolerances(group_id, 0, -1)++;
1432       if (m_world->GetConfig().TOLERANCE_VARIATIONS.Get() == 2) {
1433         if (GetOrganism()->GetPhenotype().GetMatingType() == MATING_TYPE_FEMALE) GetGroupIntolerances(group_id, 0, 0)++;
1434         else if (GetOrganism()->GetPhenotype().GetMatingType() == MATING_TYPE_MALE) GetGroupIntolerances(group_id, 0, 1)++;
1435         else if (GetOrganism()->GetPhenotype().GetMatingType() == MATING_TYPE_JUVENILE) GetGroupIntolerances(group_id, 0, 2)++;
1436       }
1437     }
1438 
1439     // Return modified tolerance total for immigrants.
1440     return GetOrganism()->GetPhenotype().CalcToleranceImmigrants();
1441   }
1442   if (tolerance_type == 1) {
1443     PushToleranceInstExe(4, ctx);
1444 
1445     // Update tolerance list by inserting new record (at the front)
1446     tList<int>& tolerance_list = GetOrganism()->GetPhenotype().GetToleranceOffspringOwn();
1447     tolerance_list.Push(new int(cur_update));
1448     if(tolerance_list.GetSize() > tolerance_max) delete tolerance_list.PopRear();
1449 
1450     // If not at min tolerance, increase the intolerance cache
1451     if (GetOrganism()->GetPhenotype().GetIntolerances()[1].second != tolerance_max) {
1452       GetOrganism()->GetPhenotype().GetIntolerances()[1].second++;
1453     }
1454     // Return modified tolerance total for own offspring.
1455     return GetOrganism()->GetPhenotype().CalcToleranceOffspringOwn();
1456 
1457   }
1458   if (tolerance_type == 2) {
1459     PushToleranceInstExe(5, ctx);
1460 
1461     // Update tolerance list by inserting new record (at the front)
1462     tList<int>& tolerance_list = GetOrganism()->GetPhenotype().GetToleranceOffspringOthers();
1463     tolerance_list.Push(new int(cur_update));
1464     if(tolerance_list.GetSize() > tolerance_max) delete tolerance_list.PopRear();
1465 
1466     // If not at min tolerance, increase the intolerance cache
1467     if (GetOrganism()->GetPhenotype().GetIntolerances()[2].second != tolerance_max) {
1468       GetOrganism()->GetPhenotype().GetIntolerances()[2].second++;
1469       GetOrganism()->GetOrgInterface().GetGroupIntolerances(group_id, 1, -1)++;
1470     }
1471     // Retrieve modified tolerance total for other offspring in the group.
1472     return GetOrganism()->GetPhenotype().CalcToleranceOffspringOthers();
1473   }
1474   return -1;
1475 }
1476 
CalcGroupToleranceImmigrants(int prop_group_id,int mating_type)1477 int cPopulationInterface::CalcGroupToleranceImmigrants(int prop_group_id, int mating_type)
1478 {
1479   return m_world->GetPopulation().CalcGroupToleranceImmigrants(prop_group_id, mating_type);
1480 }
1481 
CalcGroupToleranceOffspring(cOrganism * parent_organism)1482 int cPopulationInterface::CalcGroupToleranceOffspring(cOrganism* parent_organism)
1483 {
1484   return m_world->GetPopulation().CalcGroupToleranceOffspring(parent_organism);
1485 }
1486 
CalcGroupOddsImmigrants(int group_id,int mating_type)1487 double cPopulationInterface::CalcGroupOddsImmigrants(int group_id, int mating_type)
1488 {
1489   return m_world->GetPopulation().CalcGroupOddsImmigrants(group_id, mating_type);
1490 }
1491 
CalcGroupOddsOffspring(cOrganism * parent)1492 double cPopulationInterface::CalcGroupOddsOffspring(cOrganism* parent)
1493 {
1494   return m_world->GetPopulation().CalcGroupOddsOffspring(parent);
1495 }
1496 
CalcGroupOddsOffspring(int group_id)1497 double cPopulationInterface::CalcGroupOddsOffspring(int group_id)
1498 {
1499   return m_world->GetPopulation().CalcGroupOddsOffspring(group_id);
1500 }
1501 
AttemptImmigrateGroup(int group_id,cOrganism * org)1502 bool cPopulationInterface::AttemptImmigrateGroup(int group_id, cOrganism* org)
1503 {
1504   return m_world->GetPopulation().AttemptImmigrateGroup(group_id, org);
1505 }
1506 
PushToleranceInstExe(int tol_inst,cAvidaContext & ctx)1507 void cPopulationInterface::PushToleranceInstExe(int tol_inst, cAvidaContext& ctx)
1508 {
1509   if(!m_world->GetConfig().TRACK_TOLERANCE.Get()) {
1510     m_world->GetStats().PushToleranceInstExe(tol_inst);
1511     return;
1512   }
1513 
1514   const tArray<double> res_count = GetResources(ctx);
1515 
1516   int group_id = GetOrganism()->GetOpinion().first;
1517   int group_size = NumberOfOrganismsInGroup(group_id);
1518   double resource_level = res_count[group_id];
1519   int tol_max = m_world->GetConfig().MAX_TOLERANCE.Get();
1520 
1521   double immigrant_odds = CalcGroupOddsImmigrants(group_id, -1);
1522   double offspring_own_odds;
1523   double offspring_others_odds;
1524   int tol_immi = GetOrganism()->GetPhenotype().CalcToleranceImmigrants();
1525   int tol_own;
1526   int tol_others;
1527 
1528   if(m_world->GetConfig().TOLERANCE_VARIATIONS.Get() > 0) {
1529     offspring_own_odds = 1.0;
1530     offspring_others_odds = 1.0;
1531     tol_own = tol_max;
1532     tol_others = tol_max;
1533   } else {
1534     offspring_own_odds = CalcGroupOddsOffspring(GetOrganism());
1535     offspring_others_odds = CalcGroupOddsOffspring(group_id);
1536     tol_own = GetOrganism()->GetPhenotype().CalcToleranceOffspringOwn();
1537     tol_others = GetOrganism()->GetPhenotype().CalcToleranceOffspringOthers();
1538   }
1539 
1540   double odds_immi = immigrant_odds * 100;
1541   double odds_own = offspring_own_odds * 100;
1542   double odds_others = offspring_others_odds * 100;
1543 
1544   m_world->GetStats().PushToleranceInstExe(tol_inst, group_id, group_size, resource_level, odds_immi, odds_own, odds_others, tol_immi, tol_own, tol_others, tol_max);
1545   return;
1546 }
1547 
PushDonateSpecInstExe(cAvidaContext & ctx,cOrganism * recipient_org,int relatedness)1548 void cPopulationInterface::PushDonateSpecInstExe(cAvidaContext& ctx, cOrganism* recipient_org, int relatedness)
1549 {
1550   if(!m_world->GetConfig().TRACK_DONATES.Get()) {
1551     return;
1552   }
1553 
1554   int org_id = GetOrganism()->GetID();
1555   int cell_id = GetOrganism()->GetCellID();
1556   int recipient_id = recipient_org->GetID();
1557   int recipient_cell_id = recipient_org->GetCellID();
1558   bool recip_is_beggar = recipient_org->IsBeggar();
1559   int num_donates =GetOrganism()->GetPhenotype().GetCurNumDonates();
1560   m_world->GetStats().PushDonateSpecificInstExe(org_id, cell_id, recipient_id, recipient_cell_id, relatedness, recip_is_beggar, num_donates);
1561   return;
1562 }
1563 
GetGroupIntolerances(int group_id,int tol_num,int mating_type)1564 int& cPopulationInterface::GetGroupIntolerances(int group_id, int tol_num, int mating_type)
1565 {
1566   return m_world->GetPopulation().GetGroupIntolerances(group_id, tol_num, mating_type);
1567 }
1568 
DecNumPreyOrganisms()1569 void cPopulationInterface::DecNumPreyOrganisms()
1570 {
1571   m_world->GetPopulation().DecNumPreyOrganisms();
1572 }
1573 
DecNumPredOrganisms()1574 void cPopulationInterface::DecNumPredOrganisms()
1575 {
1576   m_world->GetPopulation().DecNumPredOrganisms();
1577 }
1578 
IncNumPreyOrganisms()1579 void cPopulationInterface::IncNumPreyOrganisms()
1580 {
1581   m_world->GetPopulation().IncNumPreyOrganisms();
1582 }
1583 
IncNumPredOrganisms()1584 void cPopulationInterface::IncNumPredOrganisms()
1585 {
1586   m_world->GetPopulation().IncNumPredOrganisms();
1587 }
1588 
AttackFacedOrg(cAvidaContext & ctx,int loser)1589 void cPopulationInterface::AttackFacedOrg(cAvidaContext& ctx, int loser)
1590 {
1591   m_world->GetPopulation().AttackFacedOrg(ctx, loser);
1592 }
1593 
RecordMinPreyFailedAttack()1594 void cPopulationInterface::RecordMinPreyFailedAttack()
1595 {
1596   m_world->GetPopulation().RecordMinPreyFailedAttack();
1597 }
1598 
1599 // -------- Avatar support --------
1600 /* Each organism carries an array of avatars linking the organism to any cells it is occupying.
1601  * Each cell contains an array of the organisms with avatars in that cell, linking the cells back to
1602  * the organisms (in cPopulationCell). This allows both multiple organisms to occupy the same cell
1603  * and organisms to occupy/interact with multiple cells. Currently only two types of avatars are
1604  * supported: input and output, also used as predators and prey.
1605  */
1606 
1607 // Check if the avatar has any output avatars sharing the same cell
HasOutputAV(int av_num)1608 bool cPopulationInterface::HasOutputAV(int av_num)
1609 {
1610   // If the avatar exists..
1611   if (av_num < getNumAV()) {
1612     // Check the avatar's cell for an output avatar
1613     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).HasOutputAV(GetOrganism());
1614   }
1615   return false;
1616 }
1617 
1618 // Check if the avatar's faced cell has any output avatars
FacedHasOutputAV(int av_num)1619 bool cPopulationInterface::FacedHasOutputAV(int av_num)
1620 {
1621   // If the avatar exists..
1622   if (av_num < getNumAV()) {
1623     // Check the avatar's faced cell for an output avatar
1624     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).HasOutputAV(GetOrganism());
1625   }
1626   return false;
1627 }
1628 
1629 // Check if the avatar's faced cell has any avatars
FacedHasAV(int av_num)1630 bool cPopulationInterface::FacedHasAV(int av_num)
1631 {
1632   // If the avatar exists..
1633   if (av_num < getNumAV()) {
1634     // Check the avatar's faced cell for other avatars
1635     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).HasAV();
1636   }
1637   return false;
1638 }
1639 
1640 // Check if the avatar's faced cell has any predator (input) avatars
FacedHasPredAV(int av_num)1641 bool cPopulationInterface::FacedHasPredAV(int av_num)
1642 {
1643   // If the avatar exists..
1644   if (av_num < getNumAV()) {
1645     // Check the faced cell for predators (inputs)
1646     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).HasInputAV();
1647   }
1648   return false;
1649 }
1650 
1651 // Check it the avatar's faced cell has any prey (output) avatars
FacedHasPreyAV(int av_num)1652 bool cPopulationInterface::FacedHasPreyAV(int av_num)
1653 {
1654   // If the avatar exists..
1655   if (av_num < getNumAV()) {
1656     // Check the faced cell for prey (outputs)
1657     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).HasOutputAV();
1658   }
1659   return false;
1660 }
1661 
1662 // Creates a new avatar and adds it to the cell avatar lists
AddIOAV(int av_cell_id,int av_facing,bool input,bool output)1663 void cPopulationInterface::AddIOAV(int av_cell_id, int av_facing, bool input, bool output)
1664 {
1665   // Add new avatar to m_avatars
1666   sIO_avatar tmpAV(av_cell_id, av_facing, -1, input, output);
1667   m_avatars.Push(tmpAV);
1668 
1669   // If this is an input avatar add to the target cell
1670   if (input) {
1671     m_world->GetPopulation().GetCell(av_cell_id).AddInputAV(GetOrganism());
1672   }
1673 
1674   // If this is an output avatar add to the target cell
1675   if (output) {
1676     m_world->GetPopulation().GetCell(av_cell_id).AddOutputAV(GetOrganism());
1677   }
1678 
1679   // Find the created avatar's faced cell
1680   SetAVFacedCellID(getNumAV() - 1);
1681 }
1682 
1683 // Creates a new avatar based on the organism's forage target as a predator or prey, and adds it to the cell
AddPredPreyAV(int av_cell_id)1684 void cPopulationInterface::AddPredPreyAV(int av_cell_id)
1685 {
1686   // Add predator (saved as input avatar)
1687   if (GetOrganism()->GetForageTarget() == -2) {
1688     sIO_avatar predAV(av_cell_id, 0, -1, true, false);
1689     m_avatars.Push(predAV);
1690     m_world->GetPopulation().GetCell(av_cell_id).AddInputAV(GetOrganism());
1691   // Add prey (saved as output avatar)
1692   } else {
1693     sIO_avatar preyAV(av_cell_id, 0, -1, false, true);
1694     m_avatars.Push(preyAV);
1695     m_world->GetPopulation().GetCell(av_cell_id).AddOutputAV(GetOrganism());
1696   }
1697   // Find the created avatar's faced cell
1698   SetAVFacedCellID(getNumAV() - 1);
1699 }
1700 
1701 // Switches the avatar from being a predator to a prey avatar or vice-versa
SwitchPredPrey(int av_num)1702 void cPopulationInterface::SwitchPredPrey(int av_num)
1703 {
1704   // If the avatar exists..
1705   if (av_num < getNumAV()) {
1706     // Is a predator, switching to a prey (input to output)
1707     if (m_avatars[av_num].av_input) {
1708       m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).RemoveInputAV(GetOrganism());
1709       m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).AddOutputAV(GetOrganism());
1710       m_avatars[av_num].av_input = false;
1711       m_avatars[av_num].av_output = true;
1712     // Is prey, switching to a predator (output to intput)
1713     } else if (m_avatars[av_num].av_output) {
1714       m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).RemoveOutputAV(GetOrganism());
1715       m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).AddInputAV(GetOrganism());
1716       m_avatars[av_num].av_input = true;
1717       m_avatars[av_num].av_output = false;
1718     }
1719   }
1720 }
1721 
1722 // Removes all the organism's avatars and removes them from cell lists
RemoveAllAV()1723 void cPopulationInterface::RemoveAllAV()
1724 {
1725   // Cycle through removing all avatars
1726   for (int i = 0; i < getNumAV(); i++) {
1727     sIO_avatar tmpAV = m_avatars.Pop();
1728     // Check that avatar is actually in a cell
1729     if (tmpAV.av_cell_id >= 0) {
1730       // If input avatar remove from the cell
1731       if (tmpAV.av_input) {
1732         m_world->GetPopulation().GetCell(tmpAV.av_cell_id).RemoveInputAV(GetOrganism());
1733       }
1734       // If output avatar remove from the cell
1735       if (tmpAV.av_output) {
1736         m_world->GetPopulation().GetCell(tmpAV.av_cell_id).RemoveOutputAV(GetOrganism());
1737       }
1738     }
1739   }
1740 }
1741 
1742 // Returns the avatar's faced direction
GetAVFacing(int av_num)1743 int cPopulationInterface::GetAVFacing(int av_num)
1744 {
1745   // If the avatar exists..
1746   if (av_num < getNumAV()) {
1747     // Return avatar's facing
1748     return m_avatars[av_num].av_facing;
1749   }
1750   return 0;
1751 }
1752 
1753 // Returns the avatar's cell id
GetAVCellID(int av_num)1754 int cPopulationInterface::GetAVCellID(int av_num)
1755 {
1756   // If the avatar exists..
1757   if (av_num < getNumAV()) {
1758     // Return the avatar's cell id
1759     return m_avatars[av_num].av_cell_id;
1760   }
1761   return -1;
1762 }
1763 
1764 // Returns cell id faced by avatar, only for torus and bounded worlds
GetAVFacedCellID(int av_num)1765 int cPopulationInterface::GetAVFacedCellID(int av_num)//** GetCellXPosition()
1766 {
1767   if (av_num < getNumAV()) {
1768     return m_avatars[av_num].av_faced_cell;
1769   }
1770   return -1;
1771 }
1772 
1773 // Returns the number of cells neighboring the avatar's
1774 // Avatar facing and movement only works in bounded or toroidial geometries
GetAVNumNeighbors(int av_num)1775 int cPopulationInterface::GetAVNumNeighbors(int av_num)
1776 {
1777   if ((m_world->GetConfig().WORLD_GEOMETRY.Get() != 1) && (m_world->GetConfig().WORLD_GEOMETRY.Get() != 2)) m_world->GetDriver().RaiseFatalException(-1, "Not valid WORLD_GEOMETRY for USE_AVATAR, must be torus or bounded.");
1778 
1779   // If the avatar exists..
1780   if (av_num < getNumAV()) {
1781     if (m_world->GetConfig().WORLD_GEOMETRY.Get() == 2) return 8;
1782 
1783     const int cell_id = m_avatars[av_num].av_cell_id;
1784     const int x_size = m_world->GetConfig().WORLD_X.Get();
1785     const int y_size = m_world->GetConfig().WORLD_Y.Get() / m_world->GetConfig().NUM_DEMES.Get();
1786     const int deme_size = x_size * y_size;
1787     int deme_cell = cell_id % deme_size;
1788     int x = deme_cell % x_size;
1789     int y = deme_cell / x_size;
1790 
1791     // Is the cell on a corner..
1792     if (x == 0 || x == (x_size - 1)) {
1793       if (y == 0 || y == (y_size - 1)) return 3;
1794       // Is the cell on a side-edge..
1795       else return 5;
1796     }
1797     // Is the cell on a top or bottom edge..
1798     if (y == 0 || y == (y_size - 1)) return 5;
1799     // The cell must be on the interior..
1800     return 8;
1801   }
1802   return 0;
1803 }
1804 
1805 // Returns the avatar's faced cell data
GetAVFacedData(int av_num)1806 int cPopulationInterface::GetAVFacedData(int av_num)
1807 {
1808   // If the avatar exists..
1809   if (av_num < getNumAV()) {
1810     // Return the avatar's faced cell data
1811     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).GetCellData();
1812   }
1813   return -1;
1814 }
1815 
1816 // Returns the avatar's faced cell org id data
GetAVFacedDataOrgID(int av_num)1817 int cPopulationInterface::GetAVFacedDataOrgID(int av_num)
1818 {
1819   // If the avatar exists..
1820   if (av_num < getNumAV()) {
1821     // Returns the avatar's faced cell org id data
1822     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).GetCellDataOrgID();
1823   }
1824   return -1;
1825 }
1826 
1827 // Returns the avatar's faced cell update data
GetAVFacedDataUpdate(int av_num)1828 int cPopulationInterface::GetAVFacedDataUpdate(int av_num)
1829 {
1830   // If the avatar exists..
1831   if (av_num < getNumAV()) {
1832     // Returns the avatar's faced cell update data
1833     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).GetCellDataUpdate();
1834   }
1835   return -1;
1836 }
1837 
1838 // Returns the avatar's faced cell territory data
GetAVFacedDataTerritory(int av_num)1839 int cPopulationInterface::GetAVFacedDataTerritory(int av_num)
1840 {
1841   // If the avatar exists..
1842   if (av_num < getNumAV()) {
1843     // Returns the avatar's faced cell territory data
1844     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).GetCellDataTerritory();
1845   }
1846   return -1;
1847 }
1848 
1849 // Returns the avatar's faced cell data
GetAVData(int av_num)1850 int cPopulationInterface::GetAVData(int av_num)
1851 {
1852   // If the avatar exists..
1853   if (av_num < getNumAV()) {
1854     // Return the avatar's faced cell data
1855     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).GetCellData();
1856   }
1857   return -1;
1858 }
1859 
1860 // Returns the avatar's faced cell org id data
GetAVDataOrgID(int av_num)1861 int cPopulationInterface::GetAVDataOrgID(int av_num)
1862 {
1863   // If the avatar exists..
1864   if (av_num < getNumAV()) {
1865     // Returns the avatar's faced cell org id data
1866     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).GetCellDataOrgID();
1867   }
1868   return -1;
1869 }
1870 
1871 // Returns the avatar's faced cell update data
GetAVDataUpdate(int av_num)1872 int cPopulationInterface::GetAVDataUpdate(int av_num)
1873 {
1874   // If the avatar exists..
1875   if (av_num < getNumAV()) {
1876     // Returns the avatar's faced cell update data
1877     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).GetCellDataUpdate();
1878   }
1879   return -1;
1880 }
1881 
1882 // Returns the avatar's faced cell territory data
GetAVDataTerritory(int av_num)1883 int cPopulationInterface::GetAVDataTerritory(int av_num)
1884 {
1885   // If the avatar exists..
1886   if (av_num < getNumAV()) {
1887     // Returns the avatar's faced cell territory data
1888     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).GetCellDataTerritory();
1889   }
1890   return -1;
1891 }
1892 
1893 // Finds the index of the next avatar which matches input/output specifications
FindAV(bool input,bool output,int av_num)1894 int cPopulationInterface::FindAV(bool input, bool output, int av_num)
1895 {
1896   assert(getNumAV() > 0);
1897   const int num_AV = getNumAV();
1898   for (int i = 0; i < num_AV; i++) {
1899     int index = i + av_num % num_AV;
1900     if (m_avatars[index].av_input == input && m_avatars[index].av_output == output) {
1901       return index;
1902     }
1903   }
1904 }
1905 
1906 // Sets the avatar's facing, then sets the faced cell
SetAVFacing(int av_facing,int av_num)1907 void cPopulationInterface::SetAVFacing(int av_facing, int av_num)
1908 {
1909   // If the avatar exists..
1910   if (av_num < getNumAV()) {
1911     m_avatars[av_num].av_facing = av_facing;
1912     // Set the new avatar faced cell id
1913     SetAVFacedCellID(av_num);
1914   }
1915 }
1916 
1917 // Changes the avatar's cell id, moving it to the correct cell lists, and find the new faced cell id
SetAVCellID(int av_cell_id,int av_num)1918 bool cPopulationInterface::SetAVCellID(int av_cell_id, int av_num)
1919 {
1920   // If the avatar exists..
1921   if (av_num < getNumAV()) {
1922     // Not necessary to move the avatar
1923     if (m_avatars[av_num].av_cell_id == av_cell_id) return false;
1924 
1925     // If the avatar was previously in another cell remove it
1926     if (m_avatars[av_num].av_cell_id > -1) {
1927       if (m_avatars[av_num].av_input) {
1928         m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).RemoveInputAV(GetOrganism());
1929       }
1930       if (m_avatars[av_num].av_output) {
1931         m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).RemoveOutputAV(GetOrganism());
1932       }
1933     }
1934 
1935     // If it is an input avatar, add to the new cell
1936     if (m_avatars[av_num].av_input) {
1937       m_world->GetPopulation().GetCell(av_cell_id).AddInputAV(GetOrganism());
1938     }
1939     // If it is an output avatar, add to the new cell
1940     if (m_avatars[av_num].av_output) {
1941       m_world->GetPopulation().GetCell(av_cell_id).AddOutputAV(GetOrganism());
1942     }
1943 
1944     // Set the avatar's cell
1945     m_avatars[av_num].av_cell_id = av_cell_id;
1946 
1947     // Set the avatar's new faced cell
1948     SetAVFacedCellID(av_num);
1949     return true;
1950   }
1951   return false;
1952 }
1953 
1954 // Determine and store the cell id faced by the avatar
1955 // Note:
SetAVFacedCellID(int av_num)1956 void cPopulationInterface::SetAVFacedCellID(int av_num)
1957 {
1958   const int world_geometry = m_world->GetConfig().WORLD_GEOMETRY.Get();
1959   // Avatars only supported in bounded and toroidal world geometries
1960   if ((world_geometry != 1) && (world_geometry != 2)) m_world->GetDriver().RaiseFatalException(-1, "Not valid WORLD_GEOMETRY for USE_AVATAR, must be torus or bounded.");
1961 
1962   // If the avatar exists..
1963   if (av_num < getNumAV()) {
1964     // Convert the cell id into a deme x,y position
1965     const int x_size = m_world->GetConfig().WORLD_X.Get();
1966     const int y_size = m_world->GetConfig().WORLD_Y.Get() / m_world->GetConfig().NUM_DEMES.Get();
1967     const int deme_size = x_size * y_size;
1968 
1969     const int old_cell_id = m_avatars[av_num].av_cell_id;
1970     const int facing = m_avatars[av_num].av_facing;
1971 
1972     const int deme_id = old_cell_id / deme_size;
1973     const int old_deme_cell = old_cell_id % deme_size;
1974 
1975     int x = old_deme_cell % x_size;
1976     int y = old_deme_cell / x_size;
1977 
1978     // If this happens to be an avatar in a single cell world, it can't face any cell beyond its own
1979     if (deme_size == 1) {
1980       m_avatars[av_num].av_faced_cell = m_avatars[av_num].av_cell_id;
1981       return;
1982     }
1983 
1984     bool off_the_edge_facing = false;
1985     // If a bounded grid, do checks for facing off the edge of a bounded world grid..
1986     if (world_geometry == 1) {
1987       // Check if the avatar is at the end of a single column world
1988       if (x_size == 1) {
1989         if (y == 0) {
1990           y += 1;
1991           off_the_edge_facing = true;
1992         }
1993         else if (y == (y_size - 1)) {
1994           y -= 1;
1995           off_the_edge_facing = true;
1996         }
1997       // Check if the avatar is at the end of a single row world
1998       } else if (y_size == 1) {
1999         if (x == 0) {
2000           x += 1;
2001           off_the_edge_facing = true;
2002         }
2003         else if (y == (y_size - 1)) {
2004           x -= 1;
2005           off_the_edge_facing = true;
2006         }
2007       }
2008 
2009       // The world is neither a single row or column, continuing border facing checks
2010       if (!off_the_edge_facing) {
2011         // West edge..
2012         if (x == 0) {
2013           // Northwest corner
2014           if (y == 0) {
2015             if (facing == 0 || facing == 7 || facing == 6) {
2016               if (m_world->GetRandom().GetInt(0, 2)) x += 1;
2017               else y += 1;
2018               off_the_edge_facing = true;
2019             }
2020             else if (facing == 5) {
2021               y += 1;
2022               off_the_edge_facing = true;
2023             }
2024             else if (facing == 1) {
2025               x += 1;
2026               off_the_edge_facing = true;
2027             }
2028           }
2029           // Southwest corner
2030           else if (y == (y_size - 1)) {
2031             if (facing == 4 || facing == 5 || facing == 6) {
2032               if (m_world->GetRandom().GetInt(0, 2)) x += 1;
2033               else y -= 1;
2034               off_the_edge_facing = true;
2035             }
2036             else if (facing == 7) {
2037               x += 1;
2038               off_the_edge_facing = true;
2039             }
2040             else if (facing == 3) {
2041               y -= 1;
2042               off_the_edge_facing = true;
2043             }
2044           }
2045           // West edge facings not checked yet
2046           if (!off_the_edge_facing) {
2047             // West edge facing southwest
2048             if (facing == 5) {
2049               y -= 1;
2050               off_the_edge_facing = true;
2051             // West edge facing west
2052             }
2053             else if (facing == 6) {
2054               if (m_world->GetRandom().GetInt(0, 2)) y += 1;
2055               else y -= 1;
2056               off_the_edge_facing = true;
2057             }
2058             // West edge facing northwest
2059             else if (facing == 7) {
2060               y += 1;
2061               off_the_edge_facing = true;
2062             }
2063           }
2064         }
2065         // East edge..
2066         else if (x == (x_size - 1)) {
2067           // Northeast corner
2068           if (y == 0) {
2069             if (facing == 0 || facing == 1 || facing == 2) {
2070               if (m_world->GetRandom().GetInt(0, 2)) x -= 1;
2071               else y += 1;
2072               off_the_edge_facing = true;
2073             }
2074             if (facing == 3) {
2075               y += 1;
2076               off_the_edge_facing = true;
2077             }
2078             if (facing == 7) {
2079               x -= 1;
2080               off_the_edge_facing = true;
2081             }
2082           }
2083           // Southeast corner
2084           else if (y == (y_size - 1)) {
2085             if (facing == 2 || facing == 3 || facing == 4) {
2086               if (m_world->GetRandom().GetInt(0, 2)) x -= 1;
2087               else y -= 1;
2088               off_the_edge_facing = true;
2089             }
2090             else if (facing == 1) {
2091               y -= 1;
2092               off_the_edge_facing = true;
2093             }
2094             else if (facing == 5) {
2095               x -= 1;
2096               off_the_edge_facing = true;
2097             }
2098           }
2099           // East edge facings not checked yet
2100           if (!off_the_edge_facing) {
2101             // East edge facing northeast
2102             if (facing == 1) {
2103               y -= 1;
2104               off_the_edge_facing = true;
2105             // East edge facing east
2106             }
2107             else if (facing == 2) {
2108               if (m_world->GetRandom().GetInt(0, 2)) y += 1;
2109               else y -= 1;
2110               off_the_edge_facing = true;
2111             }
2112             // East edge facing southeast
2113             else if (facing == 3) {
2114               y += 1;
2115               off_the_edge_facing = true;
2116             }
2117           }
2118         }
2119         // North edge..
2120         else if (y == 0) {
2121           // North edge facing northwest
2122           if (facing == 7) {
2123             x -= 1;
2124             off_the_edge_facing = true;
2125           // North edge facing north
2126           }
2127           else if (facing == 0) {
2128             if (m_world->GetRandom().GetInt(0, 2)) x += 1;
2129             else x -= 1;
2130             off_the_edge_facing = true;
2131           }
2132           // North edge facing northeast
2133           else if (facing == 1) {
2134             x += 1;
2135             off_the_edge_facing = true;
2136           }
2137         }
2138         // South edge..
2139         else if (y == (y_size - 1)) {
2140           // South edge facing southeast
2141           if (facing == 3) {
2142             x += 1;
2143             off_the_edge_facing = true;
2144           // South edge facing south
2145           }
2146           else if (facing == 4) {
2147             if (m_world->GetRandom().GetInt(0, 2)) x += 1;
2148             else x -= 1;
2149             off_the_edge_facing = true;
2150           }
2151           // South edge facing southwest
2152           else if (facing == 5) {
2153             x -= 1;
2154             off_the_edge_facing = true;
2155           }
2156         }
2157       }
2158     }
2159 
2160     // Torus world geometry or not a bounded outward facing edge..
2161     if (!off_the_edge_facing || world_geometry == 2) {
2162       // North facing
2163       if ((facing == 0) || (facing == 1) || (facing == 7)) {
2164         y = (y - 1 + y_size) % y_size;
2165       }
2166 
2167       // South facing
2168       if ((facing == 3) || (facing == 4) || (facing == 5)) {
2169         y = (y + 1) % y_size;
2170       }
2171 
2172       // East facing
2173       if ((facing == 1) || (facing == 2) || (facing == 3)) {
2174         x = (x + 1) % x_size;
2175       }
2176 
2177       // West facing
2178       if ((facing == 5) || (facing == 6) || (facing == 7)) {
2179         x = (x - 1 + x_size) % x_size;
2180       }
2181     }
2182 
2183     // Convert the x,y deme coordinates back into a cell id
2184     const int new_deme_cell = y * x_size + x;
2185     const int new_cell_id = deme_id * deme_size + new_deme_cell;
2186 
2187     // Store the faced cell id
2188     m_avatars[av_num].av_faced_cell = new_cell_id;
2189   }
2190 }
2191 
2192 // Sets the avatar's cell's data
SetAVCellData(const int newData,const int org_id,int av_num)2193 void cPopulationInterface::SetAVCellData(const int newData, const int org_id, int av_num)
2194 {
2195   // If the avatar exists..
2196   if (av_num < getNumAV()) {
2197     m_world->GetPopulation().GetCell(m_avatars[av_num].av_cell_id).SetCellData(newData, org_id);
2198   }
2199 }
2200 
2201 // Move input avatar into faced cell
MoveAV(cAvidaContext & ctx,int av_num)2202 bool cPopulationInterface::MoveAV(cAvidaContext& ctx, int av_num)
2203 {
2204   // If the avatar exists..
2205   bool success = false;
2206   if (av_num < getNumAV()) {
2207     // Move the avatar into the faced cell
2208     int src_id = m_avatars[av_num].av_cell_id;
2209     int dest_id = m_avatars[av_num].av_faced_cell;
2210     int true_cell = m_cell_id;
2211     if (m_world->GetConfig().NEURAL_NETWORKING.Get() || m_world->GetPopulation().MoveOrganisms(ctx, src_id, dest_id, true_cell)) {
2212       return SetAVCellID(m_avatars[av_num].av_faced_cell, av_num);
2213     }
2214   }
2215   return success;
2216 }
2217 
2218 // Rotate the avatar by input increment, then set the new faced cell
RotateAV(int increment,int av_num)2219 bool cPopulationInterface::RotateAV(int increment, int av_num)
2220 {
2221   // If the avatar exists..
2222   if (av_num < getNumAV()) {
2223     if (increment >= 0) {
2224       increment %= 8;
2225     } else {
2226       increment = -increment;
2227       increment %= 8;
2228       increment = -increment;
2229     }
2230     // Adjust facing by increment
2231     SetAVFacing((m_avatars[av_num].av_facing + increment + 8) % 8);
2232     return true;
2233   }
2234   return false;
2235 }
2236 
2237 // Returns a random input or output avatar from the faced cell
GetRandFacedAV(int av_num)2238 cOrganism* cPopulationInterface::GetRandFacedAV(int av_num)
2239 {
2240   // If the avatar exists..
2241   if (av_num < getNumAV()) {
2242     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).GetRandAV();
2243   }
2244   return NULL;
2245 }
2246 
2247 // Returns a random predator (input) avatar from the faced cell
GetRandFacedPredAV(int av_num)2248 cOrganism* cPopulationInterface::GetRandFacedPredAV(int av_num)
2249 {
2250   // If the avatar exists..
2251   if (av_num < getNumAV()) {
2252     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).GetRandPredAV();
2253   }
2254   return NULL;
2255 }
2256 
2257 // Returns a random prey (output) avatar from the faced cell
GetRandFacedPreyAV(int av_num)2258 cOrganism* cPopulationInterface::GetRandFacedPreyAV(int av_num)
2259 {
2260   // If the avatar exists..
2261   if (av_num < getNumAV()) {
2262     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).GetRandPreyAV();
2263   }
2264   return NULL;
2265 }
2266 
2267 // Returns an array of all avatars in the organism's avatar's faced cell
GetFacedAVs(int av_num)2268 tArray<cOrganism*> cPopulationInterface::GetFacedAVs(int av_num)
2269 {
2270   // If the avatar exists..
2271   if (av_num < getNumAV()) {
2272     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).GetCellAVs();
2273   }
2274   tArray<cOrganism*> null_array(0, NULL);
2275   return null_array;
2276 }
2277 
2278 //Returns an array of all avatars in the organism's avatar's cell
GetCellAVs(int cell_id,int av_num)2279 tArray<cOrganism*> cPopulationInterface::GetCellAVs(int cell_id, int av_num)
2280 {
2281     //If the avatar exists...
2282     if (av_num <getNumAV()) {
2283         return m_world->GetPopulation().GetCell(cell_id).GetCellAVs();
2284     }
2285     tArray<cOrganism*> null_array(0, NULL);
2286     return null_array;
2287 }
2288 
2289 // Returns an array of all prey avatars in the organism's avatar's faced cell
GetFacedPreyAVs(int av_num)2290 tArray<cOrganism*> cPopulationInterface::GetFacedPreyAVs(int av_num)
2291 {
2292   // If the avatar exists..
2293   if (av_num < getNumAV()) {
2294     return m_world->GetPopulation().GetCell(m_avatars[av_num].av_faced_cell).GetCellOutputAVs();
2295   }
2296   tArray<cOrganism*> null_array(0, NULL);
2297   return null_array;
2298 }
2299 
2300 // Returns the avatar's cell resources
GetAVResources(cAvidaContext & ctx,int av_num)2301 const tArray<double>& cPopulationInterface::GetAVResources(cAvidaContext& ctx, int av_num)
2302 {
2303   assert(av_num < getNumAV());
2304   return m_world->GetPopulation().GetCellResources(m_avatars[av_num].av_cell_id, ctx);
2305 }
2306 
2307 // Returns the avatar's faced cell's resources
GetAVFacedResources(cAvidaContext & ctx,int av_num)2308 const tArray<double>& cPopulationInterface::GetAVFacedResources(cAvidaContext& ctx, int av_num)
2309 {
2310   assert(av_num < getNumAV());
2311   return m_world->GetPopulation().GetCellResources(m_avatars[av_num].av_faced_cell, ctx);
2312 }
2313 
2314 // Updates the avatar's cell resources
UpdateAVResources(cAvidaContext & ctx,const tArray<double> & res_change,int av_num)2315 void cPopulationInterface::UpdateAVResources(cAvidaContext& ctx, const tArray<double>& res_change, int av_num)
2316 {
2317   // If the avatar exists..
2318   if (av_num < getNumAV()) {
2319     m_world->GetPopulation().UpdateCellResources(ctx, res_change, m_avatars[av_num].av_cell_id);
2320   }
2321 }
2322 
BeginSleep()2323 void cPopulationInterface::BeginSleep()
2324 {
2325   if(m_world->GetConfig().LOG_SLEEP_TIMES.Get() == 1)
2326     m_world->GetPopulation().AddBeginSleep(m_cell_id, m_world->GetStats().GetUpdate());
2327   GetDeme()->IncSleepingCount();
2328 }
2329 
EndSleep()2330 void cPopulationInterface::EndSleep()
2331 {
2332   if(m_world->GetConfig().LOG_SLEEP_TIMES.Get() == 1)
2333     m_world->GetPopulation().AddEndSleep(m_cell_id, m_world->GetStats().GetUpdate());
2334   GetDeme()->DecSleepingCount();
2335 }
2336