internal void UnselectOrganism(OrganismState state) { if (showTraces.Checked) { RemoveTrace(state); } }
/// <internal/> public MoveCompletedEventArgs(int actionID, Action action, ReasonForStop reason, OrganismState blockingOrganism) : base(actionID, action) { Reason = reason; BlockingOrganism = blockingOrganism; }
private void Update() { switch (OrgState) { case OrganismState.CHASING_FOOD: { if (velocity.sqrMagnitude > (maxStamina - 1)) { Debug.Log("Stamina Depleting"); stamina -= Time.deltaTime * 10f; } else { if (stamina < maxStamina) { stamina += Time.deltaTime * 10f; } } if (stamina < 0) { Debug.Log("Stamina is less than zero"); state = OrganismState.REST; } else if (stamina > (maxStamina / 2)) { // Should Help restore last state } break; } } }
/// <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); }
/// <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 void SelectOrganism(OrganismState state) { if (showTraces.Checked) { AddTrace(state); } }
/// <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"); } var targetOrganism = LookForNoCamouflage(organismState); if (targetOrganism != null) { if (targetOrganism is AnimalState) { // See if the camouflage hides it var invisible = Organism.OrganismRandom.Next(1, 100); if (invisible <= ((AnimalSpecies)targetOrganism.Species).InvisibleOdds) { Organism.WriteTrace("#Camouflage hid animal from organism"); return(null); } } return(targetOrganism); } return(null); }
/// <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) )); }
private void ChangeAndCacheState(OrganismState newState) { if (state != newState) { lastState = state; state = newState; } }
/// <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); _state = state; _dna = dna; }
/// <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); }
private static void ReleaseEnergy(ExperimentTurn experimentTurn, OrganismState organismState, decimal delta) { Claws.AtLeast(() => delta, 0); delta = Math.Min(delta, organismState.Health); organismState.Health -= delta; experimentTurn.ExtraEnergy += delta; }
private void RemoveTrace(OrganismState state) { Organism organism = GameEngine.Current.Scheduler.GetOrganism(state.ID); if (organism != null) { organism.Trace -= new TraceEventHandler(TraceEvent); } }
/// <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> /// 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) )); }
/// <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> /// 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)); }
private static void AbsorbEnergy(ExperimentTurn experimentTurn, OrganismState organismState, decimal delta) { Claws.AtLeast(() => delta, 0); delta = Math.Min(delta, Math.Min(experimentTurn.ExtraEnergy, 1 - organismState.Health)); experimentTurn.ExtraEnergy -= delta; organismState.Health += delta; }
internal void UnselectObject(OrganismState state) { if (formClosed) { return; } UnselectObject(state.ID); }
/// <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 MovementSegment(MovementSegment previous, OrganismState state, Point startingPoint, int entryTime, int gridX, int gridY) { Debug.Assert((previous == null && entryTime == 0) || (previous != null && entryTime != 0)); State = state; StartingPoint = startingPoint; EntryTime = entryTime; GridX = gridX; GridY = gridY; Previous = previous; }
/// <summary> /// Determines if a given creature exists within any of the teleport /// zones and if so notifies the caller. /// </summary> /// <param name="state">The organism state to be checked</param> /// <returns>True if the organism is in the teleporter, false otherwise.</returns> public Boolean IsInTeleporter(OrganismState state) { foreach (var teleportZone in _teleportZones) { if (teleportZone.Contains(state)) { return(true); } } return(false); }
internal void SelectObject(OrganismState state) { if (formClosed) { return; } comboBox.Items.Add(new OrganismComboItem(state)); if (comboBox.Items.Count == 1) { comboBox.SelectedIndex = 0; } RefreshGrid(); }
/// <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> /// 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> /// Finds all organisms within a range of cells. /// </summary> /// <param name="minGridX">Leftmost grid cell</param> /// <param name="maxGridX">Rightmost grid cell</param> /// <param name="minGridY">Topmost grid cell</param> /// <param name="maxGridY">Bottommost grid cell</param> /// <returns>A list of organisms within the cell range.</returns> public ArrayList FindOrganismsInCells(int minGridX, int maxGridX, int minGridY, int maxGridY) { Debug.Assert(IndexBuilt); Debug.Assert(minGridX <= maxGridX && minGridY <= maxGridY); Debug.Assert(minGridX >= 0 && maxGridX < _gridWidth && minGridY >= 0 && maxGridY < _gridHeight); OrganismState lastFound = null; // Since organisms are represented at multiple places in the grid, make // sure we only get one instance var foundHash = new Hashtable(); var foundOrganisms = new ArrayList(); for (var x = minGridX; x <= maxGridX; x++) { for (var y = minGridY; y <= maxGridY; y++) { var current = _cellOrganisms[x, y]; if (current == null) { continue; } // If it's the same as the last one, skip the hashable lookup // since it's expensive and we'll often find the same organism over and over // in a row if (lastFound != null && lastFound == current) { continue; } if (foundHash[current] == null) { foundHash[current] = current; foundOrganisms.Add(current); } lastFound = current; } } return(foundOrganisms); }
/// <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); }
public static void SaveOrganismState(this SqlConnection sqlConnection, OrganismState organismState) { var sqlCommand = new SqlCommand(createOrganismStateCommand, sqlConnection); var organismIdParameter = sqlCommand.Parameters.Add("@OrganismId", SqlDbType.BigInt); organismIdParameter.SqlValue = organismState.OrganismId; var experimentTurnIdParameter = sqlCommand.Parameters.Add("@ExperimentTurnId", SqlDbType.BigInt); experimentTurnIdParameter.SqlValue = organismState.ExperimentTurnId; var xParameter = sqlCommand.Parameters.Add("@X", SqlDbType.Int); xParameter.SqlValue = organismState.Position.X; var yParameter = sqlCommand.Parameters.Add("@Y", SqlDbType.Int); yParameter.SqlValue = organismState.Position.Y; var healthParameter = sqlCommand.Parameters.Add("@Health", SqlDbType.Decimal); healthParameter.SqlValue = organismState.Health; organismState.Id = sqlCommand.ReadResults(reader => reader.GetInt64(0)).Single(); }
public void ClipSegment(OrganismState blocker) { var segment = this; Debug.Assert(segment.Previous != null); segment.Previous.BlockedByState = blocker; while (segment != null) { // the starting segment should never get clipped, therefore there should always be // a previous segment Debug.Assert(segment.Previous != null); segment.Previous.Next = null; // Once one cell clips it, it doesn't matter what the other cells get, they are clipped as well segment.CellsLeftToResolve = 0; // Clip all subsequent segments segment = segment.Next; } }
/// <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); }