/// <summary>
        ///  Refreshes an organism state to the latest available state.  Organism
        ///  state objects can be held by an organism for many ticks, and they don't
        ///  automatically update themselves.  The reference held is immutable and so
        ///  only represents the creature's state at the time the Scan was made and
        ///  not necessarily the latest state.
        /// </summary>
        /// <param name="organismState">The organism state that needs to be updated</param>
        /// <returns>An updated state if the creature is still visible and alive, else null</returns>
        public OrganismState LookFor(OrganismState organismState)
        {
            if (organismState == null)
            {
                throw new ArgumentNullException("organismState", "The argument organismState cannot be null");
            }

            OrganismState targetOrganism = LookForNoCamouflage(organismState);

            if (targetOrganism != null)
            {
                if (targetOrganism is AnimalState)
                {
                    // See if the camouflage hides it
                    int invisible = Organism.OrganismRandom.Next(1, 100);
                    if (invisible <= ((AnimalSpecies)targetOrganism.Species).InvisibleOdds)
                    {
                        Organism.WriteTrace("#Camouflage hid animal from organism");
                        return null;
                    }
                }

                return targetOrganism;
            }
            else
            {
                return null;
            }
        }
Exemple #2
0
 internal void SelectOrganism(OrganismState state)
 {
     if (showTraces.Checked)
     {
         AddTrace(state);
     }
 }
        /// <summary>
        ///  Creates a new event relating to a creature being destroyed.
        /// </summary>
        /// <param name="organismState">The creature being destroyed.</param>
        /// <param name="reason">The reason the creature is being destroyed.</param>
        /// <returns>State change initialized for a creature being destroyed with messages.</returns>
        public static EngineStateChangedEventArgs AnimalDestroyed(OrganismState organismState,
                                                                  PopulationChangeReason reason)
        {
            var reasonDescription = "";

            switch (reason)
            {
                case PopulationChangeReason.Timeout:
                    reasonDescription = "thought for too long";
                    break;

                case PopulationChangeReason.Error:
                    reasonDescription = "had an error";
                    break;

                case PopulationChangeReason.SecurityViolation:
                    reasonDescription = "attempted to violate security";
                    break;

                case PopulationChangeReason.OrganismBlacklisted:
                    reasonDescription = "is blacklisted due to past bad behavior and won't be loaded";
                    break;
            }

            return new EngineStateChangedEventArgs(
                EngineStateChangeType.Other,
                string.Format("A {0} was destroyed because it {1}.", ((Species) organismState.Species).Name,
                              reasonDescription),
                string.Format("A {0} was destroyed because it {1}.", ((Species) organismState.Species).Name,
                              reasonDescription)
                );
        }
        /// <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;
        }
 /// <internal/>
 public MoveCompletedEventArgs(int actionID, Action action, ReasonForStop reason,
     OrganismState blockingOrganism)
     : base(actionID, action)
 {
     Reason = reason;
     BlockingOrganism = blockingOrganism;
 }
Exemple #6
0
        /// <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>
        ///  Creates a NewOrganism object intialized with the creature's state, some
        ///  DNA information if available.  The state object must be immutable for
        ///  this to succeed.
        /// </summary>
        /// <param name="state">The state of the organism to be added.</param>
        /// <param name="dna">The DNA the creature gets initialized with.</param>
        public NewOrganism(OrganismState state, byte[] dna)
        {
            // Must be mutable
            Debug.Assert(!state.IsImmutable);

            this.state = state;
            this.dna = dna;
        }
Exemple #8
0
        /// <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));
        }
Exemple #9
0
        /// <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));
        }
Exemple #10
0
        /// <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>
 ///  Creates a new event relating to a creature arriving.
 /// </summary>
 /// <param name="organismState">The creature arriving.</param>
 /// <returns>State change initialized for a teleporting creature with messages.</returns>
 public static EngineStateChangedEventArgs AnimalArrived(OrganismState organismState)
 {
     return new EngineStateChangedEventArgs(
         EngineStateChangeType.AnimalTeleported,
         string.Format("A new {0} arrived at {1}", ((Species) organismState.Species).Name, DateTime.Now.TimeOfDay),
         string.Format("A new {0} was teleported into your world at {1}", ((Species) organismState.Species).Name,
                       DateTime.Now)
         );
 }
