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