merge successful with staging
[biocity.git] / src / World.cpp
blobe409a3c4ce8362232f09a1b58c68414f8c8d2c37
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/>.
18 #include "World.hh"
19 #include "Organism.hh"
20 #include "scenarios.hh"
22 #include <g2.h>
23 #include <g2_X11.h>
25 #include <list>
26 #include <iostream>
27 #include <cmath>
28 #include "circle_square.hh"
29 #include "ConfReader.hh"
30 using std::cout;
31 using std::endl;
32 using std::cerr;
35 //Scenario Defs
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.
42 int Organism::id = 1;
44 World::World( int _psize, double _dx, double _dy )
46 gsl_rng_env_setup();
47 T = gsl_rng_default;
48 rgen = gsl_rng_alloc(T);
50 if (_dx <= 0 || _dy <= 0)
52 cerr<<"Distances must be positive."<<endl;
54 dim_x = _dx;
55 dim_y = _dy;
56 if (_psize < 0 )
58 cerr<<"Number of citizens cannot be negative."<<endl;
60 // setting up the population here
61 population = _psize;
62 p_type0 = 0;
63 p_type1 = 0;
65 int org_type;
66 double initx;
67 double inity;
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 );
81 World::~World( )
83 list<Organism*>::iterator i1 = citizens.begin();
84 for (int i = 0; i < population; i++)
86 if ((*i1)!=NULL) { delete (*i1); }
87 i1++;
90 if (rgen != NULL) { gsl_rng_free( rgen ); }
93 void World::move_next( )
95 int i = 0;
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)
104 p_type0--;
106 i1 = citizens.erase(i1);
107 population--;
109 else
111 (*i1)->lifeup();
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; }
120 currx += rx;
121 curry += ry;
122 p_type0++;
124 citizens.push_front( new Organism( 0, 1, currx, curry ) );
125 population++;
127 (*i1)->set_offspring( 0 );
128 (*i1)->next_state( );
129 i1++;
131 i++;
135 void World::calc_proximity( double _range )
137 list<Organism*>::iterator i1 = citizens.begin( );
138 while (i1 != citizens.end())
140 (*i1)->set_proximity(0);
141 i1++;
144 i1 = citizens.begin();
145 list<Organism*>::iterator i2 = citizens.begin( );
146 i2++;
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);
156 i2++;
158 i1++;
159 i2=i1;
160 i2++;
165 void World::update( )
167 double reproduction = 0.05;
168 double kill_rate = 0.3;
169 double average_lifetime = 100;
171 double range = 50;
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();
180 i2++;
181 int type1,type2;
182 for ( int i = 0; i < population; i++ )
184 (*i1)->lifeup(); //advance in age after each update
186 unif_circle( &rx, &ry, rgen);
187 rx*=2;
188 ry*=2;
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
207 double hunger = 0;
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 )
217 if (type1 == 1)
219 hunger = (*i1)->get_food();
221 else
223 hunger = (*i2)->get_food();
226 kill_prob = gsl_rng_uniform( rgen );
227 if (kill_prob < kill_rate*(1-hunger))
229 if (type1 == 0)
231 (*i1)->set_state( 0 ); //mark for death
232 (*i2)->eat_food();
234 else
236 (*i2)->set_state( 0 ); // " "
237 (*i1)->eat_food();
241 //End Predator-prey interactions
243 i2++;
245 i1++;
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;
254 int cutoff = 20;
255 int curr_pop = population;
256 for ( int i = 0 ; i < curr_pop; i++)
258 int currtype = (*i1)->get_type();
259 int type_dep = 1;
260 int loc_dep = 1;
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; }
281 currx += rx;
282 curry += ry;
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 );
289 population++;
291 i1++;
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
298 // natural causes
299 i1 = citizens.begin( );
300 double death = 0;
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() )
317 case 0:
318 p_type0--;
319 break;
320 case 1:
321 p_type1--;
322 break;
323 default:
324 cout<<"error"<<endl;
325 break;
327 i1 = citizens.erase( i1 ); //increments pointer too!
328 population--;
330 else { i1++; }
332 //END: Grim Reaper Loop
337 void World::print_graph( int id )
339 g2_pen( id, 0);
340 g2_filled_rectangle( id, 0, 0, dim_x, dim_y );
341 g2_pen( id, 1 );
342 list<Organism*>::iterator i1 = citizens.begin();
343 for (int i = 0; i < population; i++)
345 if ( (*i1)->get_type() == 0 )
347 g2_pen( id, 3 );
349 else if ( (*i1)->get_type() == 1)
351 g2_pen( id, 19 );
353 else
355 //do nothing
357 g2_filled_circle( id, (*i1)->get_x(), (*i1)->get_y(), 4 );
358 i1++;
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;
379 i1++;
383 void World::print_proximity()
385 list<Organism*>::iterator i1 = citizens.begin();
386 cout<<"PosX\t PosY\t Prox"<<endl;
387 double x,y;
388 int p;
389 while (i1 != citizens.end())
391 x = (*i1)->get_x();
392 y = (*i1)->get_y();
393 p = (*i1)->get_proximity();
394 cout<<x<<"\t"<<y<<"\t"<<p<<endl;
395 i1++;