Exemple #12
0
        /// <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));
        }
Exemple #13
0
 /// <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();
 }
        internal MovementSegment(MovementSegment previous, OrganismState state, Point startingPoint, int entryTime, int gridX, int gridY)
        {
            Debug.Assert((previous == null && entryTime == 0) || (previous != null && entryTime != 0));

            this.State = state;
            this.StartingPoint = startingPoint;
            this.EntryTime = entryTime;
            this.GridX = gridX;
            this.GridY = gridY;
            this.Previous = previous;
        }
Exemple #15
0
        /// <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);
            }
        }
Exemple #16
0
        /// <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>
        ///  Determines if the given organism state is within teleport zone.
        /// </summary>
        /// <param name="state">The state being checked.</param>
        /// <returns>True if the state is in the zone, false otherwise.</returns>
        public Boolean Contains(OrganismState state)
        {
            var difference = _rectangle.Left - (state.Position.X - state.Radius);
            if (difference < 0)
            {
                // Negative means rectangle boundary < state boundary
                if (-difference > _rectangle.Width + 1)
                {
                    // X isn't overlapping or adjacent
                    return false;
                }
            }
            else
            {
                // state boundary <=  rectangle boundary
                if (difference > (state.Radius*2) + 1)
                {
                    // X isn't overlapping or adjacent
                    return false;
                }
            }

            difference = _rectangle.Top - (state.Position.Y - state.Radius);
            if (difference < 0)
            {
                // Negative means rectangle boundary < state boundary
                if (-difference > _rectangle.Height + 1)
                {
                    // Y isn't overlapping or adjacent
                    return false;
                }
            }
            else
            {
                // state boundary <=  rectangle boundary
                if (difference > (state.Radius*2) + 1)
                {
                    // Y isn't overlapping or adjacent
                    return false;
                }
            }

            return true;
        }
        /// <summary>
        ///  Should only be called by the GameEngine.
        /// </summary>
        /// <param name="state">The state of the organism to add.</param>
        public void AddOrganism(OrganismState state)
        {
            if (IsImmutable)
            {
                throw new ApplicationException("WorldState must be mutable to add organisms.");
            }

            Debug.Assert(state.GridX >= 0 && state.GridX < _gridWidth && state.GridY >= 0 && state.GridY < _gridHeight);
            Debug.Assert(_cellOrganisms[state.GridX, state.GridY] == null);

            if (_organisms.ContainsKey(state.ID))
            {
                throw new OrganismAlreadyExistsException();
            }

            FillCells(state, state.GridX, state.GridY, state.CellRadius, false);

            // Lock the size and position since we've added it to the index and these shouldn't be changed now
            state.LockSizeAndPosition();

            _organisms.Add(state.ID, state);
        }
        /// <summary>
        ///  Fills in the appropriate grid cells in our CellIndex given the organism state.
        /// </summary>
        /// <param name="state">The state of the organism being added.</param>
        /// <param name="cellX">The location of the organism in cells.</param>
        /// <param name="cellY">The location of the organism in cells.</param>
        /// <param name="cellRadius">The radius in cells of the organism.</param>
        /// <param name="clear">Determines if cells should be cleared or set.</param>
        public void FillCells(OrganismState state, int cellX, int cellY, int cellRadius, Boolean clear)
        {
            Debug.Assert(cellX - cellRadius >= 0 && cellY - cellRadius + 1 >= 0);

            for (var x = cellX - cellRadius; x <= cellX + cellRadius; x++)
            {
                for (var y = cellY - cellRadius; y <= cellY + cellRadius; y++)
                {
                    if (clear)
                    {
                        // Make sure we are only clearing ourselves, the value may be null because clearindex
                        // may have been called
                        if (!(_cellOrganisms[x, y] == null || _cellOrganisms[x, y].ID == state.ID))
                        {
                            Debug.Assert(_cellOrganisms[x, y] == null || _cellOrganisms[x, y].ID == state.ID);
                        }
                        _cellOrganisms[x, y] = null;
                    }
                    else
                    {
                        // Make sure there was no one else here
                        if (!(_cellOrganisms[x, y] == null))
                        {
                            Debug.Assert(_cellOrganisms[x, y] == null);
                        }
                        _cellOrganisms[x, y] = state;
                    }
                }
            }
        }
 /// <internal/>
 public MoveCompletedEventArgs(int actionID, Action action, ReasonForStop reason,
                               OrganismState blockingOrganism) : base(actionID, action)
 {
     Reason           = reason;
     BlockingOrganism = blockingOrganism;
 }
