source: experiments/frams/foraminifera/data/scripts/foraminifera.expdef @ 591

Last change on this file since 591 was 591, checked in by Maciej Komosinski, 8 years ago

Added a comment

File size: 32.0 KB
Line 
1expdef:
2name:Reproduction of benthic foraminifera
3info:~
4Basic information about this simulation:
5www.framsticks.com/foraminifera
6
7Technical information:
8Genes and parameter values which control reproduction are stored in data->genes and data->lifeparams fields.
9
10genes:
11genes which are not encoded in Ff genotype:
12min_repro_energy - Minimum energy necessary for reproduction
13hibernation - Defines foram behavior in the case of no nutrients
14
15lifeparams:
16Physiological parameters of foraminifera:
17max_energy_level - maximum energy level reached so far
18gen - generation: 0 haploid, 1 diploid
19species - species: 0 not hibernating 1 hibernating
20hibernated - 0/1 foram is/isn't hibernated
21reproduce - 0/1 foram isn't/is ready for reproduction
22~
23code:~
24
25global colors;
26global curColor;
27global max_chamber_volume;
28global movePerStep;
29global reprocounter;
30global changePeriod;
31global phase;
32global nutrientSqrCm;
33global species_genes;
34global max_chambers_def;
35global foram_uid; //introduced because each replacement of a creature (while growing) would generate a new Creature.uid
36global chamber_vis_denominator;
37global curRadius;
38global nutrient_num_counter;
39global wrldsizSquareMeters;
40
41@include "foraminifera.inc"
42
43// -------------------------------- experiment begin --------------------------------
44
45function onExpDefLoad()
46{
47        // define genotype and creature groups
48        GenePools.clear();
49        Populations.clear();
50        GenePools[0].name = "Unused";
51
52        var pop = Populations[0];
53        pop.name = "Forams";
54        pop.en_assim = 0;
55        pop.nnsim = 0;
56        pop.enableperf = 1;
57        pop.death = 1;
58        pop.energy = 1;
59        pop.selfmask = 0;
60        pop.othermask = 0;
61        //pop.selfmask = 0x20002; pop.othermask = 0x10002;
62        pop.perfperiod = 25;
63        pop.bodysim = 0;
64
65        pop = Populations.addGroup("Nutrients");
66        pop.nnsim = 0;
67        pop.enableperf = 0;
68        pop.death = 1;
69        pop.energy = 1;
70        pop.selfmask = 0;
71        pop.othermask = 0;
72        //pop.othermask = 0x10002;
73        pop.bodysim = 0;
74
75        pop = Populations.addGroup("ReticulopodiaNutrients");
76        pop.nnsim = 0;
77        pop.enableperf = 0;
78        pop.death = 0;
79        pop.energy = 0;
80        pop.selfmask = 0;
81        pop.othermask = 0;
82        pop.bodysim = 0;
83
84        //world
85        SignalView.mode = 1;
86        World.wrldwat = 200;
87        World.wrldsiz = micronsToFrams(100000);
88        wrldsizSquareMeters = Math.pow(framsToMicrons(World.wrldsiz)*0.000001,2);
89        World.wrldbnd = 1;
90
91        //ExpProperties.visualize = 1; //uncomment to visualize reticulopodia and indicate nutrients positions
92
93        //ExpProperties.logging = 1; //uncomment to enable logging simulation parameters to log files   
94        ExpProperties.logPref = "";
95
96        //morphology
97        ExpProperties.zone1_range = micronsToFrams(1000);
98        ExpProperties.zone2_range = micronsToFrams(3000);
99        ExpProperties.chamber_proculus_haplo = micronsToFrams(20);
100        ExpProperties.chamber_proculus_diplo = micronsToFrams(10);
101        colors = ["1.0,1.0,0.3","1.0,0.7,0.0"]; //yellow and orange
102        curColor = colors[0];
103        curRadius = ExpProperties.zone1_range;
104
105        //nutrients
106        ExpProperties.nutrientradius = micronsToFrams(10);
107        ExpProperties.energy_nut = 200 * energyFromVolume(ExpProperties.nutrientradius,1);
108        nutrientSqrCm = 10;
109        ExpProperties.nutrient_pop = Math.pow(framsToMicrons(World.wrldsiz)*0.0001,2)/nutrientSqrCm;
110
111        ExpState.totaltestedcr = 0;
112        ExpState.nutrient = "";
113
114        max_chambers_def = 35;
115        chamber_vis_denominator = 12;
116        //addSpecies({"min_repro_energies" : [4,6]});
117        //addSpecies({"min_repro_energies" : [4,8]});
118       
119        //Simulator.print(create_genotype(0.2, 30, "1.0,1.0,0.0", 0.6)); //sample call
120        //Simulator.print(create_genotype(0.1, 40, "1.0,0.5,0.0", 0.1)); //sample call
121}
122
123@include "standard_placement.inc"
124
125function onExpInit()
126{
127        species_genes = [];
128        foram_uid = 0;
129        movePerStep = getMovePerStep();
130
131        Populations[0].clear();
132        Populations[1].clear();
133        Populations[2].clear(); //reticulopodia and nutrients
134
135        if (ExpProperties.max_chamber_num_haplo == max_chambers_def && ExpProperties.max_chamber_num_diplo == max_chambers_def)
136        {
137                max_chamber_volume = [[30403.5869594578,52812.2546633948,79578.5148482541,113588.815134453,154620.677376218,205094.322220826,262572.712174265,326078.453295303,402342.518962956,498133.985678766,615066.864740109,759500.497626816,937064.025544282,1155915.25563075,1429139.14079748,1762487.92940157,2176286.62046069,2685795.63187845,3316190.12127043,4096436.04462706,5051343.25226193,6231980.1061213,7687880.79524734,9485307.02904958,11716968.9852569,14459866.4934433,17836388.9853663,22004935.7247348,27138607.2546045,33482425.1582986,41336775.1280297,50997910.7842793,62888631.7871037,77563060.9243464,95659468.591964]
138, [3430.07716920763,6159.93090353532,9322.94192815286,13462.9896597283,18399.8550832969,24558.9218126892,31468.8148639192,39189.4977865513,48404.4292075836,60185.8639086061,74490.6048472854,92117.8178412275,113852.779747083,140714.366929552,174450.937643841,215250.242147183,266323.295274072,328858.042352538,406552.379957238,503526.321155323,621060.781025019,767240.824049468,947210.683224091,1169506.19906112,1447211.61255879,1787155.29073739,2205627.64766244,2723413.2837305,3360233.53738709,4147771.02835393,5126445.06973928,6328060.3331703,7805693.278958,9631924.72156452,11884287.1596814]];
139        }
140
141        else
142        {
143                max_chamber_volume = [Vector.new(), Vector.new()];
144                var density = 100;
145                for (var ploid = 0; ploid < 2; ploid++)
146                {
147                        var rad = getPloidRadius(ploid);
148                        for (var cham_num = 0; cham_num < getProperty(ploid,"max_chamber_num"); cham_num++)
149                        {
150                                max_chamber_volume[ploid].add(volumeFromGeno(ploid, rad, cham_num+1, density));
151                        }                                 
152                }
153        }
154
155        if (species_genes.size == 0)
156        {
157                addSpecies({}); //default
158        }
159
160        for (var spec = 0; spec < species_genes.size; spec++)
161        {
162                for (var i = 0; i < ExpProperties.foramPop; i++)
163                {
164                        addInitialForam(spec, i);       
165                }
166        }
167        ExpState.totaltestedcr = 0;
168
169        reprocounter = 0;
170        nutrient_num_counter = 0;
171        changePeriod = 0;
172        phase = "low";
173}
174
175function onExpLoad()
176{
177        for (var pop in Populations)
178                pop.clear();
179
180        Loader.addClass(sim_params.*);
181        Loader.setBreakLabel(Loader.BeforeUnknown, "onExpLoad_Unknown");
182        Loader.run();
183
184        Simulator.print("Loaded " + Populations[0].size + " Forams and " + Populations[1].size + " nutrient objects");
185}
186
187function onExpLoad_Unknown()
188{
189        if (Loader.objectName == "org") // saved by the old expdef
190        {
191                var g = Genotype.newFromString("");
192                Loader.currentObject = g;
193                Interface.makeFrom(g).setAllDefault();
194                Loader.loadObject();
195                var cr = Populations[0].add(g);
196                if (cr != null)
197                {
198                        //cr.rotate(0,0,Math.rnd01*Math.twopi);
199                        if ((typeof(g.data->genes) == "Vector") && (g.data->genes.size >= 3))
200                        {
201                                // [x,y,energy]
202                                cr.move(g.data->genes[0] - cr.center_x, g.data->genes[1] - cr.center_y, 0);
203                                cr.energy = g.data->genes[2];
204                        }
205                        else
206                        {
207                                cr.move(Math.rnd01 * World.wrldsiz - cr.center_x, Math.rnd01 * World.wrldsiz - cr.center_y, 0);
208                        }
209                }
210        }
211        else if (Loader.objectName == "Creature")
212        {
213                Loader.currentObject = CreatureSnapshot.new();
214                Loader.loadObject();
215                Populations[0].add(Loader.currentObject);
216        }
217}
218
219function onExpSave()
220{
221        File.writeComment("saved by '%s.expdef'" % Simulator.expdef);
222
223        var tmpvec = [], i;
224
225        for(var cr in Populations[1])
226                tmpvec.add([cr.center_x, cr.center_y, cr.energy]);
227
228        ExpState.nutrient = tmpvec;
229        File.writeObject(sim_params.*);
230        ExpState.nutrient = null; //vectors are only created for saving and then discarded
231
232        for (var cr in Populations[0])
233                File.writeObject(cr);
234}
235
236// -------------------------------- experiment end --------------------------------
237
238function volumeFromGeno(morphotype, rad, chamber_num, density)
239{
240        var geno = create_genotype(rad, chamber_num, colors[morphotype], 1);
241        var m=Model.newFromString(geno);
242        var mg=ModelGeometry.forModel(m);
243        mg.geom_density=density;
244        var volumeInFrams = mg.volume();
245
246        return volumeInFrams/Math.pow(ExpProperties.scalingFactor,3);
247}
248
249function secToSimSteps(value_in_sec){
250        return value_in_sec/ExpProperties.secPerStep;
251}
252
253function volumeInMicrons(radiusInFrams)
254{
255        return 4.0/3.0*Math.pi*Math.pow(framsToMicrons(radiusInFrams),3);
256}
257
258function energyFromVolume(base, isRadiusInFrams)
259{
260        if (isRadiusInFrams == 1) //radius in frams
261        {
262                return ExpProperties.picoCarbonPerMikro*volumeInMicrons(base);
263        }
264        else //volume in microns
265        {
266                return ExpProperties.picoCarbonPerMikro * base;
267        }
268}
269
270function getMovePerStep()
271{
272        return micronsToFrams((ExpProperties.foramSpeedMmPerMin/60)*1000)*ExpProperties.secPerStep;
273}
274
275function micronsToFrams(micrometers)
276{
277        return micrometers*ExpProperties.scalingFactor;
278}
279
280function framsToMicrons(framsworldunits)
281{
282        return framsworldunits/ExpProperties.scalingFactor;
283}
284
285function getProperty(gen, prop_id)
286{
287        var ploid = "haplo";
288        if (gen == 1) ploid = "diplo";
289        return ExpProperties.[prop_id + "_" + ploid];
290}
291
292function getGene(cr, gen_id, gen_set)
293{
294        if (cr.data->lifeparams->gen == 0)
295                return cr.data->genes[gen_id];
296        else
297                return cr.data->genes[gen_set][gen_id];
298}
299
300function getPloidRadius(ploid)
301{
302        var radius = ExpProperties.chamber_proculus_haplo;
303                if (ploid == 1)
304                {
305                        radius = ExpProperties.chamber_proculus_diplo;
306                }
307        return radius;
308}
309
310function chamberNumFromEnergy(energy, ploid)
311{
312        var chamber_num = max_chamber_volume[ploid].size;
313        for (var i = 0; i < chamber_num; i++)
314        {
315                if (energy < energyFromVolume(max_chamber_volume[ploid][i],0))
316                {
317                        chamber_num = i+1;
318                        break;
319                }       
320        }                                 
321       
322        return chamber_num;
323}
324
325function addForam(species, iter, start_energy, ploid)
326{
327        var chambernum =  chamberNumFromEnergy(start_energy, ploid);
328        var radius = getPloidRadius(ploid);
329        var geno = create_genotype(radius, chambernum, colors[ploid], 1);
330        curColor = colors[ploid];
331        var cr = Populations[0].add(geno);
332        cr.name = "Initial creature" + species + "_" + iter;
333        placeRandomlyNotColliding(cr);
334        cr.energy = start_energy;
335        setGenotype({"opt" : "birth", "cr" : cr, "gen" : ploid, "species" : species, "energy0" : cr.energy, "genes" : species_genes[species], "parentsuids" : ["c0"]});
336        if (ploid == 1)
337        {
338                cr.data->genes = [cr.data->genes, cr.data->genes]; //TODO two different genes sets
339        }
340        moveReticulopodia(cr);
341}
342
343function addInitialForam(species, iter)
344{
345        var ploid = 0;
346        if (Math.rnd01 > 0.5)
347        {
348                ploid = 1;
349        }       
350        //add new foram with random energy bewtween starting energy and reproduction threshold
351        var repro_thr = species_genes[species]->min_repro_energies[ploid];
352        var start_energy = Math.rndUni(energyFromVolume(getPloidRadius(ploid),1),repro_thr-0.25*repro_thr);
353        addForam(species, iter, start_energy,ploid);
354}
355
356//new species can be added as a dictionary with parameter values that are different than default values
357function addSpecies(new_genes)
358{
359        species_genes.add({"min_repro_energies" : [ExpProperties.min_repro_energ_haplo,ExpProperties.min_repro_energ_diplo], "energies0" : [ExpProperties.energies0_haplo, ExpProperties.energies0_diplo], "hibernation" : 0, "morphotype" : 0});
360        for (var i = 0; i < new_genes.size; i++)
361        {
362                var key = new_genes.getKey(i);
363                species_genes[species_genes.size-1][key] = new_genes[key];
364        }
365}
366
367// -------------------------------- foram begin -----------------------------------
368
369function setForamMeta(cr)
370{
371        //percent of current energy
372        cr.idleen = (ExpProperties.e_meta * cr.energy)*ExpProperties.secPerStep;
373}
374
375function lastChamberNum(cr)
376{
377        return cr.numparts;
378}
379
380function getZoneRange(cr, zone_num)
381{
382        return ExpProperties.["zone"+zone_num+"_range"];
383}
384
385function addReticulopodia(cr, radius)
386{
387                if (reticulopodiaExists(cr))
388                {
389                        Populations[2].delete(cr.data->reticulopodiacreature);
390                }
391                var ret = Populations[2].add("//0\nm:Vstyle=reticulopodia\np:sh=1,sx=0.001,sy=0.001,sz=0.001\np:sh=3,sx=0.01,sy="+radius+",sz="+radius+",ry=1.57079633,vr="+curColor+"\nj:0, 1, sh=1");
392                cr.data->reticulopodiacreature = ret;
393                ret.getMechPart(0).orient.set(cr.getMechPart(0).orient);
394                ret.moveAbs(cr.center_x-radius, cr.center_y-radius, cr.center_z-radius);
395}
396
397function onForamsBorn(cr)
398{
399        setForamMeta(cr);
400        if (ExpProperties.visualize == 1)
401        {
402                addReticulopodia(cr, curRadius);
403                moveReticulopodia(cr);
404        }
405}
406
407function placeRandomlyNotColliding(cr)
408{
409        var retry = 100; //try 100 times
410        while (retry--)
411        {
412                placeCreatureRandomly(cr, 0, 0);
413                if (!cr.boundingBoxCollisions(0))
414                {
415                        cr.moveAbs(cr.pos_x, cr.pos_y, -cr.getPart(cr.numparts-1).sx); //place slightly under the bottom surface ("z" value depends on the size of the last=largest chamber)
416                        return cr;
417                }
418        }
419
420        Populations[0].delete(cr);
421}
422
423function reticulopodiaExists(cr)
424{
425        var has_ret = 0;
426
427        if (cr.data->reticulopodiacreature != null)
428        {
429                if (Populations[2].findUID(cr.data->reticulopodiacreature.uid) != null)
430                {
431                        has_ret = 1;
432                }
433        }
434
435        return has_ret;
436}
437
438function visualization(cr)
439{
440        return reticulopodiaExists(cr);
441}
442
443function foramGrow(cr, chamber_num, lastchambergrowth)
444{
445        if ((chamber_num+1) <= max_chamber_volume[cr.data->lifeparams->gen].size)
446        {
447                curColor = colors[cr.data->lifeparams->gen];
448                var ploid = cr.data->lifeparams->gen;
449                var geno = create_genotype(getPloidRadius(ploid), chamber_num+1, colors[ploid], lastchambergrowth);
450                var cr2 = Populations[0].add(geno);
451
452                cr2.energy0 = cr.energy;
453                cr2.energy = cr2.energy0;
454
455                setGenotype({"cr" : cr2, "parent_genes" : cr.data->genes, "parent_lifeparams" : cr.data->lifeparams, "opt" : "growth", "energy0" : cr.energy0});
456                cr2.moveAbs(cr.pos_x, cr.pos_y,cr.pos_z);
457                setForamMeta(cr2);
458
459                if (reticulopodiaExists(cr))
460                {
461                        Populations[2].delete(cr.data->reticulopodiacreature);
462                }
463                Populations[0].delete(cr);
464                return cr2;
465        }
466        return cr;
467}
468
469function visualizeChamberGrowth(cr, chamber_time)
470{
471        var total_time = secToSimSteps(ExpProperties.chamberGrowthSec);
472        var ret_unit = total_time/chamber_vis_denominator;
473        var chamber_unit = total_time-ret_unit;
474
475        if (chamber_time < ret_unit || chamber_time >= chamber_unit)
476        {
477                var new_rad = Math.min(Math.max((chamber_time%ret_unit)/ret_unit*getZoneRange(cr,1),0.01),getZoneRange(cr,1));
478
479                if(chamber_time < ret_unit)
480                {
481                        new_rad = getZoneRange(cr,1)-new_rad;
482                }
483
484                curColor = colors[cr.data->lifeparams->gen];
485                addReticulopodia(cr,new_rad);
486
487                if (chamber_time == 0)//checking for end of chamber growth process
488                {
489                        cr.data->lifeparams->chamber_growth = -1;       
490                }
491        }
492        else
493        {
494                var new_rad = 1 - Math.min(Math.max((chamber_time-ret_unit)/chamber_unit,0.01),1);
495                curRadius = cr.data->reticulopodiacreature.getPart(1).sy;
496                               
497                if (chamber_time == ret_unit)
498                {
499                        new_rad = 1;
500                }
501
502                var new_cr = foramGrow(cr, chamberNumFromEnergy(cr.data->lifeparams->max_energy_level, cr.data->lifeparams->gen)-1, new_rad);
503                curRadius = getZoneRange(new_cr,1);
504        }
505}
506
507function stepToNearest(cr)
508{
509        var p = cr.getMechPart(0);
510        var n = cr.signals.receiveSet("nutrient", getZoneRange(cr,2));
511
512        //if signals are received find the source of the nearest
513        if (n.size > 0)
514        {
515                var i;
516                var mp;
517                var distvec = XYZ.new(0, 0, 0);
518                var dist;
519                var mindist = 100000000000.0;
520                var mindistvec = null;
521                var eating = 0;
522
523                for (i = 0; i < n.size; i++)
524                {
525                        mp = n[i].value.getMechPart(0);
526                        distvec.set(mp.pos);
527                        distvec.sub(p.pos);
528                        dist = distvec.length;
529                        if (dist < getZoneRange(cr,1))
530                        {
531                                if (n[i].value != null)
532                                {
533                                        energyTransfer(cr, n[i].value);
534                                        eating = 1;
535                                }
536                        }
537                        else if (eating == 0 && cr.data->lifeparams->hibernated == 0 && dist < mindist)
538                        {
539                                mindist = dist;
540                                mindistvec = distvec.clone();
541                        }
542                }
543
544                if (!eating && cr.data->lifeparams->hibernated == 0)
545                {
546                        mindistvec.z = 0;
547                        mindistvec.normalize();
548                        mindistvec.scale(-1*movePerStep);
549                        cr.localDrive = mindistvec;
550                        moveEnergyDec(cr);
551                }
552
553                return 1;
554        }
555       
556        else
557        {
558                return 0;
559        }
560}
561
562function moveEnergyDec(cr)
563{
564        if (cr.data->lifeparams->hibernated == 0)
565        {
566                //percent of maximal energy
567                cr.energy -= (ExpProperties.energy_move * cr.data->lifeparams->max_energy_level)*ExpProperties.secPerStep;
568        }
569}
570
571function fence(center, zone)
572{
573        return Math.min(Math.max(0+zone,center),World.wrldsiz-zone); //add and subtract zone from the world size to prevent reticulopodia from crossing the fence
574}
575
576function foramMove(cr)
577{
578        //are there any nutrients in zone 1 or 2?
579        {
580                var moved = stepToNearest(cr); //TODO weighted sum of distance and energy
581                if (moved==1)
582                {
583                        moveReticulopodia(cr);
584                        return;
585                }
586        }
587
588        //Prevents forams from crossing the world border. In the case of touching the border with the reticulopodia direction of the movement should be changed.
589        var change_direction = 0;
590        var new_x = fence(cr.center_x, getZoneRange(cr, 1));
591        var new_y = fence(cr.center_y, getZoneRange(cr, 1));
592
593        if ((new_x != cr.center_x) || (new_y != cr.center_y) || (cr.data->lifeparams->dir_counter >= int(secToSimSteps(ExpProperties.dir_change_sec))))
594        {
595                change_direction = 1;
596                cr.moveAbs(new_x-cr.size_x/2, new_y-cr.size_y/2, -cr.getPart(cr.numparts-1).sx);//place slightly under the bottom surface ("z" value depends on the size of the last=largest chamber)
597        }
598
599        //no nutrients in zone 2
600        if (getGene(cr, "hibernation",0) == 1)
601        {
602                reverseHib(cr);
603                cr.localDrive = XYZ.new(0,0,0);
604        }
605        //random move
606        else if (change_direction == 1)
607        {
608                cr.data->lifeparams->dir = randomDir();
609                cr.data->lifeparams->dir_counter = 0;
610                cr.localDrive = cr.data->lifeparams->dir;
611                moveEnergyDec(cr);
612        }
613        else
614        {
615                cr.localDrive = cr.data->lifeparams->dir;
616        }
617        moveReticulopodia(cr);
618}
619
620function moveReticulopodia(cr)
621{
622        if (visualization(cr))
623        {
624                cr.data->reticulopodiacreature.moveAbs(cr.center_x-getZoneRange(cr,1), cr.center_y-getZoneRange(cr,1), cr.center_z-getZoneRange(cr,1));
625                cr.data->reticulopodiacreature.localDrive = cr.localDrive;
626        }
627}
628
629function randomDir()
630{
631        var dir = (Math.rndUni(-ExpProperties.zone2_range, ExpProperties.zone2_range), Math.rndUni(-ExpProperties.zone2_range, ExpProperties.zone2_range), 0); 
632        dir.normalize();
633        dir.scale(-1*movePerStep);
634        return dir;
635}
636
637function energyTransfer(cr1, cr2)
638{
639        cr1.localDrive = XYZ.new(0,0,0);
640        var e =  ExpProperties.feedtrans*cr1.energy*ExpProperties.secPerStep; //TODO efficiency dependent on age
641        //Simulator.print("transferring "+e +"("+e*ExpProperties.ingestion+")"+" to "+cr1.name +" ("+ cr1.energy+") " +" from "+cr2.uid+" ("+cr2.energy+") "+ e/ExpProperties.secPerStep+ " per sec");
642        var transferred = cr2.transferEnergyTo(cr1, e);
643        cr1.energy -= transferred*(1-ExpProperties.ingestion);
644        if (cr1.data->lifeparams->hibernated == 1)
645        {
646                reverseHib(cr1);
647        }
648}
649
650function reverseHib(cr)
651{
652        if (cr.data->lifeparams->hibernated == 1)
653        {
654                setForamMeta(cr); //unhibernate
655        }
656        else
657        {
658                cr.idleen = (ExpProperties.energy_hib * cr.energy)*ExpProperties.secPerStep; //hibernate
659        }
660        cr.data->lifeparams->hibernated = 1 - cr.data->lifeparams->hibernated;
661}
662
663function onForamsStep(cr)
664{
665        //checking for gametogenesis process
666        if (cr.data->lifeparams->division_time > 0)
667        {
668                cr.data->lifeparams->division_time = Math.max(cr.data->lifeparams->division_time-1,0);
669        }
670        //checking for end of gametogenesis
671        else if (cr.data->lifeparams->division_time == 0)
672        {
673                //waiting for gamets fusion
674        }
675        //checking for chamber growth process
676        else if (cr.data->lifeparams->chamber_growth > 0)
677        {
678                var chamber_time = Math.max(cr.data->lifeparams->chamber_growth-1,0);
679                cr.data->lifeparams->chamber_growth = chamber_time;
680                cr.energy -= ExpProperties.chamberCostPerSec * cr.energy * ExpProperties.secPerStep;
681
682                if (visualization(cr))
683                {
684                        visualizeChamberGrowth(cr, chamber_time);
685                }
686        }
687        //checking for end of the chamber growth process
688        else if (cr.data->lifeparams->chamber_growth == 0 && visualization(cr)==0)
689        {       
690                foramGrow(cr, lastChamberNum(cr), 1);
691                cr.data->lifeparams->chamber_growth = -1;
692                //Simulator.print("chamber "+ (lastChamberNum(cr) + 1) +" complete");
693        }
694        else
695        {
696                //update of metabolism rate
697                if (cr.data->lifeparams->hibernated == 0)
698                {
699                        setForamMeta(cr);
700                }
701
702                if (deathConditions(cr) == 1)
703                {
704                        if (ExpProperties.logging == 1)
705                        {
706                                log(createLogVector(cr, cr.data->lifeparams->max_energy_level),ExpProperties.logPref+"fossil_log.txt");
707                                log(createLogVector(cr, cr.lifespan),ExpProperties.logPref+"lifespan_log.txt");
708                        }                       
709                        Populations[0].kill(cr);
710                        return;
711                }
712
713                //update direction change counter
714                cr.data->lifeparams->dir_counter += 1;
715
716                foramMove(cr);
717
718                var repro = foramReproduce(cr);
719                if (repro == 1)
720                {
721                        return;
722                }
723
724                cr.data->lifeparams->max_energy_level = Math.max(cr.energy, cr.data->lifeparams->max_energy_level);
725
726                //cheking conditions of chamber growth process start
727                if  (lastChamberNum(cr) < max_chamber_volume[cr.data->lifeparams->gen].size)
728                {
729                        if ((cr.data->lifeparams->max_energy_level >= energyFromVolume(max_chamber_volume[cr.data->lifeparams->gen][lastChamberNum(cr)-1],0))) 
730                        {
731                                cr.data->lifeparams->chamber_growth = int(secToSimSteps(ExpProperties.chamberGrowthSec));
732                        }       
733                }
734        }       
735}
736
737function deathConditions(cr)
738{
739        if ((cr.energy <= getProperty(cr.data->lifeparams->gen,"e_death_level")*cr.data->lifeparams->max_energy_level) || (Math.rnd01 < ExpProperties.hunted_prob))
740        {
741                return 1;
742        }
743        else
744                return 0;
745}
746
747function onForamsDied(cr)
748{
749        if (visualization(cr))
750        {
751                Populations[2].delete(cr.data->reticulopodiacreature);
752        }
753        //fossilization
754        var geno = GenePools[0].add(cr.genotype);
755        geno.data->genes = cr.data->genes;
756        geno.data->lifeparams = cr.data->lifeparams;
757        if (ExpProperties.logging == 1) Simulator.print("\"" + cr.name + "\" died...");
758        ExpState.totaltestedcr++;
759}
760
761// --------------------------------foram end -------------------------------------
762
763// -------------------------------- nutrient begin --------------------------------
764
765function createNutrientGenotype(nutrientradius)
766{
767        return "//0\nm:Vstyle=nutrient\np:sh=3,sx="+nutrientradius+",sy="+nutrientradius+",sz="+nutrientradius+",ry=1.57,vr=0.0,1.0,0.0";
768}
769
770function onNutrientsStep(cr)
771{
772        cr.moveAbs(cr.pos_x % World.wrldsiz, cr.pos_y % World.wrldsiz, 0.5);
773}
774
775function addNutrient()
776{
777        var cr = Populations[1].add(createNutrientGenotype(ExpProperties.nutrientradius));
778
779        cr.name = "Nutrients";
780        cr.idleen = 0;
781        cr.energy0 = ExpProperties.energy_nut;
782        cr.energy = cr.energy0;
783        cr.signals.add("nutrient");
784
785        cr.signals[0].value = cr;
786
787        placeCreatureRandomly(cr, 0, 0);
788        if (ExpProperties.visualize == 1)
789        {
790                var nutsize = ExpProperties.nutrientradius*10;
791                var nut = Populations[2].add("//0\nm:Vstyle=nutrient_visual\np:sh=2,sx="+nutsize+",sy="+nutsize+",sz="+nutsize+",ry=1.5,vr=0.0,1.0,0.0");
792                cr.data->reticulopodiacreature = nut;
793                nut.moveAbs( cr.pos_x+cr.size_x/2-nut.size_x/2,  cr.pos_y+cr.size_y/2-nut.size_y/2, -nutsize);
794        }
795}
796
797function onNutrientsDied(cr)
798{
799        if (visualization(cr))
800        {
801                Populations[2].delete(cr.data->reticulopodiacreature);
802        }
803}
804
805function getNumberCounter(counter, increase, unit) //increase counter and then deduct and return an integer number of units
806{
807        counter += increase;
808        var result = int(counter/unit);
809        counter -= result*unit;
810        return {"counter" : counter, "number" : result};
811}
812
813function nutrientGrowth()
814{
815        if (ExpProperties.foodfluxChange > 0)
816        {
817                        changePeriod += 1;
818                        if (phase=="low" && changePeriod >= secToSimSteps(23328000)) //9 months
819                        {
820                                ExpProperties.foodflux = ExpProperties.foodflux/ExpProperties.foodfluxChange;
821                                phase = "high";
822                                changePeriod = 0;
823                        }
824               
825                        else if (phase == "high" && changePeriod >= secToSimSteps(7776000)) //3 months
826                        {
827                                ExpProperties.foodflux = ExpProperties.foodflux*ExpProperties.foodfluxChange;
828                                phase = "low";
829                                changePeriod = 0;
830                        }
831        }
832
833        var nutrientNum = getNumberCounter(nutrient_num_counter, ExpProperties.foodflux*wrldsizSquareMeters*ExpProperties.secPerStep,ExpProperties.energy_nut*0.000000000001);
834
835        nutrient_num_counter = nutrientNum["counter"];
836
837        for (var i = 0; i < nutrientNum["number"]; i++)
838        {   
839                addNutrient();
840        }
841
842        if (ExpProperties.logging == 1 && nutrientNum["number"] > 0)
843        {
844                log([nutrientNum["number"]],ExpProperties.logPref+"nutrients_log.txt");
845        }
846
847}
848
849// -------------------------------- nutrient end --------------------------------
850
851// -------------------------------- step begin --------------------------------
852
853function onStep()
854{
855
856        nutrientGrowth();
857        if (ExpProperties.logging == 1)
858        {
859                createStatistics();
860        }
861
862        //reproduction --------------------------------------------
863        reprocounter += 1;
864        if (reprocounter > secToSimSteps(ExpProperties.reproTimeSec))
865        {
866                reprocounter = 0;
867                for (var s = 0; s < species_genes.size; s++)
868                {
869                        reproduce_parents(s);
870                }
871               
872        }
873
874        //check for extinction -----------------------------------------------
875        if (Populations[0].size == 0)
876        {
877                if (ExpProperties.autorestart)
878                {
879                        Simulator.print("no more creatures, restarting...");
880                        onExpInit();
881                }
882                else
883                {
884                        Simulator.print("no more creatures, stopped.");
885                        Simulator.stop();
886                }
887        }
888        if (ExpProperties.maxSteps > 0)
889        {
890                if (Simulator.stepNumber >= ExpProperties.maxSteps)
891                        Simulator.stop();
892        }
893}
894
895function createStatistics()
896{       
897        var number = [];
898        var e_inc = [];
899        var e_nut = 0.0;
900
901        for (var s = 0; s < species_genes.size; s++)
902        {
903                number.add([0,0]);// [haplo][diplo]
904                e_inc.add([0,0]);
905        }
906
907        for (var i = 0; i < Populations[0].size; i++)
908        {
909                var cr = Populations[0].get(i);
910                var gen = cr.data->lifeparams->gen;
911                var species = cr.data->lifeparams->species;
912
913                number[species][gen] = number[species][gen] + 1;
914                e_inc[species][gen] = e_inc[species][gen] + cr.energy;
915        }
916
917        for (var i = 0; i < Populations[1].size; i++)
918        {
919                var cr = Populations[1].get(i);
920                e_nut += cr.energy;
921        }
922
923        var log_numbers = [];
924        var log_energies = [];
925
926        for (var s = 0; s < species_genes.size; s++)
927        {
928                for (var p = 0; p < 2; p++)
929                {
930                        log_numbers.add(number[s][p]);
931                        log_energies.add(e_inc[s][p]);
932                }
933        }
934       
935        log_numbers.add(Populations[1].size);
936        log_energies.add(e_nut);
937
938        log(log_numbers, ExpProperties.logPref+"forams_log.txt");
939    log(log_energies,  ExpProperties.logPref+"energies_log.txt");
940}
941
942function log(tolog, fname)
943{
944        var f = File.appendDirect(fname, "forams data");
945        f.writeString("" + Simulator.stepNumber);
946        for (var  i = 0; i < tolog.size; i++)
947        {
948                f.writeString(";" + tolog[i]);
949        }
950        f.writeString("\n");
951        f.close();
952}
953
954function createLogVector(cr, value)
955{
956        var vec = Vector.new();
957        for (var i = 0; i < species_genes.size; i++)
958        {
959                for (var j = 0; j < 2; j++)
960                {
961                        vec.add(0);
962                }
963                if (cr.data->lifeparams->species == i)
964                {
965                        vec[i*2+cr.data->lifeparams->gen] = value;             
966                }
967        }
968        return vec;
969}
970
971
972// -------------------------------- step end --------------------------------
973//TODO default params values in frams instead of microns/seconds
974
975@include "standard_events.inc"
976
977~
978
979property:
980id:visualize
981name:Show reticulopodia and nutrients
982type:d 0 1 0
983group:
984
985property:
986id:maxSteps
987name:Maximum number of steps
988type:d 0 10000000 0
989group:
990
991property:
992id:scalingFactor
993name:Scaling factor for micrometers
994type:f 0 -1 0.01
995group:
996
997property:
998id:logging
999name:Log statistics to file
1000type:d 0 1 0
1001group:
1002
1003property:
1004id:logPref
1005name:Log prefix
1006type:s
1007
1008property:
1009id:secPerStep
1010name:Seconds per simulation step
1011help:~
1012Number of seconds of foraminifera time per simulation step.
1013Lower values mean smoother animation.~
1014type:f 1 480 300
1015flags: 16
1016group:
1017
1018property:
1019id:foramSpeedMmPerMin
1020name:Speed of foraminfera in mm/min
1021type:f 0.01 0.1 0.05
1022flags: 16
1023group:Foraminifera
1024
1025property:
1026id:dir_change_sec
1027name:Number of seconds before direction change
1028type:d 300 300000 6000
1029group:Foraminifera
1030
1031property:
1032id:foramPop
1033name:Initial forams population size
1034type:d 1 1000 20
1035group:Foraminifera
1036
1037property:
1038id:gametoPeriodSec
1039name:Time of gametogenesis
1040type:f 300 300000 21600
1041group:Reproduction
1042
1043property:
1044id:gametSuccessRate
1045name:Ratio of successful gamets
1046type:f 0.0001 0.01 0.001
1047group:Reproduction
1048
1049property:
1050id:divisionCost
1051name:Cost of division in pG
1052type:f 15 25 20
1053group:Reproduction
1054
1055property:
1056id:min_repro_energ_haplo
1057name:Min reproduction energy of haploid in pg
1058type:f 0 -1 350000
1059group:Energy
1060
1061property:
1062id:min_repro_energ_diplo
1063name:Min reproduction energy of diploid in pg
1064type:f 0 -1 600000
1065group:Energy
1066
1067property:
1068id:repro_prob
1069name:Probability of reproduction
1070type:f 0 1 0.8
1071group:Reproduction
1072
1073property:
1074id:energies0_haplo
1075name:Energy of offspring from diploid forams
1076type:f 0 -1 20
1077group:Energy
1078
1079property:
1080id:energies0_diplo
1081name:Energy of offspring from diploid forams
1082type:f 0 -1 1.25
1083group:Energy
1084
1085property:
1086id:max_chamber_num_haplo
1087name:Maximum number of haploid chambers
1088type:f 1 50 35
1089group:Energy
1090
1091property:
1092id:max_chamber_num_diplo
1093name:Maximum number of diploid chambers
1094type:f 1 50 35
1095group:Energy
1096
1097property:
1098id:crossprob
1099name:Crossover probability
1100type:f 0 1 0
1101group:Reproduction
1102
1103property:
1104id:mutationprob
1105name:Mutation probability
1106type:f 0 1 0
1107group:Reproduction
1108
1109property:
1110id:reproTimeSec
1111name:Time before reproduction
1112type:d 0 10000 720
1113group:Reproduction
1114
1115property:
1116id:chamberGrowthSec
1117name:Time of the chamber growth in seconds
1118type:f 720 43200 43200
1119group:Foraminifera
1120
1121property:
1122id:chamber_proculus_haplo
1123name:Size of proculus
1124type:f
1125group:Foraminifera
1126
1127property:
1128id:chamber_proculus_diplo
1129name:Size of proculus
1130type:f
1131group:Foraminifera
1132
1133property:
1134id:hunted_prob
1135name:Probability of being hunted
1136type:f 0 1 0
1137group:Foraminifera
1138
1139property:
1140id:zone1_range
1141name:Zone 1 range in frams units
1142type:f 0 200 10
1143group:Foraminifera
1144
1145property:
1146id:zone2_range
1147name:Zone 2 range in frams units
1148type:f 0 3000 30
1149group:Foraminifera
1150
1151property:
1152id:chamberCostPerSec
1153name:Cost of growning chamber per second
1154type:f 0 1 0.000001
1155group:Energy
1156
1157property:
1158id:e_death_level_haplo
1159name:Minimal level of energy to sustain life of haploid
1160type:f 0 1 0.5
1161group:Energy
1162
1163property:
1164id:e_death_level_diplo
1165name:Minimal level of energy to sustain life of diploid
1166type:f 0 1 0.5
1167group:Energy
1168
1169property:
1170id:energy_hib
1171name:Energy used for hibernation during one step
1172type:f 0 1 0.0000001
1173group:Energy
1174
1175property:
1176id:energy_move
1177name:Energy used for movement during one step
1178type:f 0 1 0.0000005
1179group:Energy
1180
1181property:
1182id:e_meta
1183name:Idle metabolism
1184type:f 0 1 0.0000005
1185group:Energy
1186help:Foraminifera consumes this proportion of its energy in one time step
1187
1188property:
1189id:ingestion
1190name:Ingestion rate
1191type:f 0 -1 0.25
1192group:Energy
1193
1194property:
1195id:nutrient_pop
1196name:Nutrient population
1197type:f 0 1000000
1198group:Energy
1199help:How fast energy is created in the world
1200
1201property:
1202id:energy_nut
1203name:Nutrient energy
1204type:f 0 10000000
1205group:Energy
1206
1207property:
1208id:nutrientradius
1209name:Nutrient size
1210type:f 0.001 0.9 0.1
1211group:Energy
1212
1213property:
1214id:picoCarbonPerMikro
1215name:Picograms of carbon in cubic micrometer
1216type:f 0 -1 0.13
1217group:Energy
1218
1219property:
1220id:feedtrans
1221name:Energy transfer per second
1222type:f 0 1 0.001
1223group:Energy
1224
1225property:
1226id:foodflux
1227name:POM flux in grams per second per square meter
1228type:f 0 1 0.0000000075631
1229group:Energy
1230
1231property:
1232id:foodfluxChange
1233name:Set variable feed rate
1234type:f 0 -1 0
1235group:Energy
1236
1237property:
1238id:stress
1239name:Environmental stress
1240type:d 0 1 1
1241group:
1242
1243property:
1244id:repro_trigger
1245name:Reproduction trigger
1246type:d 0 1 1
1247group:Reproduction
1248
1249property:
1250id:creath
1251name:Creation height
1252type:f -1 50 -0.99
1253help:~
1254Vertical position (above the surface) where new Forams are revived.
1255Negative values are only used in the water area:
1256  0   = at the surface
1257-0.5 = half depth
1258-1   = just above the bottom~
1259
1260property:
1261id:autorestart
1262name:Restart after extinction
1263help:Restart automatically this experiment after the last creature has died?
1264type:d 0 1 0
1265
1266state:
1267id:nutrient
1268name:Nutrient locations
1269help:vector of vectors [x,y,energy]
1270type:x
1271flags:32
1272
1273state:
1274id:notes
1275name:Notes
1276type:s 1
1277help:~
1278You can write anything here
1279(it will be saved to the experiment file)~
1280
1281state:
1282id:totaltestedcr
1283name:Evaluated Forams
1284help:Total number of the Forams evaluated in the experiment
1285type:d
1286flags:16
Note: See TracBrowser for help on using the repository browser.