Example #1
0
        public Ant(Dictionary<string, double> template, Random rng, Entity[,] grid, bool guaranteedMutation)
        {
            Statistics.totalNumberOfAnts++;
            if (Statistics.totalNumberOfAnts > Statistics.largestPopulation)
            {
                Statistics.largestPopulation = Statistics.totalNumberOfAnts;
            }

            attributes = new Dictionary<string, double>();

            foreach (KeyValuePair<string, double> kvp in template)
            {
                //  chance of totally random mutation for a given characteristic
                if (rng.NextDouble() <= EXTREME_MUTATION_CHANCE || guaranteedMutation)
                {
                    // old code
                    //attributes[kvp.Key] = (2 * template[kvp.Key]) * (rng.NextDouble() - RANGE_OFFSET) * (template["mutationFactor"]);
                    double range = Statistics.attributeRange[kvp.Key].Y - Statistics.attributeRange[kvp.Key].X;
                    attributes[kvp.Key] = range * rng.NextDouble() + Statistics.attributeRange[kvp.Key].X;
                }
                else
                {
                    attributes[kvp.Key] = template[kvp.Key] + (rng.NextDouble() - RANGE_OFFSET) * template["mutationFactor"] * (Statistics.attributeRange[kvp.Key].Y - Statistics.attributeRange[kvp.Key].X);

                    if (attributes[kvp.Key] > Statistics.attributeRange[kvp.Key].Y)
                    {
                        attributes[kvp.Key] = Statistics.attributeRange[kvp.Key].Y;
                    }
                    else if (attributes[kvp.Key] < Statistics.attributeRange[kvp.Key].X)
                    {
                        attributes[kvp.Key] = Statistics.attributeRange[kvp.Key].X;
                    }
                }

                Statistics.currentSum[kvp.Key] += attributes[kvp.Key];
            }

            isObstacle = true;
            health = DEFAULT_STARTING_HEALTH;

            lastSeen = new int[grid.GetLength(0), grid.GetLength(1)];
            diffusionGrid = new double[grid.GetLength(0), grid.GetLength(1)];
        }
Example #2
0
        //  todo: FIX, broken
        public List<Entity> Neighbors(Entity[,] grid)
        {
            List<Entity> l = new List<Entity>();

            for (int i = -1; i < 2; i += 2)
            {
                for (int j = -1; j < 2; j += 2)
                {
                    int x = (int) position.X + i;
                    int y = (int) position.Y + j;

                    if (x < 0 || x >= grid.GetLength(0) || y < 0 || y >= grid.GetLength(1))
                    {
                        continue;
                    }
                    l.Add(grid[x, y]);
                }
            }
            return l;
        }
Example #3
0
        //  give birth to an ant
        public Ant(Ant dad, Ant mom, Random rng, Entity[,] grid)
        {
            bool foundSpawn = false;
            int xMin = Math.Min((int)dad.position.X, (int)mom.position.X);
            int xMax = Math.Max((int)dad.position.X, (int)mom.position.X);

            int yMin = Math.Min((int)dad.position.Y, (int)mom.position.Y);
            int yMax = Math.Max((int)dad.position.Y, (int)mom.position.Y);
            for (int i = (int)xMin - 1; i < grid.GetLength(0) && i <= xMax + 1 && i >= 0; i++)
            {
                for (int j = (int)yMin - 1; j < grid.GetLength(1) && j <= yMax+1 && j >= 0; j++)
                {
                    if (grid[i, j] == null)
                    {
                        position.X = i;
                        position.Y = j;

                        foundSpawn = true;
                        break;
                    }
                }
                if (foundSpawn) break;
            }

            //  only add it to the grid if you found a proper spot
            if (foundSpawn)
            {
                attributes = new Dictionary<string, double>();

                foreach (KeyValuePair<string, double> kvp in mom.attributes)
                {
                    //  chance of totally random mutation
                    if (rng.NextDouble() <= EXTREME_MUTATION_CHANCE)
                    {
                        double range = Statistics.attributeRange[kvp.Key].Y - Statistics.attributeRange[kvp.Key].X;
                        attributes[kvp.Key] = range * rng.NextDouble() + Statistics.attributeRange[kvp.Key].X;

                        //old code
                        //attributes[kvp.Key] = (dad.attributes[kvp.Key] + mom.attributes[kvp.Key]) * (rng.NextDouble() - RANGE_OFFSET) * (dad.attributes["mutationFactor"] + mom.attributes["mutationFactor"]) / 2.0;
                    }
                    else
                    {
                        attributes[kvp.Key] = (dad.attributes[kvp.Key] + mom.attributes[kvp.Key]) / 2.0
                            + (rng.NextDouble() - RANGE_OFFSET) * ((dad.attributes["mutationFactor"] + mom.attributes["mutationFactor"]) / 2.0) * (Statistics.attributeRange[kvp.Key].Y - Statistics.attributeRange[kvp.Key].X);

                        if (attributes[kvp.Key] > Statistics.attributeRange[kvp.Key].Y)
                        {
                            attributes[kvp.Key] = Statistics.attributeRange[kvp.Key].Y;
                        }
                        else if (attributes[kvp.Key] < Statistics.attributeRange[kvp.Key].X)
                        {
                            attributes[kvp.Key] = Statistics.attributeRange[kvp.Key].X;
                        }
                    }

                    Statistics.currentSum[kvp.Key] += attributes[kvp.Key];
                }

                Statistics.birthEffects.Add(new BirthEffect(mom, dad, this));
                if (Statistics.totalNumberOfAnts > Statistics.largestPopulation)
                {
                    Statistics.largestPopulation = Statistics.totalNumberOfAnts;
                }

                Statistics.totalNumberOfAnts++;
                dad.children.Add(this);
                mom.children.Add(this);

                dad.numChildren++;
                mom.numChildren++;

                if (dad.numChildren > Statistics.largestNumberOfChildren)
                {
                    Statistics.largestNumberOfChildren = dad.numChildren;
                }
                if (mom.numChildren > Statistics.largestNumberOfChildren)
                {
                    Statistics.largestNumberOfChildren = mom.numChildren;
                }

                int generationMax = dad.generation;
                if (mom.generation > generationMax) generationMax = mom.generation;

                this.generation = generationMax + 1;

                if (this.generation > Statistics.longestGenerationLived)
                {
                    Statistics.longestGenerationLived = this.generation;
                }

                grid[(int)position.X, (int)position.Y] = this;

                isObstacle = true;
                diffusionGrid = new double[grid.GetLength(0), grid.GetLength(1)];
                lastSeen = new int[grid.GetLength(0), grid.GetLength(1)];
            }
        }
