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

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

invalid index error fixed

File size: 13.6 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:
8Vamin - Minimum stored energy necessary for reproduction
9amin - minimal age for reproduction
10
11user2:
12Physiological parameters of foraminifera:
13Va - amount of the stored energy
14gen - generation: 0 haploid, 1 diploid
15~
16code:~
17
18/*
19changes 2015-06-24:
20- xxx.get(...) changed to xxx[...]
21- xxx.set(...,...) changed to xxx[...]=...
22- function placeRandomlyNotColliding(cr) explicitly called when adding a new creature, and removed collision checking from onCreaturesBorn() which is also called when "growing" (since "growing" is implemented as creating a new creature in place of the old one, so onCreaturesBorn() is also called)
23- use creature's center (not the bbox corner) when growing
24- added "S" receptor to visualize the difference between diplo and haplo generations
25- signal.value is a MechPart (a reference) so it does not have to be updated after changing the object location
26*/
27
28global foodenergywaiting;
29global reprocounter;
30
31@include "foraminifera.inc"
32
33// -------------------------------- experiment begin --------------------------------
34
35function onExpDefLoad()
36{
37
38        // define genotype and creature groups
39        GenePools.clear();
40        Populations.clear();
41        GenePools[0].name = "Unused";
42
43        SignalView.mode = 1;
44
45        var pop = Populations[0];
46        pop.name = "Creatures";
47        pop.en_assim = 0;
48        pop.nnsim = 0;
49        pop.enableperf = 1;
50        pop.death = 1;
51        pop.energy = 1;
52        pop.selfmask = 0x10001;
53        pop.othermask = 0x20001;
54        //pop.selfmask = 0x20002; pop.othermask = 0x10002;
55        pop.perfperiod = 25;
56
57        pop = Populations.addGroup("Food");
58        pop.nnsim = 0;
59        pop.enableperf = 0;
60        pop.death = 1;
61        pop.energy = 1;
62        pop.selfmask = 0x20002;
63        pop.othermask = 0x10000;
64
65        //TODO remove unused params
66
67        //radius of the chamber
68        ExpParams.rads = [1.2, 0.6];
69        //ExpParams.rads = [2, 2];
70        //inital genotypes
71        ExpParams.genh = "//0\np:sh=1,sx=" + ExpParams.rads[0] + ",sy=" + ExpParams.rads[0] + ",sz=" + ExpParams.rads[0] + ", rz=3.14159265358979";
72        ExpParams.gend = "//0\np:sh=1,sx=" + ExpParams.rads[1] + ",sy=" + ExpParams.rads[1] + ",sz=" + ExpParams.rads[1] + ", rz=3.14159265358979";
73        ExpParams.gend += "\nn:p=0,d=\"S\"";
74        ExpParams.e_meta = 0.1;
75        ExpParams.feedrate = 0.5;
76        ExpParams.feede0 = 100;
77        ExpParams.feedtrans = 3;
78        ExpParams.creath = -0.99; //just above the bottom
79        ExpParams.foodgen = "//0\np:sh=2,sx=0.1,sy=0.1,sz=0.1\nn:d=T,p=0"; //TODO food size as param
80        ExpParams.autorestart = 0;
81        ExpParams.psize = 10;
82        //ExpParams.logging = 1; //uncomment to enable logging simulation parameters to log files
83
84        //number of offspring
85        ExpParams.ofnumh = 40;
86        ExpParams.ofnumd = 25;
87        //minial volume for reproduction
88        ExpParams.v_min_d = 300;
89        ExpParams.v_min_h = 300;
90        //minimal age for reproduction
91        ExpParams.age_min_d = 100;
92        ExpParams.age_min_h = 100;
93        //crossover probability
94        ExpParams.crossprob = 0.4;
95        //mutation probability
96        ExpParams.mutationprob = 0.2;
97        ExpParams.repro_time = 200;
98        ExpParams.repro_thr = 1;
99
100        //grwoth speed in time steps
101        ExpParams.growth_step = 50; //50
102
103        ExpState.totaltestedcr = 0;
104        ExpState.food = "";
105        foodenergywaiting = ExpParams.feede0;
106        reprocounter = 0;
107
108        ExpParams.wsize = 50;
109        World.wrldwat = 50;
110        World.wrldsiz = ExpParams.wsize;
111        World.wrldbnd = 1;
112}
113
114@include "standard_placement.inc"
115
116function onExpInit()
117{
118        Populations[0].clear();
119        Populations[1].clear();
120
121        for (var i = 0; i < ExpParams.psize; i++)
122        {
123                var cr = Populations[0].add(ExpParams.genh);
124                cr.name = "Initial creature" + i;
125                placeCreatureRandomly(cr, 0, 0);
126                cr.energy0 = ExpParams.v_min_h - ExpParams.repro_thr;
127                cr.energy = cr.energy0;
128                cr.user1 = {"vamin" : ExpParams.v_min_h, "amin": ExpParams.age_min_h};
129                cr.user2 = {"Va" : ExpParams.v_min_h - ExpParams.repro_thr, "gen" : 0, "growth_step" : ExpParams.growth_step, "rsize" : ExpParams.rads[0], "vinit" : ExpParams.v_min_h - ExpParams.repro_thr};
130        }
131        ExpState.totaltestedcr = 0;
132        foodenergywaiting = ExpParams.feede0;
133}
134
135function onExpLoad()
136{
137        for (var pop in Populations)
138                pop.clear();
139
140        Loader.addClass(sim_params.*);
141        Loader.setBreakLabel(Loader.BeforeUnknown, "onExpLoad_Unknown");
142        Loader.run();
143
144        Simulator.print("Loaded " + Populations[0].size + " creatures and " + Populations[1].size + " food objects");
145}
146
147function onExpLoad_Unknown()
148{
149        if (Loader.objectName == "org") // saved by the old expdef
150        {
151                var g = Genotype.newFromString("");
152                Loader.currentObject = g;
153                Interface.makeFrom(g).setAllDefault();
154                Loader.loadObject();
155                var cr = Populations[0].add(g);
156                if (cr != null)
157                {
158                        //cr.rotate(0,0,Math.rnd01*Math.twopi);
159                        if ((typeof(g.user1) == "Vector") && (g.user1.size >= 3))
160                        {
161                                // [x,y,energy]
162                                cr.move(g.user1[0] - cr.center_x, g.user1[1] - cr.center_y, 0);
163                                cr.energy = g.user1[2];
164                        }
165                        else
166                        {
167                                cr.move(Math.rnd01 * World.wrldsiz - cr.center_x, Math.rnd01 * World.wrldsiz - cr.center_y, 0);
168                        }
169                }
170        }
171        else if (Loader.objectName == "Creature")
172        {
173                Loader.currentObject = CreatureSnapshot.new();
174                Loader.loadObject();
175                Populations[0].add(Loader.currentObject);
176        }
177}
178
179function onExpSave()
180{
181        File.writeComment("saved by '%s.expdef'" % Simulator.expdef);
182
183        var tmpvec = [], i;
184
185        for(var cr in Populations[1])
186                tmpvec.add([cr.center_x, cr.center_y, cr.energy]);
187
188        ExpState.food = tmpvec;
189        File.writeObject(sim_params.*);
190        ExpState.food = null; //vectors are only created for saving and then discarded
191
192        for (var cr in Populations[0])
193                File.writeObject(cr);
194}
195
196// -------------------------------- experiment end --------------------------------
197
198// -------------------------------- creature begin --------------------------------
199
200function onCreaturesBorn(cr)
201{
202        cr.idleen = ExpParams.e_meta;
203}
204
205function placeRandomlyNotColliding(cr)
206{
207        var retry = 100; //try 100 times
208        while (retry--)
209        {
210                placeCreatureRandomly(cr, 0, 0);
211                if (!cr.boundingBoxCollisions(0))
212                        return cr;
213        }
214
215        Populations[0].delete(cr);
216}
217
218function readyToRepro(cr)
219{
220        cr.signals.add("repro");
221        cr.signals[0].power = 1;
222}
223
224function onCreaturesStep(cr)
225{
226        //TODO moving inside sediment?
227        cr.moveAbs(cr.pos_x, cr.pos_y, 0); //adjustment in z axis
228        var p = cr.getMechPart(0);
229        var n = cr.signals.receiveSet("food", ExpParams.food_range);
230
231        //if signals are received find the source of the nearest
232        if (n.size > 0)
233        {
234
235                var i;
236                var mp;
237                var distvec = XYZ.new(0, 0, 0);
238                var dist;
239                var mindist = 100000000000;
240                var mindistvec = null;
241
242                for (i = 0; i < n.size; i++)
243                {
244                        mp = n[i].value;
245                        distvec.set(mp.pos);
246                        distvec.sub(p.pos);
247                        dist = distvec.length;
248                        if (dist < mindist)
249                        {
250                                mindist = dist;
251                                mindistvec = distvec.clone();
252                        }
253                }
254
255                mindistvec.normalize();
256                mindistvec.scale(-0.08);
257                cr.localDrive = mindistvec;
258        }
259
260        else
261        {
262                cr.localDrive = (0.1 * Math.rnd01, 0.1 * Math.rnd01, 0);
263        }
264
265        //energy costs depend on size
266        if (cr.energy > 100)
267        {
268                //TODO energy costs dependent on size
269                // cr.energy_m = cr.user2["Va"]/cr.user2["vinit"];
270        }
271
272        if (cr.lifespan >= ExpParams.max_age)
273        {
274                //TODO what is max age value? should there be one?
275                Populations[0].kill(cr);
276                return;
277        }
278
279        //foram growth
280        if (cr.lifespan == cr.user2["growth_step"])
281        {
282                //TODO how size is related to the energy?
283                cr.user2["rsize"] = ExpParams.rads[cr.user2["gen"]] * Math.min(Math.max(float(cr.user2["Va"] / cr.user2["vinit"]) * 0.5, 1.0), 2.5);
284                var geno = "//0\np:sh=1,sx=" + cr.user2["rsize"] + ",sy=" + cr.user2["rsize"] + ",sz=" + cr.user2["rsize"] + ", rz=3.14159265358979";
285                if (cr.user2["gen"] == 1)
286                {
287                        geno += "\nn:p=0,d=\"S\""; //TODO why initial genotypes are not used as defined in ExpParams?
288                        //TODO maybe it would be nice if they rotated so the "S" would show where they are going (direction/intention)
289                }
290                var cr2 = Populations[0].add(geno);
291                cr2.energy = cr.energy;
292                setGenotype(cr2, cr.user1, cr.user2);
293                cr2.moveAbs(cr.center_x - cr2.size_x / 2, cr.center_y - cr2.size_y / 2, cr.pos_z);
294
295                Populations[0].delete(cr);
296        }
297        else
298        {
299                var properSize = 0;
300
301                if (cr.user2["gen"] == 0)
302                {
303                        properSize = cr.user2["Va"] >= cr.user1["vamin"];
304                }
305                else
306                {
307                        properSize = cr.user2["Va"] >= cr.user1[0]["vamin"]; //TODO gene selection
308                }
309
310                //if creature has proper age and cytoplasm amount
311                if ( properSize )
312                {
313                        //reproduce with probability repro_prob
314                        if (Math.rnd01 <= ExpParams.repro_prob)
315                        {
316                                readyToRepro(cr);
317                        }
318                }
319                if ( properSize && (cr.signals.receive("repro") > 0))
320                {
321                        readyToRepro(cr);
322                }
323        }
324}
325
326function onCreaturesDied(cr)
327{
328        //fossilization
329        var geno = GenePools[0].add(cr.genotype);
330        geno.user1 = cr.user1;
331        geno.user2 = cr.user2;
332        if (ExpParams.logging == 1) Simulator.print("\"" + cr.name + "\" died...");
333        ExpState.totaltestedcr++;
334}
335
336function setGenotype(cr, new_user1, new_user2)
337{
338        cr.user2 = {"Va" : new_user2["Va"], "gen" : new_user2["gen"], "growth_step" : new_user2["growth_step"], "rsize" : new_user2["rsize"], "vinit": new_user2["vinit"]};
339        if (cr.user2["gen"] == 0)
340        {
341                cr.user1 = {"vamin" : new_user1["vamin"], "amin": new_user1["amin"] };
342        }
343        else if (cr.user2["gen"] == 1)
344        {
345                cr.user1 = [ {"vamin" : new_user1[0]["vamin"], "amin": new_user1[0]["amin"] }, {"vamin" : new_user1[1]["vamin"], "amin": new_user1[1]["amin"] }];
346        }
347
348}
349
350// -------------------------------- creature end --------------------------------
351
352// -------------------------------- food begin --------------------------------
353
354function onFoodStep(cr)
355{
356        cr.moveAbs(cr.pos_x % ExpParams.wsize, cr.pos_y % ExpParams.wsize, 0.5);
357}
358
359function addfood()
360{
361        var cr = Populations[1].add(ExpParams.foodgen);
362
363        cr.name = "Food";
364        cr.idleen = 0;
365        cr.energy0 = ExpParams.feede0;
366        cr.energy = cr.energy0;
367        cr.signals.add("food");
368
369        cr.signals[0].value = cr.getMechPart(0);
370
371        placeRandomlyNotColliding(cr);
372}
373
374function onFoodCollision()
375{
376        if (Collision.Creature2.user2 != null)
377        {
378                var e = Collision.Part2.ing * ExpParams.feedtrans;
379                //Simulator.print("transferring "+e+" from "+Collision.Creature1.name+" to "+Collision.Creature2.name+" ("+Collision.Creature2.energy+")");
380                Collision.Creature1.energy_m = Collision.Creature1.energy_m + e;
381                Collision.Creature2.energy_p = Collision.Creature2.energy_p + e;
382                Collision.Creature2.user2["Va"] = float(Collision.Creature2.user2["Va"]) + float(e);
383        }
384}
385
386// -------------------------------- food end --------------------------------
387
388
389function log(tolog, fname)
390{
391        var f = File.appendDirect(fname, "forams data");
392        f.writeString("" + Simulator.stepNumber);
393        for (var  i = 0; i < tolog.size; i++)
394        {
395                f.writeString(";" + tolog[i]);
396        }
397        f.writeString("\n");
398        f.close();
399}
400
401
402
403
404@include "standard_events.inc"
405
406~
407
408prop:
409id:max_age
410name:Maximal age
411type:d 100 1000 500
412
413prop:
414id:wsize
415name:World size
416type:d 10 1000 20
417
418prop:
419id:growth_step
420name:Growth step
421type:d -1 10000 1000
422
423prop:
424id:rads
425name:Haploid and diploid radius
426type:x
427
428prop:
429id:age_min_h
430name:Min reproduction age of haploid forams
431type:d 100 10000 300
432group:Foraminifera
433
434prop:
435id:age_min_d
436name:Min reproduction age of diploid forams
437type:d 100 10000 200
438group:Foraminifera
439
440prop:
441id:v_min_h
442name:Min reproduction energy of haploid forams
443type:f 10 10000 300
444group:Foraminifera
445
446prop:
447id:v_min_d
448name:Min reproduction energy of diploid forams
449type:f 10 10000 150
450group:Foraminifera
451
452prop:
453id:repro_thr
454name:Energy creatures need to gather to reproduce
455type:d 1 1000 1
456
457prop:
458id:food_range
459name:Range of food smell
460type:d 0 10000 10000
461
462prop:
463id:repro_time
464name:Time before reproduction
465type:d 0 1000
466
467prop:
468id:psize
469name:Initial population size
470type:d 1 1000 100
471
472prop:
473id:logging
474name:Log statistics to file
475type:d 0 1 0
476
477prop:
478id:ofnumh
479name:Number of offspring from haploid forams
480type:d
481group:Foraminifera
482
483prop:
484id:ofnumd
485name:Number of offspring from diploid forams
486type:d
487group:Foraminifera
488
489prop:
490id:repro_prob
491name:Probability of reproduction
492type:f 0 1 0.9
493
494prop:
495id:crossprob
496name:Crossover probability
497type:f 0 1 0
498
499prop:
500id:mutationprob
501name:Mutation probability
502type:f 0 1 0
503
504prop:
505id:genh
506name:Initial genotype of haploid forams
507type:s 1
508group:Foraminifera
509
510prop:
511id:gend
512name:Initial genotype of diploid forams
513type:s 1
514group:Foraminifera
515
516prop:
517id:creath
518name:Creation height
519type:f -1 50
520help:~
521Vertical position (above the surface) where new creatures are revived.
522Negative values are only used in the water area:
523  0   = at the surface
524-0.5 = half depth
525-1   = just above the bottom~
526
527prop:
528id:e_meta
529name:Idle metabolism
530type:f 0 1
531group:Energy
532help:Each stick consumes this amount of energy in one time step
533
534prop:
535id:feedrate
536name:Feeding rate
537type:f 0 100
538group:Energy
539help:How fast energy is created in the world
540
541prop:
542id:feede0
543name:Food's energy
544group:Energy
545type:f 0 1000
546
547prop:
548id:feedtrans
549name:Ingestion multiplier
550group:Energy
551type:f 0 100
552
553prop:
554id:foodgen
555name:Food's genotype
556group:Energy
557type:s 1
558
559prop:
560id:autorestart
561name:Restart after extinction
562help:Restart automatically this experiment after the last creature has died?
563type:d 0 1
564
565state:
566id:notes
567name:Notes
568type:s 1
569help:~
570You can write anything here
571(it will be saved to the experiment file)~
572
573state:
574id:totaltestedcr
575name:Evaluated creatures
576help:Total number of the creatures evaluated in the experiment
577type:d
578flags:16
579
580prop:
581id:foodPop
582name:Food size
583type:d 1 1000 10
584
585state:
586id:food
587name:Food locations
588help:vector of vectors [x,y,energy]
589type:x
590flags:32
Note: See TracBrowser for help on using the repository browser.