예제 #1
0
        public double eatValue(Protozoa zoa)
        {
            double meat  = zoa.radius * zoa.digestibilityMeat;
            double herb  = zoa.radius * zoa.digestibilityHerb;
            double water = zoa.radius * zoa.digestibilityWater;

            return(meat * digestibilityMeat + herb * digestibilityHerb + water * digestibilityWater);
        }
예제 #2
0
        public void addZoa(Protozoa zoa)
        {
            zoa.id = increment++;
            lock (Protozoas)
                Protozoas.Add(zoa);

            if (OnNewZoa != null)
            {
                OnNewZoa(this, zoa);
            }
        }
예제 #3
0
        public Protozoa gemmate(Random rnd)
        {
            double mutateRate = 0.1;

            if (radius < genome.constructor.radius * (1 + mutateRate) * 3)
            {
                return(null);
            }

            moveVector.setLength(0);

            Genome childGenome = new Genome(rnd, genome, mutateRate, mutateRate);

            double   dx     = rnd.Next(-(int)radius, (int)radius) + radius * Math.Sign(rnd.Next(-1, 0));
            double   dy     = rnd.Next(-(int)radius, (int)radius) + radius * Math.Sign(rnd.Next(-1, 0));
            Protozoa newZoa = new Protozoa(x + dx, y + dy, childGenome, 0);

            radius -= newZoa.radius;

            return(newZoa);
        }
예제 #4
0
        public Protozoa love(Random rnd, Protozoa zz)
        {
            double mutateRate = 0.1;

            Genome childGenome = new Genome(rnd, genome, zz.genome, radius, zz.radius, mutateRate, mutateRate);

            if (radius < childGenome.constructor.radius / 2 || zz.radius < childGenome.constructor.radius / 2)
            {
                return(null);
            }

            moveVector.setLength(0);

            double   dx     = rnd.Next(-(int)radius, (int)radius) + radius * Math.Sign(rnd.Next(-1, 0));
            double   dy     = rnd.Next(-(int)radius, (int)radius) + radius * Math.Sign(rnd.Next(-1, 0));
            Protozoa newZoa = new Protozoa(x + dx, y + dy, childGenome, 0);

            radius    -= newZoa.radius / 2;
            zz.radius -= newZoa.radius / 2;

            return(newZoa);
        }
예제 #5
0
        public static Protozoa generateRandomZoa(Random rnd, int left, int top, int right, int bottom)
        {
            double   x                  = rnd.Next(left, right);
            double   y                  = rnd.Next(top, bottom);
            double   radius             = rnd.Next(7, 15);
            double   accPower           = rnd.Next(30000, 50000);
            double   rotationPower      = rnd.NextDouble() * 1.3;
            double   color              = rnd.NextDouble() * ZoaHSL.scale * 2 - ZoaHSL.scale;
            double   viewDepth          = rnd.Next(15, 50);
            double   viewWidth          = rnd.Next(20, 40);
            double   moveAngle          = (double)rnd.Next(-314, 314) / 100;
            double   moveLength         = rnd.Next(3, 8);
            double   digestibilityMeat  = rnd.NextDouble();
            double   digestibilityHerb  = rnd.NextDouble();
            double   digestibilityWater = rnd.NextDouble();
            Vector   moveVector         = new Vector(moveAngle, moveLength);
            Protozoa zoa                = new Protozoa(rnd, x, y, new Constructor(radius, color, viewDepth, viewWidth, accPower, rotationPower, digestibilityMeat, digestibilityHerb, digestibilityWater));

            zoa.moveVector = moveVector;

            return(zoa);
        }
