/// <summary> /// <para> /// Used to determine if your creature can attack another creature. /// This will return true all the time for a Carnivore since they /// can always attack. /// </para> /// <para> /// For Herbivores this will return true if they are hungry enough /// to be aggressive. Herbivores may also attack a creature in /// the upcoming round if that creature attacked them in the /// previous round. The best place to attack a creature that is /// attacking you is to handle the Attacked event. /// </para> /// </summary> /// <param name="targetAnimal"> /// AnimalState for the creature you would like to attack. /// </param> /// <returns> /// True if your creature can attack the target creature, False otherwise. /// </returns> /// <exception cref="System.ArgumentNullException"> /// Thrown if the targetAnimal parameter is null. /// </exception> public Boolean CanAttack(AnimalState targetAnimal) { if (State.AnimalSpecies.IsCarnivore) { return(true); } if (targetAnimal == null) { throw new ArgumentNullException("targetAnimal", "The argument 'targetAnimal' cannot be null"); } // You can attack back if you were just attacked var wasAttacked = false; foreach (AttackedEventArgs attackEvent in State.OrganismEvents.AttackedEvents) { if (attackEvent.Attacker.ID != targetAnimal.ID) { continue; } wasAttacked = true; break; } return(wasAttacked || State.EnergyState <= EnergyState.Hungry); }
/// <summary> /// /// </summary> /// <returns></returns> public override OrganismState CloneMutable() { var newInstance = new AnimalState(ID, AnimalSpecies, Generation, EnergyState, Radius); CopyStateInto(newInstance); return(newInstance); }
/// <summary> /// <para> /// Used to determine if your creature is within range to attack another /// target creature. /// </para> /// <para> /// This method does not attempt to validate the position of the /// organismState with respect to the current world state. If you /// pass a stale object in then you may get stale results. Make sure /// you use the LookFor method to get the most up-to-date results. /// </para> /// </summary> /// <param name="targetOrganism"> /// OrganismState of the creature you're thinking of attacking. /// </param> /// <returns> /// True if the creature is within range to attack, False otherwise. /// </returns> /// <exception cref="System.ArgumentNullException"> /// Thrown if the targetOrganims parameter is null /// </exception> public Boolean WithinAttackingRange(AnimalState targetOrganism) { if (targetOrganism == null) { throw new ArgumentNullException("targetOrganism", "The argument 'targetOrganism' cannot be null"); } return(State.IsWithinRect(1, targetOrganism)); }
/// <summary> /// <para> /// Method used to command a creature to begin defending against a specific /// target creature. You can only defend against one creature at a time, /// so only the final call to BeginDefending will actually be used /// in the upcoming turn. /// </para> /// <para> /// Once your creature has finished defending, the DefendCompleted event will /// be fired and your event handler will be called if you provided one. You /// can use this event to determine the results of your defense. /// </para> /// </summary> /// <param name="targetAnimal"> /// The AnimalState that represents the animal you want to defend against. /// </param> /// <exception cref="System.ArgumentNullException"> /// Thrown if the targetAnimal parameter is null. /// </exception> public void BeginDefending(AnimalState targetAnimal) { if (targetAnimal == null) { throw new ArgumentNullException("targetAnimal", "The argument 'targetAnimal' cannot be null"); } var actionID = GetNextActionID(); var action = new DefendAction(ID, actionID, targetAnimal); lock (PendingActions) { PendingActions.SetDefendAction(action); InProgressActions.SetDefendAction(action); } }
// First event fired on an organism each turn void LoadEvent(object sender, LoadEventArgs e) { try { if(targetAnimal != null) { // See if our target animal still exists (it may have died) // LookFor returns null if it isn't found targetAnimal = (AnimalState) LookFor(targetAnimal); } } catch(Exception exc) { // WriteTrace is useful in debugging creatures WriteTrace(exc.ToString()); } }
/// <summary> /// <para> /// Used to determine if your creature can attack another creature. /// This will return true all the time for a Carnivore since they /// can always attack. /// </para> /// <para> /// For Herbivores this will return true if they are hungry enough /// to be aggressive. Herbivores may also attack a creature in /// the upcoming round if that creature attacked them in the /// previous round. The best place to attack a creature that is /// attacking you is to handle the Attacked event. /// </para> /// </summary> /// <param name="targetAnimal"> /// AnimalState for the creature you would like to attack. /// </param> /// <returns> /// True if your creature can attack the target creature, False otherwise. /// </returns> /// <exception cref="System.ArgumentNullException"> /// Thrown if the targetAnimal parameter is null. /// </exception> public Boolean CanAttack(AnimalState targetAnimal) { if (State.AnimalSpecies.IsCarnivore) { return true; } if (targetAnimal == null) { throw new ArgumentNullException("targetAnimal", "The argument 'targetAnimal' cannot be null"); } // You can attack back if you were just attacked var wasAttacked = false; foreach (AttackedEventArgs attackEvent in State.OrganismEvents.AttackedEvents) { if (attackEvent.Attacker.ID != targetAnimal.ID) continue; wasAttacked = true; break; } return wasAttacked || State.EnergyState <= EnergyState.Hungry; }
void FindNewTarget() { try { ArrayList foundAnimals = Scan(); // We should see at least a couple of animals. if(foundAnimals.Count > 0) { foreach(OrganismState organismState in foundAnimals) { // We are looking for any organism that is an animal // and that isn't of our species so we can eat them. if(organismState is AnimalState && !IsMySpecies(organismState)) { targetAnimal = (AnimalState) organismState; } } } } catch(Exception exc) { WriteTrace(exc.ToString()); } }
/// <summary> /// Creates a new attack action targeting a specific creature. /// </summary> /// <param name="organismID">Attacking organism's ID</param> /// <param name="actionID">Organism Unique ID for action.</param> /// <param name="targetAnimal">The creature to attack.</param> internal AttackAction(string organismID, int actionID, AnimalState targetAnimal) : base(organismID, actionID) { TargetAnimal = targetAnimal; }
/// <summary> /// /// </summary> /// <returns></returns> public override OrganismState CloneMutable() { var newInstance = new AnimalState(ID, AnimalSpecies, Generation, EnergyState, Radius); CopyStateInto(newInstance); return newInstance; }
/// <summary> /// Initializes a new state given a position and a generation. This is /// used when creatures give birth, and the state has to effectively /// be cloned. /// </summary> /// <param name="position">The new position of the creature in the world.</param> /// <param name="generation">The family generation for this creature.</param> /// <returns>A new state to represent the creature.</returns> public override OrganismState InitializeNewState(Point position, int generation) { AnimalState newState = new AnimalState(Guid.NewGuid().ToString(), this, generation); newState.Position = position; newState.IncreaseRadiusTo(InitialRadius); // Need to start out hungry so they can't reproduce immediately and just populate the world newState.StoredEnergy = newState.UpperBoundaryForEnergyState(EnergyState.Hungry); newState.ResetGrowthWait(); return newState; }
/// <summary> /// Creates a new attack action targeting a specific creature. /// </summary> /// <param name="organismID">Attacking organism's ID</param> /// <param name="actionID">Organism Unique ID for action.</param> /// <param name="targetAnimal">The creature to attack.</param> internal AttackAction(string organismID, int actionID, AnimalState targetAnimal) : base(organismID, actionID) { this.targetAnimal = targetAnimal; }
/// <summary> /// Initializes a new state given a position and a generation. This is /// used when creatures give birth, and the state has to effectively /// be cloned. /// </summary> /// <param name="position">The new position of the creature in the world.</param> /// <param name="generation">The family generation for this creature.</param> /// <returns>A new state to represent the creature.</returns> public override OrganismState InitializeNewState(Point position, int generation) { // Need to start out hungry so they can't reproduce immediately and just populate the world var initialEnergy = EnergyState.Hungry; var newState = new AnimalState(Guid.NewGuid().ToString(), this, generation, initialEnergy, InitialRadius) { Position = position }; newState.ResetGrowthWait(); return newState; }
/// <summary> /// <para> /// Method used to command your creature to start attacking another /// creature. You can only attack one creature per round, and a single /// call to BeginAttacking will only attack a target creature in the /// upcoming tick. Calling BeginAttacking multiple times in the same /// turn will only result in your creature attacking the target specified /// in the last call to BeginAttacking. /// </para> /// <para> /// Attacking is asynchronous so you'll need to handle the AttackCompleted /// event in order to get the status of your attack. A single attack might /// not kill a target enemy so you should detect if the enemy is still /// alive and call BeginAttacking once per round until the target creature /// is either dead or has escaped. /// </para> /// </summary> /// <param name="targetAnimal"> /// The AnimalState object that represents the creature you want your creature to attack. /// </param> /// <exception cref="System.ArgumentNullException"> /// Thrown if the targetAnimal parameter is null. /// </exception> /// <exception cref="NotHungryException"> /// Thrown if the creature is not hungry enough to attack. /// </exception> public void BeginAttacking(AnimalState targetAnimal) { if (targetAnimal == null) { throw new ArgumentNullException("targetAnimal", "The argument 'targetAnimal' cannot be null"); } if (!CanAttack(targetAnimal)) { throw new NotHungryException(); } int actionID = GetNextActionID(); AttackAction action = new AttackAction(ID, actionID, targetAnimal); lock (this.PendingActions) { PendingActions.SetAttackAction(action); InProgressActions.SetAttackAction(action); } }
/// <summary> /// Creates a new set of event arguments that can be used to notify /// a creature that another creature has completed an attack action /// against them. /// </summary> /// <param name="attacker">The state of the attacking creature.</param> /// <internal/> public AttackedEventArgs(AnimalState attacker) { Attacker = attacker; }
/// <summary> /// <para> /// Used to determine if your creature is within range to attack another /// target creature. /// </para> /// <para> /// This method does not attempt to validate the position of the /// organismState with respect to the current world state. If you /// pass a stale object in then you may get stale results. Make sure /// you use the LookFor method to get the most up-to-date results. /// </para> /// </summary> /// <param name="targetOrganism"> /// OrganismState of the creature you're thinking of attacking. /// </param> /// <returns> /// True if the creature is within range to attack, False otherwise. /// </returns> /// <exception cref="System.ArgumentNullException"> /// Thrown if the targetOrganims parameter is null /// </exception> public Boolean WithinAttackingRange(AnimalState targetOrganism) { if (targetOrganism == null) { throw new ArgumentNullException("targetOrganism", "The argument 'targetOrganism' cannot be null"); } return State.IsWithinRect(1, targetOrganism); }
/// <summary> /// Creates a new defend action to defend against a particular target /// creature. /// </summary> /// <param name="organismID">Defending organism's ID</param> /// <param name="actionID">Creature Unique ID for action.</param> /// <param name="targetAnimal">The state representing the creature to defend against.</param> internal DefendAction(string organismID, int actionID, AnimalState targetAnimal) : base(organismID, actionID) { TargetAnimal = targetAnimal; }
void SampleCarnivore_Load(object sender, LoadEventArgs e) { try { if (_targetAnimal == null) { _targetAnimal = (AnimalState) LookFor(_targetAnimal); } } catch (Exception exc) { WriteTrace(exc.ToString()); } }
private bool ScanForTargetAnimal() { try { ArrayList foundAnimals = Scan(); if (foundAnimals.Count > 0) { foreach (OrganismState organism in foundAnimals) { if (!(organism is AnimalState)) continue; _targetAnimal = (AnimalState) organism; BeginMoving(new MovementVector(_targetAnimal.Position, 2)); return true; } } } catch (Exception exc) { WriteTrace(exc.ToString()); } return false; }