/// <summary> /// <para> /// Method used to command a creature to begin moving towards a specific location /// at a specific speed. The actual movement operation may take several turns, /// but is always initiated using this method. Your movement location should /// be within the world boundary and your movement speed should be less than or /// equal to your creature's Species.MaximumSpeed. /// </para> /// <para> /// Once called the creature will begin moving towards the specified point. This /// movement will continue until you issue a different BeginMoving command to your /// creature, it reaches its destination, or becomes blocked by something. Any /// calls to BeginMoving will clear out any previous calls, so care should be taken /// when issuing multi-part path movements. /// </para> /// <para> /// Once the movement is completed the MoveCompleted event will be fired and your /// event handler for this function will be called if you've provided one. The /// event handler will provide full information about the results of an attempted /// movement operation. /// </para> /// </summary> /// <param name="vector"> /// The MovementVector that determines the point you are moving to and how fast to move there. /// </param> /// <exception cref="System.ArgumentNullException"> /// Thrown if the vector parameter is null. /// </exception> /// <exception cref="OutOfBoundsException"> /// Thrown if the destination is outside of the world boundaries. /// </exception> /// <exception cref="TooFastException"> /// Thrown if the speed defined in the vector is greater than Species.MaximumSpeed. /// </exception> public void BeginMoving(MovementVector vector) { if (vector == null) { throw new ArgumentNullException("vector", "The argument 'vector' cannot be null"); } if (vector.Speed > State.AnimalSpecies.MaximumSpeed) { throw new TooFastException(); } if (vector.Destination.X > World.WorldWidth - 1 || vector.Destination.X < 0 || vector.Destination.Y > World.WorldHeight - 1 || vector.Destination.Y < 0) { throw new OutOfBoundsException(); } var actionID = GetNextActionID(); var action = new MoveToAction(ID, actionID, vector); lock (PendingActions) { PendingActions.SetMoveToAction(action); InProgressActions.SetMoveToAction(action); } }
/// <summary> /// <para> /// Use this function to command your creature to reproduce. There are many /// conditions on whether your creature can reproduce. If these conditions /// are not met, an exception will be thrown. The easiest way to make /// sure all pre-existing conditions have been met is to check the CanReproduce /// property. /// </para> /// <para> /// If you call this method multiple times in the same turn, then the last call /// will be used, and all previous calls will be ignored. This method is also /// asynchronous, and a ReproduceCompletedEvent will be fired when your creature /// has actually given birth. The time between start and completion is 10 ticks. /// </para> /// </summary> /// <param name="dna"> /// A byte array that gets passed to the child. This can be any information you /// want to pass to the child creature. The byte array is truncated at 8000 bytes. /// </param> /// <exception cref="AlreadyReproducingException"> /// Thrown when your creature is already in the process of reproduction. /// </exception> /// <exception cref="NotMatureException"> /// Thrown when your creature is not yet mature and you try to reproduce. /// </exception> /// <exception cref="NotEnoughEnergyException"> /// Thrown when your creature does not have enough energy to start reproduction. /// </exception> /// <exception cref="NotReadyToReproduceException"> /// Thrown when your creature is not yet ready to reproduce because the appropriate number of ticks has not elapsed. /// </exception> public void BeginReproduction(byte[] dna) { if (IsReproducing) { throw new AlreadyReproducingException(); } if (!State.IsMature) { throw new NotMatureException(); } if (State.EnergyState < EnergyState.Normal) { throw new NotEnoughEnergyException(); } if (!State.ReadyToReproduce) { throw new NotReadyToReproduceException(); } var actionID = GetNextActionID(); var action = new ReproduceAction(ID, actionID, dna); lock (PendingActions) { PendingActions.SetReproduceAction(action); InProgressActions.SetReproduceAction(action); } }
/// <summary> /// <para> /// Clears any pending movement operations your creature might be performing. /// </para> /// </summary> public void StopMoving() { lock (PendingActions) { PendingActions.SetMoveToAction(null); InProgressActions.SetMoveToAction(null); } }
/// <summary> /// <para> /// Method used to command your creature to start eating another creature. /// You can only eat one target creature per round, and a single call to /// BeginEating will only attack a target creature in the upcoming tick. /// Calling BeginEating multiple times in the same turn will only result /// in your creature eating the target specified in the last call to /// BeginEating. /// </para> /// <para> /// Eating is asynchronous so you'll need to handle the EatCompleted event /// in order to get the status of the bite. A single bite might not /// produce enough energy for your creature so you'll have to make multiple /// bites against the same target until it is completed eaten. /// </para> /// </summary> /// <param name="targetOrganism"> /// OrganismState of the creature you wish to eat. /// </param> /// <exception cref="System.ArgumentNullException"> /// Thrown if the targetOrganism parameter is null. /// </exception> /// <exception cref="AlreadyFullException"> /// Thrown if your creature is not hungry enough to eat. /// </exception> /// <exception cref="NotVisibleException"> /// Thrown if the creature had disappeared from your creature's view. /// </exception> /// <exception cref="NotWithinDistanceException"> /// Thrown if your creature is not within eating distance. /// </exception> /// <exception cref="ImproperFoodException"> /// Thrown if a Carnivore tries to eat a plant or a Herbivore tries to eat an Animal /// </exception> /// <exception cref="NotDeadException"> /// Thrown if a Carnivore tries to eat a creature that isn't dead yet. /// </exception> public void BeginEating(OrganismState targetOrganism) { if (targetOrganism == null) { throw new ArgumentNullException("targetOrganism", "The argument 'targetOrganism' cannot be null"); } if (State.EnergyState > EnergyState.Normal) { throw new AlreadyFullException(); } // Get an up to date state -- this organism may be an old state var currentOrganism = World.LookForNoCamouflage(targetOrganism); if (currentOrganism == null) { throw new NotVisibleException(); } if (!WithinEatingRange(currentOrganism)) { throw new NotWithinDistanceException(); } // Make sure it is edible if (State.AnimalSpecies.IsCarnivore) { if (currentOrganism is PlantState) { throw new ImproperFoodException(); } if (currentOrganism.IsAlive) { throw new NotDeadException(); } } else { if (currentOrganism is AnimalState) { throw new ImproperFoodException(); } } var actionID = GetNextActionID(); var action = new EatAction(ID, actionID, targetOrganism); lock (PendingActions) { PendingActions.SetEatAction(action); InProgressActions.SetEatAction(action); } }
/// <internal/> public PendingActions GetThenErasePendingActions() { PendingActions detachedActions; lock (PendingActions) { detachedActions = pendingActions; pendingActions = new PendingActions(); } detachedActions.MakeImmutable(); return(detachedActions); }
/// <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); } }
/// <internal/> public PendingActions GetThenErasePendingActions() { PendingActions detachedActions; lock (PendingActions) { detachedActions = pendingActions; pendingActions = new PendingActions(); } detachedActions.MakeImmutable(); return detachedActions; }