Exemple #21
0
        /// <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>
        ///  Make sure the organism only overlaps itself and not other organisms.
        /// </summary>
        /// <param name="state">The state of the organism to check.</param>
        /// <returns>True if the creature is safe, false otherwise.</returns>
        public Boolean OnlyOverlapsSelf(OrganismState state)
        {
            Debug.Assert(this.IndexBuilt);

            int minGridX = state.GridX - state.CellRadius;
            int maxGridX = state.GridX + state.CellRadius;
            int minGridY = state.GridY - state.CellRadius;
            int maxGridY = state.GridY + state.CellRadius;

            // If it would be out of bounds, return false.
            if (minGridX < 0 || maxGridX > gridWidth - 1 ||
                minGridY < 0 || maxGridY > gridHeight - 1)
            {
                return false;
            }

            for (int x = minGridX; x <= maxGridX; x++)
            {
                for (int y = minGridY; y <= maxGridY; y++)
                {
                    if (CellOrganisms[x,y] != null)
                    {
                        if (CellOrganisms[x,y].ID != state.ID)
                        {
                            return false;
                        }
                    }
                }
            }

            return true;
        }
Exemple #23
0
        /// <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>
 ///  Creates a new KilledOrganism based on information in an OrganismState.
 /// </summary>
 /// <param name="state">The state object that ID and death reason will be pulled from.</param>
 public KilledOrganism(OrganismState state)
 {
     this.id = state.ID;
     this.deathReason = state.DeathReason;
 }
Exemple #25
0
 /// <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));
 }
