private static bool Path(CreatureMovement mover, Voxel start, GoalRegion goal, ChunkManager chunks, int maxExpansions, ref List<Creature.MoveAction> toReturn, bool reverse) { VoxelChunk startChunk = chunks.ChunkData.ChunkMap[start.ChunkID]; VoxelChunk endChunk = chunks.ChunkData.ChunkMap[goal.GetVoxel().ChunkID]; if(startChunk.IsCompletelySurrounded(start) || endChunk.IsCompletelySurrounded(goal.GetVoxel())) { toReturn = null; return false; } HashSet<Voxel> closedSet = new HashSet<Voxel>(); HashSet<Voxel> openSet = new HashSet<Voxel> { start }; Dictionary<Voxel, Creature.MoveAction> cameFrom = new Dictionary<Voxel, Creature.MoveAction>(); Dictionary<Voxel, float> gScore = new Dictionary<Voxel, float>(); PriorityQueue<Voxel> fScore = new PriorityQueue<Voxel>(); gScore[start] = 0.0f; fScore.Enqueue(start, gScore[start] + Heuristic(start, goal.GetVoxel())); int numExpansions = 0; List<Voxel> manhattanNeighbors = new List<Voxel>(6); for (int i = 0; i < 6; i++) { manhattanNeighbors.Add(new Voxel()); } while(openSet.Count > 0 && numExpansions < maxExpansions) { Voxel current = GetVoxelWithMinimumFScore(fScore, openSet); if (current == null) { current = start; numExpansions++; } numExpansions++; if (goal.IsInGoalRegion(current)) { Creature.MoveAction first = new Creature.MoveAction() { Voxel = current, MoveType = Creature.MoveType.Walk }; toReturn = ReconstructPath(cameFrom, first); return true; } openSet.Remove(current); closedSet.Add(current); VoxelChunk currentChunk = chunks.ChunkData.ChunkMap[current.ChunkID]; List<Creature.MoveAction> neighbors = null; neighbors = mover.GetMoveActions(current); currentChunk.GetNeighborsManhattan(current, manhattanNeighbors); if(manhattanNeighbors.Contains(goal.GetVoxel())) { Creature.MoveAction first = new Creature.MoveAction() { Voxel = current, MoveType = Creature.MoveType.Walk }; Creature.MoveAction last = new Creature.MoveAction() { Voxel = goal.GetVoxel(), MoveType = Creature.MoveType.Walk }; List<Creature.MoveAction> subPath = ReconstructPath(cameFrom, first); subPath.Add(last); toReturn = subPath; return true; } foreach(Creature.MoveAction n in neighbors) { if(closedSet.Contains(n.Voxel)) { continue; } float tenativeGScore = gScore[current] + GetDistance(current, n.Voxel, n.MoveType, chunks); if(openSet.Contains(n.Voxel) && !(tenativeGScore < gScore[n.Voxel])) { continue; } openSet.Add(n.Voxel); Creature.MoveAction cameAction = n; cameAction.Voxel = current; cameFrom[n.Voxel] = cameAction; gScore[n.Voxel] = tenativeGScore; fScore.Enqueue(n.Voxel, gScore[n.Voxel] + Heuristic(n.Voxel, goal.GetVoxel())); } if(numExpansions >= maxExpansions) { return false; } } toReturn = null; return false; }
public List<Creature.MoveAction> GetMoveActions(Voxel voxel) { List<Creature.MoveAction> toReturn = new List<Creature.MoveAction>(); CollisionManager objectHash = PlayState.ComponentManager.CollisionManager; Voxel[,,] neighborHood = GetNeighborhood(voxel); int x = (int)voxel.GridPosition.X; int y = (int)voxel.GridPosition.Y; int z = (int)voxel.GridPosition.Z; bool inWater = (neighborHood[1, 1, 1] != null && neighborHood[1, 1, 1].WaterLevel > 5); bool standingOnGround = (neighborHood[1, 0, 1] != null && !neighborHood[1, 0, 1].IsEmpty); bool topCovered = (neighborHood[1, 2, 1] != null && !neighborHood[1, 2, 1].IsEmpty); bool hasNeighbors = HasNeighbors(neighborHood); List<Creature.MoveAction> successors = new List<Creature.MoveAction>(); //Climbing ladders IEnumerable<IBoundedObject> objectsInside = objectHash.Hashes[CollisionManager.CollisionType.Static].GetItems( new Point3(MathFunctions.FloorInt(voxel.Position.X), MathFunctions.FloorInt(voxel.Position.Y), MathFunctions.FloorInt(voxel.Position.Z))); bool blockedByObject = false; if (objectsInside != null) { var bodies = objectsInside.OfType<GameComponent>(); var enumerable = bodies as IList<GameComponent> ?? bodies.ToList(); // TODO: This is supposed to be done when the door is a NEIGHBOR of this voxel only!! foreach (GameComponent body in enumerable) { Door door = body.GetRootComponent().GetChildrenOfType<Door>(true).FirstOrDefault(); if (door != null) { if ( PlayState.Diplomacy.GetPolitics(door.TeamFaction, Creature.Faction).GetCurrentRelationship() == Relationship.Hateful) { if (IsEmpty(neighborHood[0, 1, 1])) // +- x successors.Add(new Creature.MoveAction() { Diff = new Vector3(0, 1, 1), MoveType = Creature.MoveType.DestroyObject, InteractObject = door, Voxel = neighborHood[0, 1, 1] }); if (IsEmpty(neighborHood[2, 1, 1])) successors.Add(new Creature.MoveAction() { Diff = new Vector3(2, 1, 1), MoveType = Creature.MoveType.DestroyObject, InteractObject = door, Voxel = neighborHood[2, 1, 1] }); if (IsEmpty(neighborHood[1, 1, 0])) // +- z successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 1, 0), MoveType = Creature.MoveType.DestroyObject, InteractObject = door, Voxel = neighborHood[1, 1, 0] }); if (IsEmpty(neighborHood[1, 1, 2])) successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 1, 2), MoveType = Creature.MoveType.DestroyObject, InteractObject = door, Voxel = neighborHood[1, 1, 2] }); blockedByObject = true; } } } if (blockedByObject) { return successors; } if (CanClimb) { bool hasLadder = enumerable.Any(component => component.Tags.Contains("Climbable")); if (hasLadder) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 2, 1), MoveType = Creature.MoveType.Climb }); if (!standingOnGround) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 0, 1), MoveType = Creature.MoveType.Climb }); } standingOnGround = true; } } } if (standingOnGround || (CanSwim && inWater)) { Creature.MoveType moveType = inWater ? Creature.MoveType.Swim : Creature.MoveType.Walk; if (IsEmpty(neighborHood[0, 1, 1])) // +- x successors.Add(new Creature.MoveAction() { Diff = new Vector3(0, 1, 1), MoveType = moveType }); if (IsEmpty(neighborHood[2, 1, 1])) successors.Add(new Creature.MoveAction() { Diff = new Vector3(2, 1, 1), MoveType = moveType }); if (IsEmpty(neighborHood[1, 1, 0])) // +- z successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 1, 0), MoveType = moveType }); if (IsEmpty(neighborHood[1, 1, 2])) successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 1, 2), MoveType = moveType }); if (!hasNeighbors) { if (IsEmpty(neighborHood[2, 1, 2])) // +x + z successors.Add(new Creature.MoveAction() { Diff = new Vector3(2, 1, 2), MoveType = moveType }); if (IsEmpty(neighborHood[2, 1, 0])) successors.Add(new Creature.MoveAction() { Diff = new Vector3(2, 1, 0), MoveType = moveType }); if (IsEmpty(neighborHood[0, 1, 2])) // -x -z successors.Add(new Creature.MoveAction() { Diff = new Vector3(0, 1, 2), MoveType = moveType }); if (IsEmpty(neighborHood[0, 1, 0])) successors.Add(new Creature.MoveAction() { Diff = new Vector3(0, 1, 0), MoveType = moveType }); } } if (!topCovered && (standingOnGround || (CanSwim && inWater))) { for (int dx = 0; dx <= 2; dx++) { for (int dz = 0; dz <= 2; dz++) { if (dx == 1 && dz == 1) continue; if (!IsEmpty(neighborHood[dx, 1, dz])) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(dx, 2, dz), MoveType = Creature.MoveType.Jump }); } } } } // Falling if (!inWater && !standingOnGround) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 0, 1), MoveType = Creature.MoveType.Fall }); } if (CanFly) { for (int dx = 0; dx <= 2; dx++) { for (int dz = 0; dz <= 2; dz++) { for (int dy = 0; dy <= 2; dy++) { if (dx == 1 && dz == 1 && dy == 1) continue; if (IsEmpty(neighborHood[dx, 1, dz])) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(dx, dy, dz), MoveType = Creature.MoveType.Fly }); } } } } } foreach (Creature.MoveAction v in successors) { Voxel n = neighborHood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z]; if (n != null && (n.IsEmpty || n.WaterLevel > 0)) { Creature.MoveAction newAction = v; newAction.Voxel = n; toReturn.Add(newAction); } } return toReturn; }
private static bool Path(CreatureMovement mover, Voxel start, GoalRegion goal, ChunkManager chunks, int maxExpansions, ref List <Creature.MoveAction> toReturn, bool reverse, float weight) { if (!goal.IsPossible()) { toReturn = null; return(false); } HashSet <Voxel> closedSet = new HashSet <Voxel>(); HashSet <Voxel> openSet = new HashSet <Voxel> { start }; Dictionary <Voxel, Creature.MoveAction> cameFrom = new Dictionary <Voxel, Creature.MoveAction>(); Dictionary <Voxel, float> gScore = new Dictionary <Voxel, float>(); PriorityQueue <Voxel> fScore = new PriorityQueue <Voxel>(); gScore[start] = 0.0f; fScore.Enqueue(start, gScore[start] + weight * goal.Heuristic(start)); int numExpansions = 0; List <Voxel> manhattanNeighbors = new List <Voxel>(6); for (int i = 0; i < 6; i++) { manhattanNeighbors.Add(new Voxel()); } while (openSet.Count > 0 && numExpansions < maxExpansions) { Voxel current = GetVoxelWithMinimumFScore(fScore, openSet); if (current == null) { current = start; numExpansions++; } numExpansions++; if (goal.IsInGoalRegion(current)) { Creature.MoveAction first = new Creature.MoveAction() { Voxel = current, MoveType = Creature.MoveType.Walk }; toReturn = ReconstructPath(cameFrom, first); return(true); } openSet.Remove(current); closedSet.Add(current); VoxelChunk currentChunk = chunks.ChunkData.ChunkMap[current.ChunkID]; List <Creature.MoveAction> neighbors = null; neighbors = mover.GetMoveActions(current); currentChunk.GetNeighborsManhattan(current, manhattanNeighbors); if (manhattanNeighbors.Contains(goal.GetVoxel())) { Creature.MoveAction first = new Creature.MoveAction() { Voxel = current, MoveType = Creature.MoveType.Walk }; Creature.MoveAction last = new Creature.MoveAction() { Voxel = goal.GetVoxel(), MoveType = Creature.MoveType.Walk }; List <Creature.MoveAction> subPath = ReconstructPath(cameFrom, first); subPath.Add(last); toReturn = subPath; return(true); } foreach (Creature.MoveAction n in neighbors) { if (closedSet.Contains(n.Voxel)) { continue; } float tenativeGScore = gScore[current] + GetDistance(current, n.Voxel, n.MoveType, chunks); if (openSet.Contains(n.Voxel) && !(tenativeGScore < gScore[n.Voxel])) { continue; } openSet.Add(n.Voxel); Creature.MoveAction cameAction = n; cameAction.Voxel = current; cameFrom[n.Voxel] = cameAction; gScore[n.Voxel] = tenativeGScore; fScore.Enqueue(n.Voxel, gScore[n.Voxel] + weight * goal.Heuristic(n.Voxel)); } if (numExpansions >= maxExpansions) { return(false); } } toReturn = null; return(false); }
public static List <Creature.MoveAction> ReconstructPath(Dictionary <Voxel, Creature.MoveAction> cameFrom, Creature.MoveAction currentNode) { List <Creature.MoveAction> toReturn = new List <Creature.MoveAction>(); if (cameFrom.ContainsKey(currentNode.Voxel)) { toReturn.AddRange(ReconstructPath(cameFrom, cameFrom[currentNode.Voxel])); toReturn.Add(currentNode); return(toReturn); } else { toReturn.Add(currentNode); return(toReturn); } }
public IEnumerable <Status> AvoidTarget(float range, float time) { if (Target == null) { yield return(Status.Fail); yield break; } Timer avoidTimer = new Timer(time, true, Timer.TimerMode.Game); while (true) { avoidTimer.Update(DwarfTime.LastTime); if (avoidTimer.HasTriggered) { yield return(Status.Success); } float dist = (Target.Position - Agent.Position).Length(); if (dist > range) { yield return(Status.Success); yield break; } List <Creature.MoveAction> neighbors = Agent.Movement.GetMoveActions(Agent.Position); neighbors.Sort((a, b) => { if (a.Equals(b)) { return(0); } float da = (a.Voxel.Position - Target.Position).LengthSquared(); float db = (b.Voxel.Position - Target.Position).LengthSquared(); return(da.CompareTo(db)); }); neighbors.RemoveAll( a => a.MoveType == Creature.MoveType.Jump || a.MoveType == Creature.MoveType.Climb); if (neighbors.Count == 0) { yield return(Status.Fail); yield break; } Creature.MoveAction furthest = neighbors.Last(); bool reachedTarget = false; Timer timeout = new Timer(2.0f, true); while (!reachedTarget) { Vector3 output = Creature.Controller.GetOutput(DwarfTime.Dt, furthest.Voxel.Position + Vector3.One * 0.5f, Agent.Position); Creature.Physics.ApplyForce(output, DwarfTime.Dt); if (Creature.AI.Movement.CanFly) { Creature.Physics.ApplyForce(Vector3.Up * 10, DwarfTime.Dt); } timeout.Update(DwarfTime.LastTime); yield return(Status.Running); if (timeout.HasTriggered || (furthest.Voxel.Position - Agent.Position).Length() < 1) { reachedTarget = true; } Agent.Creature.CurrentCharacterMode = Creature.CharacterMode.Walking; } yield return(Status.Success); yield break; } }
public List <Creature.MoveAction> GetMoveActions(Voxel voxel) { List <Creature.MoveAction> toReturn = new List <Creature.MoveAction>(); CollisionManager objectHash = PlayState.ComponentManager.CollisionManager; Voxel[,,] neighborHood = GetNeighborhood(voxel); int x = (int)voxel.GridPosition.X; int y = (int)voxel.GridPosition.Y; int z = (int)voxel.GridPosition.Z; bool inWater = (neighborHood[1, 1, 1] != null && neighborHood[1, 1, 1].WaterLevel > 5); bool standingOnGround = (neighborHood[1, 0, 1] != null && !neighborHood[1, 0, 1].IsEmpty); bool topCovered = (neighborHood[1, 2, 1] != null && !neighborHood[1, 2, 1].IsEmpty); bool hasNeighbors = HasNeighbors(neighborHood); List <Creature.MoveAction> successors = new List <Creature.MoveAction>(); //Climbing ladders List <IBoundedObject> bodiesInside = objectHash.Hashes[CollisionManager.CollisionType.Static].GetItems( new Point3(MathFunctions.FloorInt(voxel.Position.X), MathFunctions.FloorInt(voxel.Position.Y), MathFunctions.FloorInt(voxel.Position.Z))); if (CanClimb && bodiesInside != null) { bool hasLadder = bodiesInside.OfType <GameComponent>() .Any(component => component.Tags.Contains("Climbable")); if (hasLadder) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 2, 1), MoveType = Creature.MoveType.Climb }); if (!standingOnGround) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 0, 1), MoveType = Creature.MoveType.Climb }); } standingOnGround = true; } } if (standingOnGround || (CanSwim && inWater)) { Creature.MoveType moveType = inWater ? Creature.MoveType.Swim : Creature.MoveType.Walk; if (IsEmpty(neighborHood[0, 1, 1])) { // +- x successors.Add(new Creature.MoveAction() { Diff = new Vector3(0, 1, 1), MoveType = moveType }); } if (IsEmpty(neighborHood[2, 1, 1])) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(2, 1, 1), MoveType = moveType }); } if (IsEmpty(neighborHood[1, 1, 0])) { // +- z successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 1, 0), MoveType = moveType }); } if (IsEmpty(neighborHood[1, 1, 2])) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 1, 2), MoveType = moveType }); } if (!hasNeighbors) { if (IsEmpty(neighborHood[2, 1, 2])) { // +x + z successors.Add(new Creature.MoveAction() { Diff = new Vector3(2, 1, 2), MoveType = moveType }); } if (IsEmpty(neighborHood[2, 1, 0])) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(2, 1, 0), MoveType = moveType }); } if (IsEmpty(neighborHood[0, 1, 2])) { // -x -z successors.Add(new Creature.MoveAction() { Diff = new Vector3(0, 1, 2), MoveType = moveType }); } if (IsEmpty(neighborHood[0, 1, 0])) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(0, 1, 0), MoveType = moveType }); } } } if (!topCovered && (standingOnGround || (CanSwim && inWater))) { for (int dx = 0; dx <= 2; dx++) { for (int dz = 0; dz <= 2; dz++) { if (dx == 1 && dz == 1) { continue; } if (!IsEmpty(neighborHood[dx, 1, dz])) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(dx, 2, dz), MoveType = Creature.MoveType.Jump }); } } } } // Falling if (!inWater && !standingOnGround) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(1, 0, 1), MoveType = Creature.MoveType.Fall }); } if (CanFly) { for (int dx = 0; dx <= 2; dx++) { for (int dz = 0; dz <= 2; dz++) { for (int dy = 0; dy <= 2; dy++) { if (dx == 1 && dz == 1 && dy == 1) { continue; } if (IsEmpty(neighborHood[dx, 1, dz])) { successors.Add(new Creature.MoveAction() { Diff = new Vector3(dx, dy, dz), MoveType = Creature.MoveType.Fly }); } } } } } foreach (Creature.MoveAction v in successors) { Voxel n = neighborHood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z]; if (n != null && (n.IsEmpty || n.WaterLevel > 0)) { Creature.MoveAction newAction = v; newAction.Voxel = n; toReturn.Add(newAction); } } return(toReturn); }