/// <internal/> public MoveCompletedEventArgs(int actionID, Action action, ReasonForStop reason, OrganismState blockingOrganism) : base(actionID, action) { Reason = reason; BlockingOrganism = blockingOrganism; }
/// <summary> /// Derived classes must override (and call Base.CopyStateInto) /// if they have additional state /// </summary> /// <param name="newInstance">The new state that will hold this state's members</param> /// <internal/> protected virtual void CopyStateInto(OrganismState newInstance) { // OrganismID and species are copied via the constructor newInstance.Radius = Radius; // Safe because they are immutable newInstance._currentMoveToAction = _currentMoveToAction; newInstance._currentReproduceAction = _currentReproduceAction; // Points aren't immutable, so return a copy newInstance._currentPosition = new Point(_currentPosition.X, _currentPosition.Y); newInstance._energy = _energy; newInstance.currentFoodChunks = currentFoodChunks; newInstance.IncubationTicks = IncubationTicks; newInstance.TickAge = TickAge; newInstance.ReproductionWait = ReproductionWait; newInstance.GrowthWait = GrowthWait; newInstance.DeathReason = DeathReason; newInstance.ActualDirection = ActualDirection; // This object remains mutable because it is information // that the renderer updates after the WorldVector has been // created. Nothing besides the renderer should ever touch this newInstance.RenderInfo = RenderInfo; }
/// <summary> /// /// </summary> /// <param name="newInstance"></param> protected override void CopyStateInto(OrganismState newInstance) { base.CopyStateInto(newInstance); ((AnimalState)newInstance).damage = damage; ((AnimalState)newInstance).RotTicks = RotTicks; ((AnimalState)newInstance).state = new AntennaState(state); }
/// <summary> /// Create a new state object to represent an organism. /// </summary> /// <param name="id">The GUID ID representing this organism in the world.</param> /// <param name="species">The species which defines the basic properties of the organism.</param> /// <param name="generation">The familial generation number.</param> /// <param name="initialEnergyState">The initial EnergyState of the organism.</param> /// <param name="initialRadius">The initial Radius of the organism.</param> internal OrganismState(string id, ISpecies species, int generation, EnergyState initialEnergyState, int initialRadius) { DeathReason = PopulationChangeReason.NotDead; ID = id; Species = species; Generation = generation; SetStoredEnergyInternal(OrganismState.UpperBoundaryForEnergyState(species, initialEnergyState, initialRadius)); Radius = initialRadius; _events = new OrganismEventResults(); _currentPosition = new Point(); }
/// <summary> /// Used to compute whether or not a given state object is in an adjacent or /// overlapping grid cell. The extra radius can be used to extend the area /// used for the function to find a match and so can be used for functions /// like visibiliy. /// </summary> /// <param name="state1ExtraRadius">The amount of extra grid cells to add</param> /// <param name="state2">The organism state of the creature to use in the area test.</param> /// <returns>True if the creature is within range, false otherwise.</returns> public Boolean IsWithinRect(int state1ExtraRadius, OrganismState state2) { if (null == state2) { return(false); } var state1Radius = CellRadius + state1ExtraRadius; var state2Radius = state2.CellRadius; var difference = (GridX - state1Radius) - (state2.GridX - state2Radius); if (difference < 0) { // Negative means state1 boundary < state2 boundary if (-difference > (state1Radius * 2) + 1) { // X isn't overlapping or adjacent return(false); } } else { // state2 boundary <= state1 boundary if (difference > (state2Radius * 2) + 1) { // X isn't overlapping or adjacent return(false); } } difference = (GridY - state1Radius) - (state2.GridY - state2Radius); if (difference < 0) { // Negative means state1 boundary < state2 boundary if (-difference > (state1Radius * 2) + 1) { // Y isn't overlapping or adjacent return(false); } } else { // state2 boundary <= state1 boundary if (difference > (state2Radius * 2) + 1) { // Y isn't overlapping or adjacent return(false); } } return(true); }
/// <summary> /// <para> /// Tries to return an updated OrganismState given a creature's state OrganismState. /// This function may return null if the creature can't be found or was hidden by /// camouflage. You may call this method multiple times and get different results. /// </para> /// </summary> /// <param name="organismState"> /// The stale OrganismState object you want to refresh. /// </param> /// <returns> /// OrganismState representing the creature being looked for or null if not found. /// </returns> /// <exception cref="System.ArgumentNullException"> /// Thrown if the organismState parameter is null. /// </exception> public OrganismState LookFor(OrganismState organismState) { if (organismState == null) { throw new ArgumentNullException("organismState", "The argument 'organismState' cannot be null"); } return World.LookFor(organismState); }
/// <summary> /// <para> /// Allows a creature to determine if the OrganismState of another creature /// represents the same species. This can be used to determine whether you /// should attack/defend against another creature. /// </para> /// <para> /// Creatures of the same species often don't fight one another, defend against /// one another, and kill one another. They often help their own species in /// fights against other species. Carnivores of the same species may sacrifice /// themselves as food once they become too old to members of their species. /// </para> /// </summary> /// <param name="targetState"> /// The OrganismState for the creature to be used in species comparison. /// </param> /// <returns> /// True if the organism owning the state object is of the same species, false otherwise. /// </returns> /// <exception cref="System.ArgumentNullException"> /// Thrown if the targetState parameter is null. /// </exception> public Boolean IsMySpecies(OrganismState targetState) { if (targetState == null) { throw new ArgumentNullException("targetState", "The argument 'targetState' cannot be null"); } return State.Species.IsSameSpecies(targetState.Species); }
/// <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); } }
/// <summary> /// /// </summary> /// <param name="newInstance"></param> protected override void CopyStateInto(OrganismState newInstance) { base.CopyStateInto(newInstance); ((AnimalState)newInstance).damage = damage; ((AnimalState)newInstance).RotTicks = RotTicks; ((AnimalState)newInstance).state = new AntennaState(state); }
/// <summary> /// <para> /// Determines if a creature is immediately next to or overlapping /// another creature using grid cells comparisons. /// </para> /// </summary> /// <param name="state2"> /// OrganismState of the creature to check for proximity. /// </param> /// <returns> /// True if the creature is adjacent or overlapping, False otherwise. /// </returns> public Boolean IsAdjacentOrOverlapping(OrganismState state2) { return IsWithinRect(0, state2); }
/// <summary> /// <para> /// Determines if a creature is immediately next to or overlapping /// another creature using grid cells comparisons. /// </para> /// </summary> /// <param name="state2"> /// OrganismState of the creature to check for proximity. /// </param> /// <returns> /// True if the creature is adjacent or overlapping, False otherwise. /// </returns> public Boolean IsAdjacentOrOverlapping(OrganismState state2) { return(IsWithinRect(0, state2)); }
/// <summary> /// Create a new eat action to eat a specific organism. /// </summary> /// <param name="organismID">Eating organism's ID</param> /// <param name="actionID">Unique Organism ID for action.</param> /// <param name="targetOrganism">The state representing the organism to eat.</param> internal EatAction(string organismID, int actionID, OrganismState targetOrganism) : base(organismID, actionID) { TargetOrganism = targetOrganism; }
/// <summary> /// Copies the value of the current state into a new state object. /// Used by the CloneMutable method to make mutable copies of state /// objects. /// </summary> /// <param name="newInstance">The new state object that will hold the values.</param> /// <internal/> protected override void CopyStateInto(OrganismState newInstance) { base.CopyStateInto(newInstance); ((PlantState)newInstance).Height = Height; }
/// <summary> /// Copies the value of the current state into a new state object. /// Used by the CloneMutable method to make mutable copies of state /// objects. /// </summary> /// <param name="newInstance">The new state object that will hold the values.</param> /// <internal/> protected override void CopyStateInto(OrganismState newInstance) { base.CopyStateInto(newInstance); ((PlantState)newInstance).Height = Height; }
/// <summary> /// Used to compute whether or not a given state object is in an adjacent or /// overlapping grid cell. The extra radius can be used to extend the area /// used for the function to find a match and so can be used for functions /// like visibiliy. /// </summary> /// <param name="state1ExtraRadius">The amount of extra grid cells to add</param> /// <param name="state2">The organism state of the creature to use in the area test.</param> /// <returns>True if the creature is within range, false otherwise.</returns> public Boolean IsWithinRect(int state1ExtraRadius, OrganismState state2) { if (null == state2) { return false; } var state1Radius = CellRadius + state1ExtraRadius; var state2Radius = state2.CellRadius; var difference = (GridX - state1Radius) - (state2.GridX - state2Radius); if (difference < 0) { // Negative means state1 boundary < state2 boundary if (-difference > (state1Radius * 2) + 1) { // X isn't overlapping or adjacent return false; } } else { // state2 boundary <= state1 boundary if (difference > (state2Radius * 2) + 1) { // X isn't overlapping or adjacent return false; } } difference = (GridY - state1Radius) - (state2.GridY - state2Radius); if (difference < 0) { // Negative means state1 boundary < state2 boundary if (-difference > (state1Radius * 2) + 1) { // Y isn't overlapping or adjacent return false; } } else { // state2 boundary <= state1 boundary if (difference > (state2Radius * 2) + 1) { // Y isn't overlapping or adjacent return false; } } return true; }
/// <summary> /// <para> /// Used to determine if your creature is within range to eat 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 eating. /// </param> /// <returns> /// True if the creature is within range to eat, False otherwise. /// </returns> /// <exception cref="System.ArgumentNullException"> /// Thrown if the targetOrganism parameter is null. /// </exception> public Boolean WithinEatingRange(OrganismState targetOrganism) { if (targetOrganism == null) { throw new ArgumentNullException("targetOrganism", "The argument 'targetOrganism' cannot be null"); } return State.IsAdjacentOrOverlapping(targetOrganism); }
/// <summary> /// <para> /// Calculates the linear distance between your creature and another using /// various API's defined by the Vector class. /// </para> /// </summary> /// <param name="organismState"> /// The OrganismState object for the creature to /// use when computing linear distance from you're creature. /// </param> /// <returns> /// A System.Double representing the linear distance between your creature and another. /// </returns> public double DistanceTo(OrganismState organismState) { if (organismState == null) { throw new ArgumentNullException("organismState", "The argument 'organismState' cannot be null"); } return Vector.Subtract(Position, organismState.Position).Magnitude; }
/// <summary> /// Derived classes must override (and call Base.CopyStateInto) /// if they have additional state /// </summary> /// <param name="newInstance">The new state that will hold this state's members</param> /// <internal/> protected virtual void CopyStateInto(OrganismState newInstance) { // OrganismID and species are copied via the constructor newInstance.Radius = Radius; // Safe because they are immutable newInstance._currentMoveToAction = _currentMoveToAction; newInstance._currentReproduceAction = _currentReproduceAction; // Points aren't immutable, so return a copy newInstance._currentPosition = new Point(_currentPosition.X, _currentPosition.Y); newInstance._energy = _energy; newInstance.currentFoodChunks = currentFoodChunks; newInstance.IncubationTicks = IncubationTicks; newInstance.TickAge = TickAge; newInstance.ReproductionWait = ReproductionWait; newInstance.GrowthWait = GrowthWait; newInstance.DeathReason = DeathReason; newInstance.ActualDirection = ActualDirection; // This object remains mutable because it is information // that the renderer updates after the WorldVector has been // created. Nothing besides the renderer should ever touch this newInstance.RenderInfo = RenderInfo; }