// todo: keep track of the last generation of ants that were alive... then average out // all of their characteristics at the end, and analyze the difference between // the starting 10 ants and the last generation of ants // todo: implement DISEASE factor; it's a green spot that when stepped on produces disease // that wears down an ant's health. it can be passed on randomly to adjacent ants // and it becomes more severe with time until the ants die. protected override void Initialize() { debugMessage = ""; lastFoodSpawnTime = 0; //seeded by time rng = new Random((int)DateTime.Now.Ticks); // TODO: store generations in an array in Statistics // TODO: represent ants that are dead with a new icon foodSpawnInterval = 10; // how many seconds before food should respawn GRID_WIDTH = (3 * ((int)(7 * (rng.NextDouble() * .7 + .3)))); GRID_HEIGHT = (int)((2f / 3f) * GRID_WIDTH); STARTING_ANTS = (int)((rng.NextDouble() * .15) * GRID_WIDTH * GRID_HEIGHT) + 2; if (STARTING_ANTS > 20) { STARTING_ANTS = 20; } numberOfFoodsSpawned = (int)((rng.NextDouble() * .10) * GRID_WIDTH * GRID_HEIGHT) + 1; // how many foods made Statistics.EXTREME_MUTATION_CHANCE = rng.NextDouble() * .5; Statistics.runTimeInSeconds = 0; LINE_THICKNESS = 0; gameState = Statistics.GameState.ANTS_SCREEN; secondsCounter = 30.0; cursor = new SpriteSheet(Content.Load <Texture2D>("cursorSheet"), 50, 50); cursor.SetScale(TILE_WIDTH, TILE_HEIGHT); Statistics.birthEffects = new List <BirthEffect>(); Statistics.foodEffects = new List <FoodEffect>(); Statistics.foodFades = new List <FoodFade>(); numberOfSecondsBeforeRoundEnds = 100; // TODO: remember to check that ALL statistics.attributes are refreshed // TODO: have a Dictionary that returns a list of ants associated with a particular generation number Statistics.numberOfMovements = 0; Statistics.longestAgeLived = 0; Statistics.largestNumberOfChildren = 0; Statistics.largestNumberOfFoodsEaten = 0; Statistics.topFiveAncestors = new List <Ant>(); Statistics.largestPopulation = 0; Statistics.longestGenerationLived = 0; Statistics.timeOfLastMovement = 0; Statistics.systemHasMoved = false; Statistics.totalFoods = 0; Statistics.totalNumberOfAnts = 0; grid = new Entity[GRID_WIDTH, GRID_HEIGHT]; SIDE_PANEL_WIDTH = (int)(graphics.GraphicsDevice.Viewport.Width * .2f); SCREEN_WIDTH = graphics.GraphicsDevice.Viewport.Width - SIDE_PANEL_WIDTH; SCREEN_HEIGHT = graphics.GraphicsDevice.Viewport.Height; TILE_WIDTH = SCREEN_WIDTH / GRID_WIDTH; TILE_HEIGHT = SCREEN_HEIGHT / GRID_HEIGHT; attributes = new Dictionary <string, double>(); Statistics.attributeRange = new Dictionary <string, Vector2>(); attributeRange = Statistics.attributeRange; Statistics.firstAverages = new Dictionary <string, double>(); Statistics.currentSum = new Dictionary <string, double>(); attributes["redColor"] = 100; //RGB color scheme attributeRange["redColor"] = new Vector2(0, 255); attributes["blueColor"] = 50; attributeRange["blueColor"] = new Vector2(0, 255); attributes["greenColor"] = 70; attributeRange["greenColor"] = new Vector2(0, 255); attributes["mutationFactor"] = .2; attributeRange["mutationFactor"] = new Vector2(0, 1); attributes["walkSpeed"] = 1000.0; // how many milliseconds it takes to move a single step attributeRange["walkSpeed"] = new Vector2(100, 2000); attributes["desireForFood"] = 100.0; // how much this ant prioritizes collecting food attributeRange["desireForFood"] = new Vector2(-4000, 4000); attributes["desireToFollowAnts"] = 10.0; // how much this ant is willing to follow/avoid ants attributeRange["desireToFollowAnts"] = new Vector2(-300, 300); attributes["desireToExplore"] = 1.0; // how much this ant is willing to explore new places attributeRange["desireToExplore"] = new Vector2(-200, 200); attributes["desireToMate"] = 500.0; // influenced by number of children attributeRange["desireToMate"] = new Vector2(-600, 600); attributes["desireToContinueInSameDirection"] = 1500.0; // prevents equal-sum scenarios attributeRange["desireToContinueInSameDirection"] = new Vector2(-2000, 2000); attributes["desireToGoBackwards"] = -1000.0; // prevents oscillation attributeRange["desireToGoBackwards"] = new Vector2(-1500, 1500); attributes["timeToReexplore"] = 10.0; // how long (seconds) an ant remembers a spot attributeRange["timeToReexplore"] = new Vector2(1, 30); attributes["decayFactor"] = 4.0; // analogous to the ant's sense of smell attributeRange["decayFactor"] = new Vector2(1, 8); attributes["healthThreshold"] = 200.0; // if another ant meets this health threshold, // then the two will mate and produce offspring attributeRange["healthThreshold"] = new Vector2(1, 400); attributes["childbirthPercentage"] = 21.0; // % chance of having child when threshold met attributeRange["childbirthPercentage"] = new Vector2(1, 100); attributes["childbirthCost"] = 50.0; // how much the parent pays to raise child attributeRange["childbirthCost"] = new Vector2(1, 300); attributes["childbirthCooldown"] = 10.0; // how many seconds before having a child again attributeRange["childbirthCooldown"] = new Vector2(5, 30); //attributes["health"] = 150.0; // health is restored by eating food, // and it is lowered by moving around and taking damage //attributeRange["health"] = new Vector2(0, 300); //attributes["strength"] = 10.0; // TODO: damage dealt in a hit to a predator. influences // construction of buildings, too attributes["oldestPossibleAge"] = 200.0; // number of moves this ant can make before dying attributeRange["oldestPossibleAge"] = new Vector2(30, 400); attributes["eyesightRange"] = 100.0; // number of tiles this ant can see attributeRange["eyesightRange"] = new Vector2(3, 150); //attributes["resistance"] = 5.0; // TODO: immunity to cold, poison, and disease // also, social model vs individualistic model. social model is a shared diffusion. //attributes["shelterShape"] = 22.0; // TODO: this number gets rounded down when used in calculation. // base-2 representation of the truncated version is // used. each digit represents having or not having // a block in a certain location in a 5x5 grid. // digit ordering as follows: (1 = first digit's block location) // and alphabetical chars correspond to numbers beyond 9 // 22 = 10110(b2) = _ // _| shape /* PLDEM * KC56F * B4127 * JA38G * OI9HN */ line = new Texture2D(graphics.GraphicsDevice, 1, 1); line.SetData(new Color[] { Color.White }); base.Initialize(); }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); KeyboardState keyboardState = Keyboard.GetState(); if (keyboardState.IsKeyDown(Keys.Escape)) { Exit(); } else if (keyboardState.IsKeyDown(Keys.Space)) { Statistics.totalNumberOfAnts = 0; } if (gameState == Statistics.GameState.ANTS_SCREEN) { numberOfSecondsBeforeRoundEnds -= gameTime.ElapsedGameTime.TotalMilliseconds / 1000.0; Statistics.runTimeInSeconds += gameTime.ElapsedGameTime.TotalMilliseconds / 1000.0; if (lastFoodSpawnTime == 0 || gameTime.TotalGameTime.TotalSeconds - lastFoodSpawnTime >= foodSpawnInterval) { for (int i = 0; i < numberOfFoodsSpawned; i++) { Vector2 pos = new Vector2((int)rng.Next(GRID_WIDTH), (int)rng.Next(GRID_HEIGHT)); // don't spawn food on top of other ants or foods if (grid[(int)pos.X, (int)pos.Y] == null) { grid[(int)pos.X, (int)pos.Y] = new Food(rng); grid[(int)pos.X, (int)pos.Y].SetPosition(pos); grid[(int)pos.X, (int)pos.Y].SetSprite(foodSprite); Statistics.totalFoods++; } } lastFoodSpawnTime = gameTime.TotalGameTime.TotalSeconds; } foreach (Entity e in grid) { if (e is Ant) { ((Ant)e).Update(grid, gameTime, rng); // note: update will null an ant that is dead } if (e != null) { char move = e.CreateMovement(grid, gameTime.TotalGameTime.TotalMilliseconds); MoveInDirection(e, move); } } if (Statistics.totalNumberOfAnts == 0 || (Math.Abs(gameTime.TotalGameTime.TotalSeconds - Statistics.timeOfLastMovement) > 30 && Statistics.systemHasMoved)) { // if there have been 30 seconds w/o movement, then end gameState = Statistics.GameState.STATISTICS_SCREEN; } } base.Update(gameTime); }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) { this.Exit(); } KeyboardState keyboardState = Keyboard.GetState(); if (keyboardState.IsKeyDown(Keys.Escape)) { Exit(); } else if (keyboardState.IsKeyDown(Keys.Space)) { Statistics.totalNumberOfAnts = 0; } if (gameState == Statistics.GameState.ANTS_SCREEN) { numberOfSecondsBeforeRoundEnds -= gameTime.ElapsedGameTime.TotalMilliseconds / 1000.0; Statistics.runTimeInSeconds += gameTime.ElapsedGameTime.TotalMilliseconds / 1000.0; if (lastFoodSpawnTime == 0 || gameTime.TotalGameTime.TotalSeconds - lastFoodSpawnTime >= foodSpawnInterval) { for (int i = 0; i < numberOfFoodsSpawned; i++) { Vector2 pos = new Vector2((int)rng.Next(GRID_WIDTH), (int)rng.Next(GRID_HEIGHT)); // don't spawn food on top of other ants or foods if (grid[(int)pos.X, (int)pos.Y] == null) { grid[(int)pos.X, (int)pos.Y] = new Food(rng); grid[(int)pos.X, (int)pos.Y].SetPosition(pos); grid[(int)pos.X, (int)pos.Y].SetSprite(foodSprite); Statistics.totalFoods++; } } lastFoodSpawnTime = gameTime.TotalGameTime.TotalSeconds; } foreach (Entity e in grid) { if (e is Ant) { ((Ant)e).Update(grid, gameTime, rng); // note: update will null an ant that is dead } if (e != null) { char move = e.CreateMovement(grid, gameTime.TotalGameTime.TotalMilliseconds); MoveInDirection(e, move); } } if (Statistics.totalNumberOfAnts == 0 || (Math.Abs(gameTime.TotalGameTime.TotalSeconds - Statistics.timeOfLastMovement) > 30 && Statistics.systemHasMoved)) { // if there have been 30 seconds w/o movement, then end gameState = Statistics.GameState.STATISTICS_SCREEN; } } base.Update(gameTime); }
// todo: keep track of the last generation of ants that were alive... then average out // all of their characteristics at the end, and analyze the difference between // the starting 10 ants and the last generation of ants // todo: implement DISEASE factor; it's a green spot that when stepped on produces disease // that wears down an ant's health. it can be passed on randomly to adjacent ants // and it becomes more severe with time until the ants die. protected override void Initialize() { debugMessage = ""; lastFoodSpawnTime = 0; //seeded by time rng = new Random((int)DateTime.Now.Ticks); // TODO: store generations in an array in Statistics // TODO: represent ants that are dead with a new icon foodSpawnInterval = 10; // how many seconds before food should respawn GRID_WIDTH = (3 * ((int) (7* (rng.NextDouble() * .7 + .3)))); GRID_HEIGHT = (int)((2f/3f)*GRID_WIDTH); STARTING_ANTS = (int)((rng.NextDouble()*.15)*GRID_WIDTH*GRID_HEIGHT) + 2; if (STARTING_ANTS > 20) STARTING_ANTS = 20; numberOfFoodsSpawned = (int)((rng.NextDouble()*.10)*GRID_WIDTH*GRID_HEIGHT)+1; // how many foods made Statistics.EXTREME_MUTATION_CHANCE = rng.NextDouble() * .5; Statistics.runTimeInSeconds = 0; LINE_THICKNESS = 0; gameState = Statistics.GameState.ANTS_SCREEN; secondsCounter = 30.0; cursor = new SpriteSheet(Content.Load<Texture2D>("cursorSheet"), 50, 50); cursor.SetScale(TILE_WIDTH, TILE_HEIGHT); Statistics.birthEffects = new List<BirthEffect>(); Statistics.foodEffects = new List<FoodEffect>(); Statistics.foodFades = new List<FoodFade>(); numberOfSecondsBeforeRoundEnds = 100; // TODO: remember to check that ALL statistics.attributes are refreshed // TODO: have a Dictionary that returns a list of ants associated with a particular generation number Statistics.numberOfMovements = 0; Statistics.longestAgeLived = 0; Statistics.largestNumberOfChildren = 0; Statistics.largestNumberOfFoodsEaten = 0; Statistics.topFiveAncestors = new List<Ant>(); Statistics.largestPopulation = 0; Statistics.longestGenerationLived = 0; Statistics.timeOfLastMovement = 0; Statistics.systemHasMoved = false; Statistics.totalFoods = 0; Statistics.totalNumberOfAnts = 0; grid = new Entity[GRID_WIDTH, GRID_HEIGHT]; SIDE_PANEL_WIDTH = (int) (graphics.GraphicsDevice.Viewport.Width * .2f); SCREEN_WIDTH = graphics.GraphicsDevice.Viewport.Width - SIDE_PANEL_WIDTH; SCREEN_HEIGHT = graphics.GraphicsDevice.Viewport.Height; TILE_WIDTH = SCREEN_WIDTH / GRID_WIDTH; TILE_HEIGHT = SCREEN_HEIGHT / GRID_HEIGHT; attributes = new Dictionary<string, double>(); Statistics.attributeRange = new Dictionary<string, Vector2>(); attributeRange = Statistics.attributeRange; Statistics.firstAverages = new Dictionary<string, double>(); Statistics.currentSum = new Dictionary<string, double>(); attributes["redColor"] = 100; //RGB color scheme attributeRange["redColor"] = new Vector2(0, 255); attributes["blueColor"] = 50; attributeRange["blueColor"] = new Vector2(0, 255); attributes["greenColor"] = 70; attributeRange["greenColor"] = new Vector2(0, 255); attributes["mutationFactor"] = .2; attributeRange["mutationFactor"] = new Vector2(0, 1); attributes["walkSpeed"] = 1000.0; // how many milliseconds it takes to move a single step attributeRange["walkSpeed"] = new Vector2(100, 2000); attributes["desireForFood"] = 100.0; // how much this ant prioritizes collecting food attributeRange["desireForFood"] = new Vector2(-4000, 4000); attributes["desireToFollowAnts"] = 10.0; // how much this ant is willing to follow/avoid ants attributeRange["desireToFollowAnts"] = new Vector2(-300, 300); attributes["desireToExplore"] = 1.0; // how much this ant is willing to explore new places attributeRange["desireToExplore"] = new Vector2(-200, 200); attributes["desireToMate"] = 500.0; // influenced by number of children attributeRange["desireToMate"] = new Vector2(-600, 600); attributes["desireToContinueInSameDirection"] = 1500.0; // prevents equal-sum scenarios attributeRange["desireToContinueInSameDirection"] = new Vector2(-2000, 2000); attributes["desireToGoBackwards"] = -1000.0; // prevents oscillation attributeRange["desireToGoBackwards"] = new Vector2(-1500, 1500); attributes["timeToReexplore"] = 10.0; // how long (seconds) an ant remembers a spot attributeRange["timeToReexplore"] = new Vector2(1, 30); attributes["decayFactor"] = 4.0; // analogous to the ant's sense of smell attributeRange["decayFactor"] = new Vector2(1, 8); attributes["healthThreshold"] = 200.0; // if another ant meets this health threshold, // then the two will mate and produce offspring attributeRange["healthThreshold"] = new Vector2(1, 400); attributes["childbirthPercentage"] = 21.0; // % chance of having child when threshold met attributeRange["childbirthPercentage"] = new Vector2(1, 100); attributes["childbirthCost"] = 50.0; // how much the parent pays to raise child attributeRange["childbirthCost"] = new Vector2(1, 300); attributes["childbirthCooldown"] = 10.0; // how many seconds before having a child again attributeRange["childbirthCooldown"] = new Vector2(5, 30); //attributes["health"] = 150.0; // health is restored by eating food, // and it is lowered by moving around and taking damage //attributeRange["health"] = new Vector2(0, 300); //attributes["strength"] = 10.0; // TODO: damage dealt in a hit to a predator. influences // construction of buildings, too attributes["oldestPossibleAge"] = 200.0; // number of moves this ant can make before dying attributeRange["oldestPossibleAge"] = new Vector2(30, 400); attributes["eyesightRange"] = 100.0; // number of tiles this ant can see attributeRange["eyesightRange"] = new Vector2(3, 150); //attributes["resistance"] = 5.0; // TODO: immunity to cold, poison, and disease // also, social model vs individualistic model. social model is a shared diffusion. //attributes["shelterShape"] = 22.0; // TODO: this number gets rounded down when used in calculation. // base-2 representation of the truncated version is // used. each digit represents having or not having // a block in a certain location in a 5x5 grid. // digit ordering as follows: (1 = first digit's block location) // and alphabetical chars correspond to numbers beyond 9 // 22 = 10110(b2) = _ // _| shape /* PLDEM * KC56F * B4127 * JA38G * OI9HN */ line = new Texture2D(graphics.GraphicsDevice, 1, 1); line.SetData(new Color[] { Color.White }); base.Initialize(); }