Exemple #26
0
 /// <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>
        ///  Find a list of organisms within the view of the given organism.
        /// </summary>
        /// <param name="state">The state of the organism to check.</param>
        /// <param name="radius">The radius of vision.</param>
        /// <returns>A list of found organisms.</returns>
        public ArrayList FindOrganismsInView(OrganismState state, int radius)
        {
            Debug.Assert(IndexBuilt);

            // Make sure we have enough space in our visibility matrix
            Debug.Assert((state.CellRadius + radius)*2 + 1 <= _invisible.GetLength(0));

            var foundOrganisms = new ArrayList();
            var foundHash = new Hashtable();
            var originX = state.GridX;
            var originY = state.GridY;
            var middleX = -originX + state.CellRadius + radius;
            var middleY = -originY + state.CellRadius + radius;
            int xIncrement = 0, yIncrement = 0;

            // The first ring is all visible
            var currentRadius = state.CellRadius + 1;
            var currentX = originX - currentRadius;
            var currentY = originY - currentRadius;
            for (var side = 0; side < 4; side++)
            {
                switch (side)
                {
                    case 0:
                        xIncrement = 1;
                        yIncrement = 0;
                        break;
                    case 1:
                        xIncrement = 0;
                        yIncrement = 1;
                        break;
                    case 2:
                        xIncrement = -1;
                        yIncrement = 0;
                        break;
                    case 3:
                        xIncrement = 0;
                        yIncrement = -1;
                        break;
                }

                for (var count = 0; count < currentRadius << 1; count++)
                {
                    if (currentX >= 0 && currentY >= 0 && currentX < _gridWidth && currentY < _gridHeight)
                    {
                        var currentOrganism = _cellOrganisms[currentX, currentY];
                        if (currentOrganism != null)
                        {
                            if (foundHash[currentOrganism] == null)
                            {
                                foundHash[currentOrganism] = currentOrganism;
                                foundOrganisms.Add(currentOrganism);
                            }
                        }

                        _invisible[currentX + middleX, currentY + middleY] = 0;
                    }

                    currentX += xIncrement;
                    currentY += yIncrement;
                }
            }

            for (currentRadius = state.CellRadius + 2; currentRadius <= state.CellRadius + radius; currentRadius++)
            {
                // Look at each point on a square of radius currentRadius
                // Look at the two points that are between this point and the origin
                // if they are invisible, this point is invisible

                // p1 is in the diagonal direction from [x,y] to [originX,originY] and
                // p2 is in the horizontal/vertical direction from [x,y] to [originX, originY].
                // p2 collapses to point_1 if j = 0 or i = 0
                currentX = originX - currentRadius;
                currentY = originY - currentRadius;
                for (var side = 0; side < 4; side++)
                {
                    switch (side)
                    {
                        case 0:
                            xIncrement = 1;
                            yIncrement = 0;
                            break;
                        case 1:
                            xIncrement = 0;
                            yIncrement = 1;
                            break;
                        case 2:
                            xIncrement = -1;
                            yIncrement = 0;
                            break;
                        case 3:
                            xIncrement = 0;
                            yIncrement = -1;
                            break;
                    }

                    for (var count = 0; count < currentRadius << 1; count++)
                    {
                        if (currentX >= 0 && currentY >= 0 && currentX < _gridWidth && currentY < _gridHeight)
                        {
                            var i = currentX - originX;
                            var j = currentY - originY;

                            // These actually calculate -1 * sign not just the sign function
                            int signI;
                            if (i < 0)
                            {
                                signI = 1;
                            }
                            else if (i > 0)
                            {
                                signI = -1;
                            }
                            else
                            {
                                signI = 0;
                            }

                            int signJ;
                            if (j < 0)
                            {
                                signJ = 1;
                            }
                            else if (j > 0)
                            {
                                signJ = -1;
                            }
                            else
                            {
                                signJ = 0;
                            }

                            int absI;
                            if (i < 0)
                            {
                                absI = -i;
                            }
                            else
                            {
                                absI = i;
                            }

                            int absJ;
                            if (j < 0)
                            {
                                absJ = -j;
                            }
                            else
                            {
                                absJ = j;
                            }

                            // Check first point which is the diagonal direction from [x,y] to [originX,originY]
                            int p1X;
                            int p1Y;
                            if (absJ > absI)
                            {
                                // We are in the  90 < theta < 45 degrees region of every quadrant
                                p1X = currentX;
                                p1Y = signJ + currentY;
                            }
                            else
                            {
                                p1X = signI + currentX;
                                p1Y = signJ + currentY;
                            }

                            // Check second point
                            // if Abs(j) == Abs(i) then we are on a diagonal, so secondpoint is the same as first point
                            int p2X;
                            int p2Y;
                            if (absJ != absI)
                            {
                                p2X = signI + currentX;
                                p2Y = signJ + currentY;
                            }
                            else
                            {
                                p2X = p1X;
                                p2Y = p1Y;
                            }

                            // if p1 or p2 was invisible or they were something that blocks visibility
                            if (_invisible[p1X + middleX, p1Y + middleY] == 1 ||
                                _invisible[p2X + middleX, p2Y + middleY] == 1)
                            {
                                _invisible[currentX + middleX, currentY + middleY] = 1;
                            }
                            else
                            {
                                var currentOrganism = _cellOrganisms[currentX, currentY];
                                if (currentOrganism != null)
                                {
                                    // if there is an organism here, mark this spot as invisible
                                    // (even though it really isn't)
                                    // so the outer cells will be invisible too
                                    _invisible[currentX + middleX, currentY + middleY] = 1;

                                    if (foundHash[currentOrganism] == null)
                                    {
                                        foundHash[currentOrganism] = currentOrganism;
                                        foundOrganisms.Add(currentOrganism);
                                    }
                                }
                                else
                                {
                                    _invisible[currentX + middleX, currentY + middleY] = 0;
                                }
                            }
                        }

                        currentX += xIncrement;
                        currentY += yIncrement;
                    }
                }
            }

            return foundOrganisms;
        }