예제 #6
0
        public void ControlTick(double time)
        {
            notContolledTime = 0;

            lock (Protozoas)
            {
                List <Protozoa> newZoas = new List <Protozoa>();
                //Parallel.ForEach(Protozoas, (zoa) =>
                foreach (Protozoa zoa in Protozoas)
                {
                    //check cooldown
                    zoa.cooldown -= time;

                    //eat under-body food
                    if (zoa.cooldown <= 0)
                    {
                        lock (food)
                        {
                            foreach (Food f in food)
                            {
                                double dist = Vector.GetLength(zoa.centerP, f.point);
                                if (dist < zoa.radius)
                                {
                                    food.Remove(f);
                                    zoa.radius += foodWeight * zoa.eatValue(f);
                                    zoa.makeBusy(eatCooldown);
                                    break;
                                }
                            }
                        }
                    }

                    //change acceleration due to food distribution
                    double
                        meatLeft = 0, meatRight = 0,
                        herbLeft = 0, herbRight = 0,
                        waterLeft = 0, waterRight = 0;
                    lock (food)
                        foreach (Food f in food)
                        {
                            double dist = Vector.GetLength(zoa.centerP, f.point);
                            if (dist > zoa.viewDepth * zoa.radius)
                            {
                                continue;
                            }
                            if (pointInTriangle(f.point, zoa.leftP, zoa.farCenterP, zoa.centerP))
                            {
                                meatLeft  += f.meat / (dist * dist);
                                herbLeft  += f.herb / (dist * dist);
                                waterLeft += f.water / (dist * dist);
                            }
                            else
                            if (pointInTriangle(f.point, zoa.rightP, zoa.farCenterP, zoa.centerP))
                            {
                                meatLeft  += f.meat / (dist * dist);
                                herbLeft  += f.herb / (dist * dist);
                                waterLeft += f.water / (dist * dist);
                            }
                        }
                    double zoasLeft = 0, zoasRight = 0, colorLeft = 0, colorRight = 0;
                    foreach (Protozoa z in Protozoas)
                    {
                        if (z.id != zoa.id)
                        {
                            if (pointInTriangle(z.centerP, zoa.leftP, zoa.farCenterP, zoa.centerP))
                            {
                                double dist  = Vector.GetLength(zoa.centerP, z.centerP);
                                double coeff = 1 / (dist * dist);
                                if (dist == 0)
                                {
                                    coeff = 0;
                                }
                                zoasLeft += coeff * z.radius;
                                colorLeft = (colorLeft + coeff * ((zoa.color - z.color) / ZoaHSL.scale) * z.radius) / 2;
                            }
                            else
                            if (pointInTriangle(z.centerP, zoa.rightP, zoa.farCenterP, zoa.centerP))
                            {
                                double dist  = Vector.GetLength(zoa.centerP, z.centerP);
                                double coeff = 1 / (dist * dist);
                                if (dist == 0)
                                {
                                    coeff = 0;
                                }
                                zoasRight += coeff * z.radius;
                                colorRight = (colorRight + coeff * ((zoa.color - z.color) / ZoaHSL.scale) * z.radius) / 2;
                            }
                        }
                    }

                    double sum      = meatLeft + meatRight + herbLeft + herbRight + waterLeft + waterRight;
                    double sumLeft  = meatLeft + herbLeft + waterLeft;
                    double sumRight = meatRight + herbRight + waterRight;
                    double sumMeat  = meatLeft + meatRight;
                    double sumHerb  = herbLeft + herbRight;
                    double sumWater = waterLeft + waterRight;
                    double noFood   = 0;
                    if (sum == 0)
                    {
                        sum = noFood = 1;
                    }
                    if (sumMeat == 0)
                    {
                        sumMeat = 1;
                    }
                    if (sumHerb == 0)
                    {
                        sumHerb = 1;
                    }
                    if (sumWater == 0)
                    {
                        sumWater = 1;
                    }

                    zoa.moveControl(new double[] {
                        sumLeft / sum,
                        sumRight / sum,
                        meatLeft / sumMeat,
                        meatRight / sumMeat,
                        herbLeft / sumHerb,
                        herbRight / sumHerb,
                        waterLeft / sumWater,
                        waterRight / sumWater,
                        noFood,
                        colorLeft,
                        colorRight
                    }, time);

                    //now collision between zoas
                    if (zoa.cooldown <= 0)
                    {
                        foreach (Protozoa zz in Protozoas)
                        {
                            if (zz.radius != 0 && zoa.radius > zz.radius && zz.id != zoa.id)
                            {
                                double dist = Vector.GetLength(zoa.centerP, zz.centerP);
                                if (dist < zz.radius + zoa.radius)
                                {
                                    double[] input = new double[] {
                                        Math.Abs(zoa.color - zz.color) / ZoaHSL.scale,
                                        optimalRadius / zoa.radius - 1
                                    };
                                    double[] res    = zoa.interactControl(input);
                                    double   toEat  = res[0];
                                    double   toLove = res[1];

                                    if (toLove <= 0 && toEat <= 0)
                                    {
                                        continue;
                                    }

                                    if (toLove > toEat)
                                    {
                                        Protozoa child = zoa.love(rnd, zz);
                                        if (child != null)
                                        {
                                            newZoas.Add(child);
                                            child.makeBusy(interactCooldown);
                                            zoa.makeBusy(interactCooldown);
                                        }
                                    }
                                    else
                                    {
                                        zoa.radius += zoa.eatValue(zz);
                                        zz.radius   = 0;
                                        zoa.makeBusy(eatCooldown);
                                    }
                                }
                            }
                        }
                    }

                    //try to gemmate the Zoa
                    if (gemmating && zoa.cooldown <= 0)
                    {
                        Protozoa newZoa = zoa.gemmate(rnd);
                        if (newZoa != null)
                        {
                            newZoas.Add(newZoa);
                            zoa.makeBusy(interactCooldown);
                        }
                    }
                }//;
                foreach (Protozoa zoa in newZoas)
                {
                    addZoa(zoa);
                }
            }
        }
예제 #7
0
        public void addRandomZoaInArea(Random rnd, int left, int top, int right, int bottom)
        {
            Protozoa zoa = World.generateRandomZoa(rnd, left, top, right, bottom);

            world.addZoa(zoa);
        }