1 /* Copyright 2008 Jason Kim Chong Polak
3 Please respect the following:
5 This file is part of bioCity. bioCity is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "Organism.hh"
20 #include "scenarios.hh"
28 #include "circle_square.hh"
29 #include "ConfReader.hh"
36 #include "World_scenarios_base.cpp"
37 // "Be who you are and say what you feel
38 // because those who mind don't matter and
39 // those who matter don't mind." -Seuss
41 // Set the organism id numbers starting at 1.
44 World::World( int _psize
, double _dx
, double _dy
)
48 rgen
= gsl_rng_alloc(T
);
50 if (_dx
<= 0 || _dy
<= 0)
52 cerr
<<"Distances must be positive."<<endl
;
58 cerr
<<"Number of citizens cannot be negative."<<endl
;
60 // setting up the population here
69 for ( int i
= 0; i
< population
; i
++)
71 org_type
= (int) 0.0*floor( sqrt((gsl_rng_uniform( rgen
)*2)) );
72 if (org_type
== 0) { p_type0
++; }
73 if (org_type
== 1) { p_type1
++; }
74 initx
= gsl_rng_uniform( rgen
)*dim_x
;
75 inity
= gsl_rng_uniform( rgen
)*dim_y
;
76 Organism
*temp
= new Organism( org_type
, 1, initx
,inity
);
77 citizens
.push_front( temp
);
83 list
<Organism
*>::iterator i1
= citizens
.begin();
84 for (int i
= 0; i
< population
; i
++)
86 if ((*i1
)!=NULL
) { delete (*i1
); }
90 if (rgen
!= NULL
) { gsl_rng_free( rgen
); }
93 void World::move_next( )
96 double currx
,curry
,rx
,ry
;
97 list
<Organism
*>::iterator i1
= citizens
.begin();
98 while (i1
!= citizens
.end() )
100 if ( (*i1
)->get_state( ) == 0 )
102 if ( (*i1
)->get_type() == 0)
106 i1
= citizens
.erase(i1
);
112 if (i
< population
&& (*i1
)->get_offspring() > 0)
114 rx
= gsl_rng_uniform( rgen
) - 1.0/2;
115 ry
= gsl_rng_uniform( rgen
) - 1.0/2;
116 currx
= (*i1
)->get_x();
117 curry
= (*i1
)->get_y();
118 if ( currx
+ rx
> dim_x
|| currx
+ rx
< 0 ) { rx
*= -1; }
119 if ( curry
+ ry
> dim_y
|| curry
+ ry
< 0 ) { ry
*= -1; }
124 citizens
.push_front( new Organism( 0, 1, currx
, curry
) );
127 (*i1
)->set_offspring( 0 );
128 (*i1
)->next_state( );
135 void World::calc_proximity( double _range
)
137 list
<Organism
*>::iterator i1
= citizens
.begin( );
138 while (i1
!= citizens
.end())
140 (*i1
)->set_proximity(0);
144 i1
= citizens
.begin();
145 list
<Organism
*>::iterator i2
= citizens
.begin( );
147 while (i1
!= citizens
.end())
149 while (i2
!= citizens
.end() )
151 if ( (*i1
)->distance_to( **i2
) < _range
)
153 (*i1
)->add_proximity(1);
154 (*i2
)->add_proximity(1);
165 void World::update( )
167 double reproduction = 0.05;
168 double kill_rate = 0.3;
169 double average_lifetime = 100;
172 double kill_range = 5;
173 double kill_prob = 0;
175 double currx,curry,rx,ry;
177 // Movement and Predation Loop
178 list<Organism*>::iterator i1 = citizens.begin();
179 list<Organism*>::iterator i2 = citizens.begin();
182 for ( int i = 0; i < population; i++ )
184 (*i1)->lifeup(); //advance in age after each update
186 unif_circle( &rx, &ry, rgen);
190 currx = (*i1)->get_x();
191 curry = (*i1)->get_y();
192 if ( currx + rx > dim_x || currx + rx < 0 ) { rx *= -1; }
193 if ( curry + ry > dim_y || curry + ry < 0 ) { ry *= -1; }
195 (*i1)->add_pos( rx, ry );
196 for ( int j = i + 1; j < population; j++)
198 if ( (*i1)->distance_to( **i2 ) < range )
200 int i1p = (*i1)->get_proximity();
201 int i2p = (*i2)->get_proximity();
202 (*i1)->set_proximity( i1p + 1 );
203 (*i2)->set_proximity( i2p + 1 );
206 //The predator-prey interaction rules
208 bool canEat = (*i1)->get_state() == 1;
209 canEat = canEat && (*i2)->get_state() == 1;
210 type1 = (*i1)->get_type();
211 type2 = (*i2)->get_type();
212 bool diff = type1 != type2;
213 canEat = canEat && diff;
215 if ( (*i1)->distance_to( **i2 ) < kill_range && canEat )
219 hunger = (*i1)->get_food();
223 hunger = (*i2)->get_food();
226 kill_prob = gsl_rng_uniform( rgen );
227 if (kill_prob < kill_rate*(1-hunger))
231 (*i1)->set_state( 0 ); //mark for death
236 (*i2)->set_state( 0 ); // " "
241 //End Predator-prey interactions
246 i2=i1; //Set i2 as the new i1
247 i2++; //Then increment i2
251 //Begin: Reproduction Loop
252 i1 = citizens.begin();
253 double will_reproduce;
255 int curr_pop = population;
256 for ( int i = 0 ; i < curr_pop; i++)
258 int currtype = (*i1)->get_type();
262 //If the predator has no food, it can't reproduce
263 if (currtype == 1) { type_dep *= (*i1)->get_food(); }
265 // If there are more than cutoff organisms in the
266 // given range then the organism cannot reproduce
267 // if (proximity[i] >= cutoff) {loc_dep = 0; }
269 will_reproduce = gsl_rng_uniform( rgen );
270 double test_cond = reproduction/(1 + (*i1)->get_proximity() );
271 (*i1)->set_proximity( 0 );
273 if (will_reproduce < test_cond*type_dep*loc_dep )
275 rx = gsl_rng_uniform( rgen ) - 1.0/2;
276 ry = gsl_rng_uniform( rgen ) - 1.0/2;
277 currx = (*i1)->get_x();
278 curry = (*i1)->get_y();
279 if ( currx + rx > dim_x || currx + rx < 0 ) { rx *= -1; }
280 if ( curry > dim_y || curry + ry < 0 ) { ry *= -1; }
284 if (currtype == 0) { p_type0++; }
285 if (currtype == 1) { p_type1++; }
287 Organism *temp = new Organism( currtype, 1, currx, curry );
288 citizens.push_front( temp );
293 //END: Reproduction Loop
295 // START: Grim Reaper
296 // Removes all organisms that have been eaten,
297 // and kills any organism that has died of
299 i1 = citizens.begin( );
301 double death_prob = 0;
302 while ( i1 != citizens.end() )
304 if ( (*i1)->get_state() == 1 )
306 death = gsl_cdf_gaussian_P( (*i1)->get_age()-average_lifetime ,3.0);
307 death_prob = gsl_rng_uniform( rgen );
308 if (death_prob < death)
310 (*i1)->set_state( 0 );
313 if ( (*i1)->get_state() == 0 )
315 switch ( (*i1)->get_type() )
327 i1 = citizens.erase( i1 ); //increments pointer too!
332 //END: Grim Reaper Loop
337 void World::print_graph( int id
)
340 g2_filled_rectangle( id
, 0, 0, dim_x
, dim_y
);
342 list
<Organism
*>::iterator i1
= citizens
.begin();
343 for (int i
= 0; i
< population
; i
++)
345 if ( (*i1
)->get_type() == 0 )
349 else if ( (*i1
)->get_type() == 1)
357 g2_filled_circle( id
, (*i1
)->get_x(), (*i1
)->get_y(), 4 );
362 void World::print_stats( )
364 cout
<<population
<<"\t"<<p_type0
<<"\t"<<p_type1
<<endl
;
367 void World::complete_stats( )
369 double curr_x
,curr_y
;
370 list
<Organism
*>::iterator i1
= citizens
.begin();
371 for (int i
= 0; i
< population
; i
++)
373 curr_x
= (*i1
)->get_x();
374 curr_y
= (*i1
)->get_y();
375 if (curr_x
< 0 || curr_x
> dim_x
|| curr_y
< 0 || curr_y
> dim_y
)
377 cout
<<"out of bounds error..."<<endl
;
383 void World::print_proximity()
385 list
<Organism
*>::iterator i1
= citizens
.begin();
386 cout
<<"PosX\t PosY\t Prox"<<endl
;
389 while (i1
!= citizens
.end())
393 p
= (*i1
)->get_proximity();
394 cout
<<x
<<"\t"<<y
<<"\t"<<p
<<endl
;