Exemple #28
0
        /// <summary>
        ///  Can be called with an OrganismState that needs to be teleported.
        ///  Cannot be called during MoveAnimals since it passes true to the clearOld
        ///  argument in RemoveOrganism.
        /// </summary>
        /// <param name="state">The state of the creature to be teleported.</param>
        public void Teleport(OrganismState state)
        {
            if (null == state)
            {
                throw new Exception("Null object passed into Teleport");
            }

            TeleportState teleportState = new TeleportState();

            Organism organism = Scheduler.GetOrganism(state.ID);
            state.MakeImmutable();
            teleportState.OrganismState = state;
            teleportState.Organism = organism;
            teleportState.OrganismWrapper = new OrganismWrapper(organism);
            teleportState.Originator = _newWorldState.StateGuid;
            teleportState.Country = GameConfig.UserCountry;
            teleportState.State = GameConfig.UserState;

            // Remove it from this world
            removeOrganism(new KilledOrganism(state.ID, PopulationChangeReason.TeleportedFrom));

            // Teleport the organism through the network engine
            if (_usingNetwork)
            {
                _networkEngine.Teleport(teleportState);
            }
            else
            {
                ReceiveTeleportation(teleportState, true);
            }
        }
        /// <summary>
        ///  Uses the bounding box computation methods to compute a
        ///  box that can be printed within the graphics engine.  This
        ///  is used for debugging creature pathing.
        /// </summary>
        /// <param name="orgState">The state of the creature to compute a bounding box for.</param>
        /// <returns>A bounding box.</returns>
        private Rectangle GetBoundsOfState(OrganismState orgState)
        {
            var origin = orgState.Position;
            var cellRadius = orgState.CellRadius;

            var p1 = new Point(
                (origin.X >> 3)*8,
                (origin.Y >> 3)*8
                );

            var bounds = new Rectangle(
                p1.X - (cellRadius*8),
                p1.Y - (cellRadius*8),
                (((cellRadius*2 + 1)*8) - 1),
                (((cellRadius*2 + 1)*8) - 1)
                );

            return bounds;
        }
        /// <summary>
        ///  Provides the same features as LookFor, except does not take camouflage
        ///  into account.
        /// </summary>
        /// <param name="organismState">The organism state that needs to be updated.</param>
        /// <returns>An updated state if the creature is still alive and within range, null otherwise.</returns>
        /// <internal/>
        public OrganismState LookForNoCamouflage(OrganismState organismState)
        {
            if (organismState != null)
            {
                var worldState = AppMgr.CurrentScheduler.CurrentState;

                organismState = worldState.GetOrganismState(organismState.ID);
                OrganismState thisOrganism = CurrentAnimalState;

                if (organismState == null ||
                    !thisOrganism.IsWithinRect(((AnimalSpecies) thisOrganism.Species).EyesightRadius, organismState))
                {
                    organismState = null;
                }
            }

            return organismState;
        }
        /// <summary>
        ///  Should only be called by the game engine.  Should be called if the state
        ///  of the organism changes.
        /// </summary>
        /// <param name="state">The state of the organism to refresh.</param>
        public void RefreshOrganism(OrganismState state)
        {
            if (IsImmutable)
            {
                throw new ApplicationException("WorldState must be mutable to change.");
            }

            var organismID = state.ID;

            // Clear the index if it's built
            if (IndexBuilt)
            {
                var oldState = GetOrganismState(organismID);
                FillCells(oldState, oldState.GridX, oldState.GridY, oldState.CellRadius, true);
            }

            _organisms.Remove(organismID);
            AddOrganism(state);
        }
        /// <summary>
        ///  Make sure the organism only overlaps itself and not other organisms.
        /// </summary>
        /// <param name="state">The state of the organism to check.</param>
        /// <returns>True if the creature is safe, false otherwise.</returns>
        public Boolean OnlyOverlapsSelf(OrganismState state)
        {
            Debug.Assert(IndexBuilt);

            var minGridX = state.GridX - state.CellRadius;
            var maxGridX = state.GridX + state.CellRadius;
            var minGridY = state.GridY - state.CellRadius;
            var maxGridY = state.GridY + state.CellRadius;

            // If it would be out of bounds, return false.
            if (minGridX < 0 || maxGridX > _gridWidth - 1 ||
                minGridY < 0 || maxGridY > _gridHeight - 1)
            {
                return false;
            }

            for (var x = minGridX; x <= maxGridX; x++)
            {
                for (var y = minGridY; y <= maxGridY; y++)
                {
                    if (_cellOrganisms[x, y] == null) continue;
                    if (_cellOrganisms[x, y].ID != state.ID)
                    {
                        return false;
                    }
                }
            }

            return true;
        }
