private void moveAnimals()
{
// Move the teleporters if necessary
_newWorldState.Teleporter.Move();
GridIndex index = new GridIndex();
foreach (string organismID in _organismIDList)
{
OrganismState organismState = _newWorldState.GetOrganismState(organismID);
if (organismState == null) continue;
if (organismState is AnimalState)
{
AnimalState animalState = (AnimalState) organismState;
if (!animalState.IsStopped)
{
// Need to move
Vector vector = Vector.Subtract(animalState.Position,
animalState.CurrentMoveToAction.MovementVector.Destination);
Point newLocation;
Vector unitVector = vector.GetUnitVector();
if (vector.Magnitude <= animalState.CurrentMoveToAction.MovementVector.Speed)
{
// We've arrived
newLocation = animalState.CurrentMoveToAction.MovementVector.Destination;
}
else
{
Vector speedVector =
unitVector.Scale(animalState.CurrentMoveToAction.MovementVector.Speed);
newLocation = Vector.Add(animalState.Position, speedVector);
}
index.AddPath(animalState, animalState.Position, newLocation);
}
else
{
// Organism isn't moving but it needs to be added so that the grid is occupied
index.AddPath(animalState, animalState.Position, animalState.Position);
}
}
else
{
// Plants don't move but they need to be added so that the grid is occupied
index.AddPath(organismState, organismState.Position, organismState.Position);
}
}
index.ResolvePaths();
// The index contains the old positions. If you don't clear them, you will get collisions with old positions
_newWorldState.ClearIndex();
foreach (MovementSegment segment in index.StartSegments)
{
if (segment.IsStationarySegment)
{
OrganismState stationaryState = segment.State;
if (stationaryState.CurrentMoveToAction != null)
{
// This organism wanted to go where it already was, so -- destination reached
stationaryState.OrganismEvents.MoveCompleted =
new MoveCompletedEventArgs(stationaryState.CurrentMoveToAction.ActionID,
stationaryState.CurrentMoveToAction,
ReasonForStop.DestinationReached, null);
stationaryState.CurrentMoveToAction = null;
}
continue;
}
MovementSegment endSegment = segment;
// Find where the organism ended
while (endSegment.Next != null)
{
endSegment = endSegment.Next;
}
AnimalState newState = (AnimalState) endSegment.State;
Vector moveVector = Vector.Subtract(endSegment.EndingPoint, endSegment.State.Position);
newState.Position = endSegment.EndingPoint;
// Make sure we're ending up where we think we are
Debug.Assert(endSegment.GridX == newState.GridX && endSegment.GridY == newState.GridY);
newState.BurnEnergy(newState.EnergyRequiredToMove(moveVector.Magnitude,
newState.CurrentMoveToAction.MovementVector.Speed));
// Burning energy may have killed the organism, in which case we can't
// send it events because the CurrentMoveToAction is gone
if (!newState.IsAlive) continue;
if (endSegment.ExitTime != 0)
{
Debug.Assert(newState != null);
Debug.Assert(newState.CurrentMoveToAction != null);
// If where they landed wasn't where they wanted to go, then they got blocked. Stop movement and notify them
newState.OrganismEvents.MoveCompleted =
new MoveCompletedEventArgs(newState.CurrentMoveToAction.ActionID,
newState.CurrentMoveToAction, ReasonForStop.Blocked,
endSegment.BlockedByState);
newState.CurrentMoveToAction = null;
}
else if (endSegment.State.CurrentMoveToAction.MovementVector.Destination == newState.Position)
{
// Destination reached
newState.OrganismEvents.MoveCompleted =
new MoveCompletedEventArgs(newState.CurrentMoveToAction.ActionID,
newState.CurrentMoveToAction, ReasonForStop.DestinationReached,
null);
newState.CurrentMoveToAction = null;
}
}
_newWorldState.BuildIndex();
}