Example #4
0
        void ProcessVision(Entity[,] grid, double curTime)
        {
            for (int i = 0; i < grid.GetLength(0); i++)
            {
                for (int j = 0; j < grid.GetLength(1); j++)
                {
                    int dist = Math.Abs((int) position.X - i) + Math.Abs((int) position.Y - j);

                    if (dist > attributes["eyesightRange"])
                    {
                        continue;  // don't account for things you cannot see
                    }

                    Entity e = grid[i, j];
                    if (e != null)
                    {
                        if (e is Ant)
                        {
                            ants.Add((Ant)e);
                        }
                        else if (e is Food)
                        {
                            foods.Add((Food)e);
                        }
                    }

                    lastSeen[i, j] = (int)curTime;
                }
            }
        }
Example #5
0
        public void Update(Entity[,] grid, GameTime gameTime, Random rng)
        {
            //  update health every second
            if (gameTime.TotalGameTime.TotalSeconds - timeOfLastUpdate > 1)
            {
                timeOfLastUpdate = gameTime.TotalGameTime.TotalSeconds;
                health -= STANDING_COST;
            }

            int curTime = (int) gameTime.TotalGameTime.TotalSeconds;
            Vector2 newPosition = position;
            foreach (char c in Entity.Directions)
            {
                newPosition = directionTranslate(c);

                //  give birth to ant sometimes
                if (newPosition.Y >= 0 && newPosition.Y < grid.GetLength(1) &&
                        newPosition.X >= 0 && newPosition.X < grid.GetLength(0) &&
                        grid[(int)newPosition.X, (int)newPosition.Y] is Ant)
                {
                    Ant other = (Ant) grid[(int)newPosition.X, (int)newPosition.Y];

                    if (curTime - timeOfLastChild >= attributes["childbirthCooldown"]
                        && curTime - other.timeOfLastChild >= other.attributes["childbirthCooldown"]
                        && curTime - other.timeOfLastChild >= MINIMUM_CHILDBIRTH_TIME
                        && curTime - timeOfLastChild >= MINIMUM_CHILDBIRTH_TIME)
                    {
                        if (rng.NextDouble() <= attributes["childbirthPercentage"] / 100)
                        {
                            Ant child = new Ant(this, other, rng, grid);
                            child.sprite = other.sprite;

                            timeOfLastChild = curTime;
                            other.timeOfLastChild = curTime;

                            //  health of parents go into raising the child
                            child.health = other.attributes["childbirthCost"] + attributes["childbirthCost"];

                            other.health -= 1.5*other.attributes["childbirthCost"];
                            health -= 1.5*attributes["childbirthCost"];
                        }
                    }
                }
            }

            // punish ants for having high eyesight, strength, etc
            health -= attributes["eyesightRange"] * .0001;

            //  death
            if (health <= 0 || moves >= attributes["oldestPossibleAge"])
            {
                //  kill this ant if it has low health
                Die(grid);
            }
        }