Exemple #33
0
        /// <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);
        }
Exemple #34
0
 /// <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;
 }
Exemple #35
0
        /// <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);
            }
        }
Exemple #36
0
        /// <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);
        }
Exemple #37
0
        /// <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);
        }
Exemple #38
0
        /// <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;
        }
        internal void SelectObject(OrganismState state)
        {
            if (formClosed)
            {
                return;
            }

            comboBox.Items.Add(new OrganismComboItem(state));
            if (comboBox.Items.Count == 1)
            {
                comboBox.SelectedIndex = 0;
            }
            RefreshGrid();
        }
        /// <summary>
        ///  Initializes a new organism state by computed and
        ///  attaching a TerrariumSprite class that can be used
        ///  to control on screen movement, animation skins, and
        ///  selection.
        /// </summary>
        /// <param name="orgState">The organism state to attach the sprite animation information to.</param>
        private void InitOrganism(OrganismState orgState)
        {
            var tsSprite = new TerrariumSprite();
            tsSprite.CurFrame = 0;
            tsSprite.CurFrameDelta = 1;

            var species = orgState.Species;
            if (species is AnimalSpecies)
            {
                tsSprite.SpriteKey = ((AnimalSpecies) species).Skin;
                tsSprite.SkinFamily = ((AnimalSpecies) species).SkinFamily.ToString();
                tsSprite.IsPlant = false;

                if (tsSprite.SpriteKey == null && tsSprite.SkinFamily == null)
                {
                    tsSprite.SpriteKey = AnimalSkinFamily.Spider.ToString(); // This will be our default
                }
            }
            else
            {
                tsSprite.SpriteKey = ((PlantSpecies) species).Skin;
                tsSprite.SkinFamily = ((PlantSpecies) species).SkinFamily.ToString();
                tsSprite.IsPlant = true;

                if (tsSprite.SpriteKey == null && tsSprite.SkinFamily == null)
                {
                    tsSprite.SpriteKey = PlantSkinFamily.Plant.ToString(); // This will be our default
                }
            }

            tsSprite.XPosition = orgState.Position.X;
            tsSprite.YPosition = orgState.Position.Y;
            tsSprite.PreviousAction = orgState.PreviousDisplayAction;
            orgState.RenderInfo = tsSprite;
        }
        internal void UnselectObject(OrganismState state)
        {
            if (formClosed)
            {
                return;
            }

            UnselectObject(state.ID);
        }
Exemple #42
0
        /// <summary>
        ///  Subtracts an organism from the count of organisms.  Depending on the 
        ///  organism type either plants or animals will be decremented.
        /// </summary>
        /// <param name="state">The state of the creature.</param>
        /// <param name="reason">The reason the creature is being removed.</param>
        private void uncountOrganism(OrganismState state, PopulationChangeReason reason)
        {
            Debug.Assert(state != null);

            _populationData.UncountOrganism(((Species) state.Species).Name, reason);
            if (state is AnimalState)
            {
                _animalCount--;
            }
            else
            {
                _plantCount--;
            }
        }
 public OrganismComboItem(OrganismState o)
 {
     this.id = o.ID;
     this.name = ((Species) o.Species).Name;
     this.text = this.name + " - " + this.id;
 }