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

Last change on this file since 429 was 429, checked in by oriona, 9 years ago

removed duplicated parameters

File size: 17.7 KB
Line 
1expdef:
2name:Reproduction of benthic foraminifera
3info:~
4Genes and parameter values which control reproduction are stored in user1 and user2 fields.
5
6user1:
7genes which are not encoded in Ff genotype:
8min_repro_energy - Minimum energy necessary for reproduction
9hibernation - Defines foram behavior in the case of no nutrients
10
11user2:
12Physiological parameters of foraminifera:
13max_energy_level - maximum energy level reached so far
14gen - generation: 0 haploid, 1 diploid
15species - species: 0 not hibernating 1 hibernating
16hibernated - 0/1 foram isn't/is hibernated
17reproduce - 0/1 foram isn't/is ready for reproduction
18~
19code:~
20
21/*
22changes 2015-06-24:
23- xxx.get(...) changed to xxx[...]
24- xxx.set(...,...) changed to xxx[...]=...
25- function placeRandomlyNotColliding(cr) explicitly called when adding a new creature, and removed collision checking from onForamsBorn() which is also called when "growing" (since "growing" is implemented as creating a new creature in place of the old one, so onForamsBorn() is also called)
26- use creature's center (not the bbox corner) when growing
27- added "S" receptor to visualize the difference between diplo and haplo generations
28- signal.value is a MechPart (a reference) so it does not have to be updated after changing the object location
29*/
30
31global nutrientenergywaiting;
32global reprocounter;
33global colors;
34global chambers;
35global o;
36global max_chamber_energ;
37
38
39@include "foraminifera.inc"
40
41// -------------------------------- experiment begin --------------------------------
42
43function onExpDefLoad()
44{
45        // define genotype and creature groups
46        GenePools.clear();
47        Populations.clear();
48        GenePools[0].name = "Unused";
49
50        var pop = Populations[0];
51        pop.name = "Forams";
52        pop.en_assim = 0;
53        pop.nnsim = 0;
54        pop.enableperf = 1;
55        pop.death = 1;
56        pop.energy = 1;
57        pop.selfmask = 0x10001;
58        pop.othermask = 0x20001;
59        //pop.selfmask = 0x20002; pop.othermask = 0x10002;
60        pop.perfperiod = 25;
61
62        pop = Populations.addGroup("Nutrients");
63        pop.nnsim = 0;
64        pop.enableperf = 0;
65        pop.death = 1;
66        pop.energy = 1;
67        pop.selfmask = 0x20002;
68        pop.othermask = 0x10000;
69        //pop.othermask = 0x10002;
70
71        //world
72        SignalView.mode = 1;
73        ExpParams.world_size = 100;
74        World.wrldwat = ExpParams.world_size;
75        World.wrldsiz = ExpParams.world_size;
76        World.wrldbnd = 1;
77        ExpParams.stress = 1;
78        ExpParams.creath = -0.99; //just above the bottom
79        ExpParams.autorestart = 0;
80
81        //ExpParams.logging = 1; //uncomment to enable logging simulation parameters to log files
82
83        //reproduction
84        ExpParams.foramPop = 3;
85        ExpParams.crossprob = 0.4;
86        ExpParams.mutationprob = 0.2;
87        ExpParams.repro_time = 20;
88        reprocounter = 0;
89
90        //morphology
91        init_chambers();
92        ExpParams.chamber_proculus_haplo = scale(60);
93        ExpParams.chamber_difference_haplo = 0.0;
94        ExpParams.chamber_proculus_diplo = scale(20);
95        ExpParams.chamber_difference_diplo = 0.2;
96        max_chamber_energ = [Vector.new(), Vector.new()];
97        for (var j = 0; j < 2; j++)
98        {
99                for (var i = 0; i < chambers[0].size; i++)
100                {
101                        max_chamber_energ[j].add(((Math.pow(getProperty(j, "chamber_proculus"),3) + Math.pow(getProperty(j, "chamber_proculus") + (i) * getProperty(j, "chamber_difference"),3))*(i+1))/2);
102
103                }                                 
104        }
105        ExpParams.zone1_range = scale(250);
106        ExpParams.zone2_range = scale(5000);
107
108        //energetics
109        ExpParams.min_repro_energ_haplo = max_chamber_energ[0][2];
110        ExpParams.min_repro_energ_diplo = max_chamber_energ[1][8];
111        ExpParams.e_meta = 0.00003 * max_chamber_energ[0][0];
112        ExpParams.energy_hib = 0.00003 * max_chamber_energ[0][0];
113        ExpParams.energy_move = 0.0003 * max_chamber_energ[0][0];
114        ExpParams.energies0_haplo = max_chamber_energ[0][0] - 0.1*max_chamber_energ[0][0];
115        ExpParams.energies0_diplo = max_chamber_energ[1][0] - 0.1*max_chamber_energ[1][0];
116        ExpParams.feedtrans = 0.05;
117        ExpParams.e_repro_cost_haplo = 0.5;
118        ExpParams.e_repro_cost_diplo = 0.3;
119
120        //nutrients
121        ExpParams.nutrientsize = scale(10);
122        ExpParams.energy_nut = 100 * Math.pow(ExpParams.nutrientsize, 3);
123        ExpParams.nutrientPop = 10;
124        ExpParams.feedrate = 0.0025;
125        nutrientenergywaiting = ExpParams.energy_nut;
126        ExpState.totaltestedcr = 0;
127        ExpState.nutrient = "";
128}
129
130@include "standard_placement.inc"
131
132function scale(x)
133{
134        return x*0.025;
135}
136
137function getProperty(gen, prop_id)
138{
139        var ploid = "haplo";
140        if (gen == 1) ploid = "diplo";
141        return ExpParams.[prop_id + "_" + ploid];
142}
143
144function addInitialForam(species, i)
145{
146        var geno = createForamGenotype(0, species, 0);
147        var cr = Populations[0].add(geno);
148        cr.name = "Initial creature" + species + "_" + i;
149        placeCreatureRandomly(cr, 0, 0);
150        cr.energy0 = getProperty(0, "energies0");
151        cr.energy = cr.energy0;
152        setGenotype({"opt" : 0, "cr" : cr, "species" : species});
153}
154
155function onExpInit()
156{
157        Populations[0].clear();
158        Populations[1].clear();
159
160        for (var i = 0; i < ExpParams.foramPop; i++)
161        {
162                addInitialForam(0, i); 
163                addInitialForam(1, i);
164        }
165        o = Populations[0][0].getMechPart(0).orient.clone();
166        ExpState.totaltestedcr = 0;
167        nutrientenergywaiting = ExpParams.energy_nut;
168}
169
170function onExpLoad()
171{
172        for (var pop in Populations)
173                pop.clear();
174
175        Loader.addClass(sim_params.*);
176        Loader.setBreakLabel(Loader.BeforeUnknown, "onExpLoad_Unknown");
177        Loader.run();
178
179        Simulator.print("Loaded " + Populations[0].size + " Forams and " + Populations[1].size + " nutrient objects");
180}
181
182function onExpLoad_Unknown()
183{
184        if (Loader.objectName == "org") // saved by the old expdef
185        {
186                var g = Genotype.newFromString("");
187                Loader.currentObject = g;
188                Interface.makeFrom(g).setAllDefault();
189                Loader.loadObject();
190                var cr = Populations[0].add(g);
191                if (cr != null)
192                {
193                        //cr.rotate(0,0,Math.rnd01*Math.twopi);
194                        if ((typeof(g.user1) == "Vector") && (g.user1.size >= 3))
195                        {
196                                // [x,y,energy]
197                                cr.move(g.user1[0] - cr.center_x, g.user1[1] - cr.center_y, 0);
198                                cr.energy = g.user1[2];
199                        }
200                        else
201                        {
202                                cr.move(Math.rnd01 * World.wrldsiz - cr.center_x, Math.rnd01 * World.wrldsiz - cr.center_y, 0);
203                        }
204                }
205        }
206        else if (Loader.objectName == "Creature")
207        {
208                Loader.currentObject = CreatureSnapshot.new();
209                Loader.loadObject();
210                Populations[0].add(Loader.currentObject);
211        }
212}
213
214function onExpSave()
215{
216        File.writeComment("saved by '%s.expdef'" % Simulator.expdef);
217
218        var tmpvec = [], i;
219
220        for(var cr in Populations[1])
221                tmpvec.add([cr.center_x, cr.center_y, cr.energy]);
222
223        ExpState.nutrient = tmpvec;
224        File.writeObject(sim_params.*);
225        ExpState.nutrient = null; //vectors are only created for saving and then discarded
226
227        for (var cr in Populations[0])
228                File.writeObject(cr);
229}
230
231// -------------------------------- experiment end --------------------------------
232
233// -------------------------------- foram begin -----------------------------------
234
235function onForamsBorn(cr)
236{
237        cr.idleen = ExpParams.e_meta;
238}
239
240function placeRandomlyNotColliding(cr)
241{
242        var retry = 100; //try 100 times
243        while (retry--)
244        {
245                placeCreatureRandomly(cr, 0, 0);
246                if (!cr.boundingBoxCollisions(0))
247                        return cr;
248        }
249
250        Populations[0].delete(cr);
251}
252
253function foramGrow(cr, chamber_num)
254{
255        var geno = createForamGenotype(cr.user2["gen"], cr.user2["species"], chamber_num);
256        var cr2 = Populations[0].add(geno);
257
258        cr2.energy0 = cr.energy;
259        cr2.energy = cr2.energy0;
260
261        setGenotype({"cr" : cr2, "parent_user1" : cr.user1, "parent_user2" : cr.user2, "opt" : 2});
262        cr2.moveAbs(cr.center_x - cr2.size_x / 2, cr.center_y - cr2.size_y / 2, cr.pos_z);
263
264        Populations[0].delete(cr);
265}
266
267function stepToNearest(cr, range)
268{
269        var p = cr.getMechPart(0);
270        var n = cr.signals.receiveSet("nutrient", ExpParams.zone2_range);
271
272        //if signals are received find the source of the nearest
273        if (n.size > 0)
274        {
275                var i;
276                var mp;
277                var distvec = XYZ.new(0, 0, 0);
278                var dist;
279                var mindist = 100000000000;
280                var mindistvec = null;
281
282                for (i = 0; i < n.size; i++)
283                {
284                        mp = n[i].value;
285                        distvec.set(mp.pos);
286                        distvec.sub(p.pos);
287                        dist = distvec.length;
288                        if (dist < mindist)
289                        {
290                                mindist = dist;
291                                mindistvec = distvec.clone();
292                        }
293                }
294
295                mindistvec.normalize();
296                mindistvec.scale(-0.08);
297                cr.localDrive = mindistvec;
298                return 1;
299        }
300       
301        else
302                return 0;
303}
304
305function moveEnergyDec(cr)
306{
307        if (cr.user2["hibernated"] == 1)
308        {
309                cr.energy_m += ExpParams.energy_hib;
310        }
311        else
312        {
313                cr.energy_m += ExpParams.energy_move;
314        }
315}
316
317function foramMove(cr)
318{
319        //TODO moving inside sediment?
320
321        //adjustment in z axis
322        cr.moveAbs(cr.pos_x, cr.pos_y, 0.5);
323
324        //are there any nutrients in zone 1?
325        if (cr.boundingBoxCollisions() == 2)
326        {
327                if (cr.user2["hibernated"] == 1)
328                        cr.user2["hibernated"] = 0;
329                return;
330        }
331
332        else if (cr.user2["hibernated"] == 1)
333        {
334                moveEnergyDec(cr);
335                return;
336        }
337
338        //are there any nutrients in zone 2?
339        else
340        {
341                var moved = stepToNearest(ExpParams.zone2_range); //TODO weighted sum of distance and energy
342                if (moved==1)
343                {
344                        moveEnergyDec(cr);
345                        return;
346                }
347        }
348
349        //no nutrients in zone 2
350
351        var hibernation = 0;
352        if (cr.user2["gen"] == 0) hibernation =  cr.user1["hibernation"];
353        else hibernation =  cr.user1[0]["hibernation"];
354        //hibernation
355        if (hibernation == 1)
356        {
357                moveEnergyDec(cr);
358                cr.user2["hibernated"] = 1;
359                cr.localDrive = XYZ.new(0,0,0);
360        }
361        //random move
362        else
363        {
364                cr.localDrive = (0.1 * Math.rnd01, 0.1 * Math.rnd01, 0);
365                moveEnergyDec(cr);
366        }
367}
368
369function onForamsCollision()
370{
371        if (Collision.Creature1.user2 != null)
372        {
373                Collision.Creature1.localDrive = XYZ.new(0,0,0);
374                var e = Collision.Part2.ing * ExpParams.feedtrans; //TODO efficiency dependent on age
375                //Simulator.print("transferring "+e+" to "+Collision.Creature1.name+" from "+Collision.Creature2.name+" ("+Collision.Creature2.energy+")");
376                Collision.Creature2.energy_m = Collision.Creature2.energy_m + e;
377                Collision.Creature1.energy_p = Collision.Creature1.energy_p + e;
378                Collision.Creature1.user2["hibernated"] = 0;
379        }
380}
381
382function onForamsStep(cr)
383{
384        cr.getMechPart(0).orient.set(o);
385
386        if (deathConditions(cr) == 1)
387        {
388                Populations[0].kill(cr);
389                return;
390        }
391
392        foramMove(cr);
393
394        cr.user2["max_energy_level"] = Math.max(cr.energy, cr.user2["max_energy_level"]);
395        if  (cr.numparts <= chambers[0].size)
396        {
397                if ((cr.user2["max_energy_level"] >= max_chamber_energ[cr.user2["gen"]][cr.numparts-1]))       
398                {
399                        foramGrow(cr, cr.numparts);
400                        return;
401                }       
402        }
403
404        foramReproduce(cr);     
405}
406
407function deathConditions(cr)
408{
409        if ((cr.energy <= ExpParams.e_death_level) || (Math.rnd01 < ExpParams.hunted_prob))
410                return 1;
411        else
412                return 0;
413}
414
415function onForamsDied(cr)
416{
417        //fossilization
418        var geno = GenePools[0].add(cr.genotype);
419        geno.user1 = cr.user1;
420        geno.user2 = cr.user2;
421        if (ExpParams.logging == 1) Simulator.print("\"" + cr.name + "\" died...");
422        ExpState.totaltestedcr++;
423}
424
425// --------------------------------foram end -------------------------------------
426
427// -------------------------------- nutrient begin --------------------------------
428
429function createNutrientGenotype(nutrientsize, zone1_range)
430{
431        return "//0\np:sh=3,sx="+nutrientsize+",sy="+(zone1_range + nutrientsize)+",sz="+(zone1_range+nutrientsize)+",ry=1.5,vr=0.0,1.0,0.0";
432}
433
434function onNutrientsStep(cr)
435{
436        cr.moveAbs(cr.pos_x % ExpParams.world_size, cr.pos_y % ExpParams.world_size, -ExpParams.zone1_range+0.5);
437}
438
439function addNutrient()
440{
441        var cr = Populations[1].add(createNutrientGenotype(ExpParams.nutrientsize, ExpParams.zone1_range));
442
443        cr.name = "Nutrients";
444        cr.idleen = 0;
445        cr.energy0 = ExpParams.energy_nut;
446        cr.energy = cr.energy0;
447        cr.signals.add("nutrient");
448
449        cr.signals[0].value = cr.getMechPart(0);
450
451        placeCreatureRandomly(cr, 0, 0);
452}
453
454function nutrientGrowth()
455{
456        nutrientenergywaiting = nutrientenergywaiting + ExpParams.feedrate;
457        if (nutrientenergywaiting > ExpParams.energy_nut)
458        {
459                for (var i = 0; i < ExpParams.nutrientPop; i++)
460                {
461                        addNutrient();
462                }
463
464                nutrientenergywaiting = 0.0;
465                Simulator.checkpoint();
466        }
467}
468
469// -------------------------------- nutrient end --------------------------------
470
471// -------------------------------- step begin --------------------------------
472
473function onStep()
474{
475        if (ExpParams.logging == 1)
476        {
477                createStatistics();
478        }
479
480        nutrientGrowth();
481
482        //reproduction --------------------------------------------
483        reprocounter += 1;
484        if (reprocounter > ExpParams.repro_time)
485        {
486                reprocounter = 0;
487                reproduce_parents(0);
488                reproduce_parents(1);
489        }
490
491        //check for extinction -----------------------------------------------
492        if (Populations[0].size == 0)
493        {
494                if (ExpParams.autorestart)
495                {
496                        Simulator.print("no more creatures, restarting...");
497                        onExpInit();
498                }
499                else
500                {
501                        Simulator.print("no more creatures, stopped.");
502                        Simulator.stop();
503                }
504        }
505}
506
507function createStatistics()
508{       
509        var number_ploidy = [0, 0];
510        var number_species = [0, 0];
511        var e_inc = [0.0, 0.0];
512        var e_nut = 0.0;
513
514        for (var i = 0; i < Populations[0].size; i++)
515        {
516                var cr = Populations[0].get(i);
517                var gen = cr.user2["gen"];
518                number_ploidy[gen] = number_ploidy[gen] + 1;
519                var species = cr.user2["species"];
520                number_species[species] = number_species[species] + 1;
521                e_inc[gen] = e_inc[gen] + cr.energy;
522        }
523
524        for (var i = 0; i < Populations[1].size; i++)
525        {
526                var cr = Populations[1].get(i);
527                e_nut += cr.energy;
528        }
529
530        var log_numbers = [number_ploidy[0], number_ploidy[1], Populations[1].size];
531        var log_species = [number_species[0], number_species[1]];
532        var log_energy = [e_inc[0], e_inc[1], e_nut];
533
534        log(log_numbers, "log_sizes.txt");
535        log(log_species, "log_species.txt");
536        log(log_energy, "log_energy.txt");
537}
538
539function log(tolog, fname)
540{
541        var f = File.appendDirect(fname, "forams data");
542        f.writeString("" + Simulator.stepNumber);
543        for (var  i = 0; i < tolog.size; i++)
544        {
545                f.writeString(";" + tolog[i]);
546        }
547        f.writeString("\n");
548        f.close();
549}
550
551// -------------------------------- step end --------------------------------
552
553@include "standard_events.inc"
554
555~
556
557prop:
558id:e_repro_cost_haplo
559name:Cost of reproduction
560type:f 0.1 0.9 0.5
561group:Foraminifera
562
563prop:
564id:e_repro_cost_diplo
565name:Cost of reproduction
566type:f 0.1 0.9 0.3
567group:Foraminifera
568
569prop:
570id:chamber_proculus_haplo
571name:Size of proculus
572type:f
573group:Foraminifera
574
575prop:
576id:chamber_proculus_diplo
577name:Size of proculus
578type:f
579group:Foraminifera
580
581prop:
582id:chamber_difference_haplo
583name:Difference in size between subsequent chambers
584type:f
585group:Foraminifera
586
587prop:
588id:chamber_difference_diplo
589name:Difference in size between subsequent chambers
590type:f
591group:Foraminifera
592
593prop:
594id:hunted_prob
595name:Probability of being hunted
596type:f 0 1 0
597group:Forminifera
598
599prop:
600id:zone1_range
601name:Zone 1 range
602type:f 0 200
603group:Foraminifera
604
605prop:
606id:zone2_range
607name:Zone 2 range
608type:f 0 3000
609group:Foraminifera
610
611prop:
612id:colors
613name:Haploid and diploid colors
614type:x
615group:Foraminifera
616
617prop:
618id:min_repro_energ_haplo
619name:Min reproduction energy of forams
620type:f
621group:Foraminifera
622
623prop:
624id:min_repro_energ_diplo
625name:Min reproduction energy of forams
626type:f
627group:Foraminifera
628
629prop:
630id:repro_prob
631name:Probability of reproduction
632type:f 0 1 0.8
633group:Foraminifera
634
635prop:
636id:energies0_haplo
637name:Energy of offspring from diploid forams
638type:f
639group:Foraminifera
640
641prop:
642id:energies0_diplo
643name:Energy of offspring from diploid forams
644type:f
645group:Foraminifera
646
647prop:
648id:energy_hib
649name:Energy used for hibernation during one step
650type:f 0 1 0.001
651group:Foraminifera
652
653prop:
654id:energy_move
655name:Energy used for movement during one step
656type:f 0 20 0.001
657group:Foraminifera
658
659prop:
660id:min_vol
661name:Minimal volume for reproduction
662type:f 100 900 100
663group:Foraminifera
664
665prop:
666id:max_size
667name:Maximal size
668type:d 1 10 5
669group:Foraminifera
670
671prop:
672id:foramPop
673name:Initial forams population size
674type:d 1 1000 100
675group:Foraminifera
676
677prop:
678id:crossprob
679name:Crossover probability
680type:f 0 1 0
681group:Foraminifera
682
683prop:
684id:mutationprob
685name:Mutation probability
686type:f 0 1 0
687group:Foraminifera
688
689prop:
690id:e_death_level
691name:Minimal level of energy to sustain life
692type:f 0 20 0
693group:Foraminifera
694
695prop:
696id:e_meta
697name:Idle metabolism
698type:f 0 1
699group:Energy
700help:Each stick consumes this amount of energy in one time step
701
702prop:
703id:feedrate
704name:Feeding rate
705type:f 0 100
706group:Energy
707help:How fast energy is created in the world
708
709prop:
710id:energy_nut
711name:Nutrient energy
712type:f 0 1000
713group:Energy
714
715prop:
716id:feedtrans
717name:Ingestion multiplier
718type:f 0 100
719group:Energy
720
721prop:
722id:nutrientsize
723name:Nutrient size
724type:f 0.1 0.9 0.1
725group:Energy
726
727prop:
728id:nutrientPop
729name:Nutrient population size
730group:Energy
731type:d 1 1000 10
732
733prop:
734id:world_size
735name:World size
736type:d 10 1000 20
737group:World
738
739prop:
740id:stress
741name:Environmental stress
742type:d 0 1 1
743group:World
744
745prop:
746id:repro_trigger
747name:Reproduction trigger
748type:d 0 1 1
749group:World
750
751prop:
752id:repro_time
753name:Time before reproduction
754type:d 0 1000
755
756prop:
757id:creath
758name:Creation height
759type:f -1 50
760help:~
761Vertical position (above the surface) where new Forams are revived.
762Negative values are only used in the water area:
763  0   = at the surface
764-0.5 = half depth
765-1   = just above the bottom~
766
767state:
768id:nutrient
769name:Nutrient locations
770help:vector of vectors [x,y,energy]
771type:x
772flags:32
773
774prop:
775id:autorestart
776name:Restart after extinction
777help:Restart automatically this experiment after the last creature has died?
778type:d 0 1
779
780state:
781id:notes
782name:Notes
783type:s 1
784help:~
785You can write anything here
786(it will be saved to the experiment file)~
787
788state:
789id:totaltestedcr
790name:Evaluated Forams
791help:Total number of the Forams evaluated in the experiment
792type:d
793flags:16
794
795prop:
796id:logging
797name:Log statistics to file
798type:d 0 1 0
Note: See TracBrowser for help on using the repository browser.