Example #6
0
        // NOTE: curTime is in milliseconds
        public override char CreateMovement(Entity[,] grid, double curTime)
        {
            if (curTime - timeOfLastMove < attributes["walkSpeed"])
                return '0'; //  don't move if the time isn't right

            timeOfLastMove = curTime; // update movetime

            ProcessVision(grid, curTime / 1000.0);
            CalculateDiffusion(grid, curTime / 1000.0);

            char dir = '0';
            double max = 0;
            Vector2 newPosition = position;

            foreach (char c in Entity.Directions)
            {
                newPosition = directionTranslate(c);

                //  absorbs a food piece just by being next to it
                if (newPosition.Y >= 0 && newPosition.Y < grid.GetLength(1) &&
                        newPosition.X >= 0 && newPosition.X < grid.GetLength(0) &&
                        grid[(int)newPosition.X, (int)newPosition.Y] is Food)
                {
                    health += ((Food)grid[(int)newPosition.X, (int)newPosition.Y]).Calories();

                    Statistics.foodFades.Add(new FoodFade(newPosition, grid[(int)newPosition.X, (int)newPosition.Y].Sprite()));

                    grid[(int)newPosition.X, (int)newPosition.Y] = null;

                    Statistics.foodEffects.Add(new FoodEffect(this, newPosition));

                    foodsEaten++;
                    Statistics.totalFoods--;

                    if (foodsEaten > Statistics.largestNumberOfFoodsEaten)
                    {
                        Statistics.largestNumberOfFoodsEaten = foodsEaten;
                    }
                }

                //  don't walk onto a position that has an ant
                if (newPosition.Y >= 0 && newPosition.Y < grid.GetLength(1) &&
                    newPosition.X >= 0 && newPosition.X < grid.GetLength(0) &&
                    grid[(int)newPosition.X, (int)newPosition.Y] == null)
                {
                    //  only calculate diffusion for valid locations
                    if (diffusionGrid[(int)newPosition.X, (int)newPosition.Y] > max)
                    {
                        max = diffusionGrid[(int)newPosition.X, (int)newPosition.Y];
                        dir = c;
                    }
                }
            }

            if (dir != '0')
            {
                health -= MOVEMENT_COST;
                moves++;
                Statistics.numberOfMovements++;
                if (moves > Statistics.longestAgeLived)
                {
                    Statistics.longestAgeLived = moves;
                }

                Statistics.timeOfLastMovement = (int)(curTime/1000.0);
                Statistics.systemHasMoved = true;
            }

            lastMove = dir;

            return dir;
        }
Example #7
0
        public double[,] CalculateDiffusion(Entity[,] grid, double curTime)
        {
            for (int i = 0; i < grid.GetLength(0); i++)
            {
                for (int j = 0; j < grid.GetLength(1); j++)
                {
                    Vector2 currentPos = new Vector2(i, j);

                    if (curTime - lastSeen[i, j]
                        >= attributes["timeToReexplore"])
                    {
                        diffusionGrid[i, j] = attributes["desireToExplore"];
                    }
                    else
                    {
                        diffusionGrid[i, j] = 0;
                    }

                    foreach (Food food in foods)
                    {
                        diffusionGrid[i, j]
                            += Score(attributes["desireForFood"]*food.Calories(), food.Position(), currentPos);
                    }
                    foreach (Ant ant in ants)
                    {
                        diffusionGrid[i, j]
                            += Score(attributes["desireToFollowAnts"], ant.Position(), currentPos);

                        if (ant.health >= attributes["healthThreshold"])
                        {
                            if (curTime - timeOfLastChild >= attributes["childbirthCooldown"]
                            && curTime - timeOfLastChild >= MINIMUM_CHILDBIRTH_TIME)
                            {
                                diffusionGrid[i, j]
                                    += Score((attributes["desireToMate"] +
                                    (ant.health - attributes["healthThreshold"])) / (children.Count + 1)
                                    , ant.Position(), currentPos);
                            }
                        }
                    }

                    Vector2 sameDirMove = directionTranslate(lastMove);
                    if (i == sameDirMove.X && j == sameDirMove.Y && lastMove != '0')
                    {
                        //  prevents equal-sum scenarios
                        diffusionGrid[i, j] += attributes["desireToContinueInSameDirection"];
                    }

                    Vector2 backwardsDirMove = directionTranslate(BackwardsDirection(lastMove));
                    if (i == backwardsDirMove.X && j == backwardsDirMove.Y && lastMove != '0')
                    {
                        //  prevents oscillation
                        diffusionGrid[i, j] += attributes["desireToGoBackwards"];
                    }

                }
            }

            return diffusionGrid;
        }