protected virtual void CheckState() { //refresh state to take new variables state ChangeState(state); switch (state) { case AntState.lookForFood: if (food != null) { ChangeState(AntState.goToFood); } break; case AntState.goToFood: if (food.Amount == 0 && Vector2.Distance(foodPosition, Position) < ConstantsHolder.Singleton.Vision) { food = null; ChangeState(AntState.lookForFood); break; } if (Vector2.Distance(foodPosition, Position) < ConstantsHolder.Singleton.EatingRadius) { foodCarried = ConstantsHolder.Singleton.CarryMax; food.Amount -= ConstantsHolder.Singleton.CarryMax; ChangeState(AntState.bringBackFood); } break; case AntState.bringBackFood: if (Vector2.Distance(AntHill.Position, Position) < ConstantsHolder.Singleton.EatingRadius) { game.AntHill.Food += foodCarried; foodCarried = 0; ChangeState(AntState.goToFood); } break; case AntState.transportCorpse: cadaver.Position = position; //if the ant don't know a cemetery it will just put the corpse at a sanitary distance of the anthill if (cemeteryBest == null) { if (Vector2.Distance(position, antHill.Position) > ConstantsHolder.Singleton.SainityDistance) { //double tap! cadaver.Kill(); if (leftToClean > 0) { ChangeState(AntState.backToClean); } else { ChangeState(previousState); } } } else { // the ant reaches the biggest known cemetery it put the cadaver in the cemetery if (Vector2.Distance(goal, Position) < ConstantsHolder.Singleton.EatingRadius) { //if the best known have desapeared the ant just put the corpse at a sanitary distance from the anthill if (cemeteryBest.Count == 0) { cemeteryBest = null; //double tap! cadaver.Kill(); } else { cemeteryBest.Add(cadaver); } cadaver = null; //go back to clean the previous cemetery if it is not known as empty if (leftToClean > 0) { ChangeState(AntState.backToClean); } else { ChangeState(previousState); } break; } } break; case AntState.goToCorpse: if (Vector2.Distance(goal, Position) < ConstantsHolder.Singleton.EatingRadius) { //take a cadaver in a cemetery when it reach it if (cemeteryToClean.Contains(cadaver)) { cemeteryToClean.Remove(cadaver); leftToClean = cemeteryToClean.Count; //if taking the corpse clean the cemetery it will be destroyed if (cemeteryToClean.Count == 0) { game.Cemeteries.Remove(cemeteryToClean); cemeteryToClean = null; } ChangeState(AntState.transportCorpse); } //if the corpse have been taken by an other ant, it return to normal activity else { ChangeState(previousState); } } break; //go back the previous cemetery to clean it case AntState.backToClean: //if the cemetery is empty the ant remove it and go back to its activity //if it's full the ant will automatically change state to goforCorpse from the cemetery scan in the update function if (Vector2.Distance(goal, Position) < ConstantsHolder.Singleton.Vision) { if (cemeteryToClean == null || cemeteryToClean.Count == 0) { leftToClean = 0; cemeteryToClean = null; if (previousState == AntState.backToClean) { previousState = AntState.lookForFood; } ChangeState(previousState); } } break; } }
public override void Update(GameTime gameTime) { base.Update(gameTime); //the ant have a certain probability to die each frame double ran = game.Random.NextDouble(); if (ran < 0.5f / ConstantsHolder.Singleton.HalfLife) { Kill(); } CheckState(); if (Vector2.Distance(AntHill.Position, Position) < ConstantsHolder.Singleton.EatingRadius) { if (AntHill.Food >= 0) { AntHill.Food -= Hungry; Hungry = 0; } } if (Hungry > ConstantsHolder.Singleton.Starvation) { Kill(); } //find closest food point foreach (Food possibleFood in game.Foods) { if (Vector2.Distance(possibleFood.Position, Position) < ConstantsHolder.Singleton.Vision && (food == null || Vector2.Distance(possibleFood.Position, AntHill.Position) < Vector2.Distance(food.Position, AntHill.Position))) { food = possibleFood; foodPosition = possibleFood.Position; if (state == AntState.goToFood) { goal = food.Position; } } } //find bigest cemetery around for (int i = 0; i < game.Cemeteries.Count; i++) { Cemetery possibleCemetery = game.Cemeteries[i]; //within view range if (Vector2.Distance(possibleCemetery.Position, Position) < ConstantsHolder.Singleton.Vision && possibleCemetery.Count != 0) { //find bigest cemetery if (Vector2.Distance(possibleCemetery.Position, antHill.Position) >= ConstantsHolder.Singleton.SainityDistance && (cemeteryBest == null || possibleCemetery.Count > cemeterySmell)) { //if the ant had a previous best cemetery, it decided to move it in the new one bool needToClean = false; if (cemeteryBest != null && cemeteryBest != possibleCemetery && state != AntState.goToCorpse && state != AntState.transportCorpse) { cemeteryToClean = cemeteryBest; cemeteryToCleanPos = cemeteryToClean.Position; previousState = state; needToClean = true; } //update the biggest known cemetery cemeteryBest = possibleCemetery; cemeterySmell = possibleCemetery.Count; if (state == AntState.transportCorpse) { goal = possibleCemetery.Position; goalLover = ConstantsHolder.Singleton.TransportGoal; } //start to clean the old cemetery if (needToClean) { ChangeState(AntState.backToClean); } } ////with a decent distance to the hill //if (Vector2.Distance(possibleCemetery.Position, antHill.Position) >= ConstantsHolder.Singleton.SainityDistance // && (cemeteryBest == null || possibleCemetery.Count > cemeterySmell)) //{ // bool needToClean = false; // if (cemeteryBest != null // && cemeteryBest != possibleCemetery // && state != AntState.goToCorpse // && state != AntState.transportCorpse) // { // cemeteryToClean = cemeteryBest; // cemeteryToCleanPos = cemeteryToClean.Position; // previousState = state; // needToClean = true; // } // cemeteryBest = possibleCemetery; // cemeterySmell = possibleCemetery.Count; // if (state == AntState.transportCorpse) // { // goal = possibleCemetery.Position; // goalLover = ConstantsHolder.Singleton.TransportGoal; // } // if (needToClean) // { // ChangeState(AntState.backToClean); // } //} //Update the size of the biggest known cemetery if (possibleCemetery == cemeteryBest) { cemeterySmell = possibleCemetery.Count; } //if the cemetery seen is not the biggest the ant start to clean it //if the ant is not already carrying a corpse a going to a corpse else if (state != AntState.goToCorpse && state != AntState.transportCorpse) { cadaver = possibleCemetery.Last(); //handle a little bug that sometime the cemetery have one null cadaver instead of nothing //it would be maybe cleaner to prevent that if (cadaver != null) { cemeteryToClean = possibleCemetery; cemeteryToCleanPos = cemeteryToClean.Position; previousState = state; //remember the size to know if there is a need to come back to clean leftToClean = cemeteryToClean.Count; ChangeState(AntState.goToCorpse); } else { //we don't keep empty cemeteries game.Cemeteries.Remove(possibleCemetery); if (state == AntState.backToClean) { cemeteryToClean = null; ChangeState(previousState); } } } } } this.previousPosition = this.position; }