public static MazeNode FindPathEnd(MazeNode root) { MazeNode previous = new MazeNode(-1, -1); MazeNode current = root; bool currentChanged = false; int counter = 0; while (!previous.Equals(current) && counter < 1000) { foreach (MazeNode n in current.GetAdjacentNodes()) { if (n.OnExitPath && !n.Equals(previous)) { previous = current; current = n; currentChanged = true; break; } } if (!currentChanged) { previous = current; } currentChanged = false; counter++; } return(current); }
public static void setDirectionValuesHelper(MazeNode previous, MazeNode current) { foreach (MazeNode n in current.GetAdjacentNodes()) { int total = 1; if (!n.Equals(previous)) { setDirectionValuesHelper(current, n); total += n.forwardNodes; total += n.backwardNodes; total += n.leftNodes; total += n.rightNodes; } if (n.Equals(previous)) { total = 0; } if (n.Equals(current.Left)) { current.leftNodes = total; } else if (n.Equals(current.Right)) { current.rightNodes = total; } else if (n.Equals(current.Forward)) { current.forwardNodes = total; } else { current.backwardNodes = total; } } }
public static void setDirectionValues(MazeNode root) { foreach (MazeNode n in root.GetAdjacentNodes()) { int total = 1; setDirectionValuesHelper(root, n); total += n.forwardNodes; total += n.backwardNodes; total += n.leftNodes; total += n.rightNodes; if (n.Equals(root.Left)) { root.leftNodes = total; } else if (n.Equals(root.Right)) { root.rightNodes = total; } else if (n.Equals(root.Forward)) { root.forwardNodes = total; } else { root.backwardNodes = total; } } }
public static LinkedList <MazeNode> GetPathHelper(MazeNode start, MazeNode end, Stack visited) { List <MazeNode> adjacents = start.GetAdjacentNodes(); bool leftAvailable = (start.Left != null && !visited.Contains(start.Left)); bool rightAvailable = (start.Right != null && !visited.Contains(start.Right)); bool forwardAvailable = (start.Forward != null && !visited.Contains(start.Forward)); bool backwardAvailable = (start.Backward != null && !visited.Contains(start.Backward)); LinkedList <MazeNode> path = new LinkedList <MazeNode>(); if (start.Row == end.Row && start.Col == end.Col) { path.AddFirst(start); return(path); } if (!leftAvailable && !rightAvailable && !forwardAvailable && !backwardAvailable) { return(null); } foreach (MazeNode node in adjacents) { if (!visited.Contains(node)) { visited.Push(node); path = GetPathHelper(node, end, visited); if (path != null) { path.AddFirst(start); return(path); } } } return(null); }
public static int DistanceBetween2(MazeNode start, MazeNode finish) { Queue <MazeNode> next = new Queue <MazeNode>(); Queue <MazeNode> prev = new Queue <MazeNode>(); Queue <Stack <MazeNode> > visited = new Queue <Stack <MazeNode> >(); Queue <int> distances = new Queue <int>(); Stack <MazeNode> initial = new Stack <MazeNode>(); initial.Push(start); next.Enqueue(start); distances.Enqueue(0); prev.Enqueue(start); visited.Enqueue(initial); int count = 0; while (next.Count > 0) { MazeNode current = next.Dequeue(); MazeNode previous = prev.Dequeue(); Stack <MazeNode> vis = visited.Dequeue(); int distance = distances.Dequeue(); if (current.Col == finish.Col && current.Row == finish.Row && current.Floor == finish.Floor) { return(distance); } foreach (MazeNode n in current.GetAdjacentNodes()) { Stack <MazeNode> visited2 = vis; if (!vis.Contains(n)) { visited2.Push(n); next.Enqueue(n); distances.Enqueue(distance + 1); prev.Enqueue(current); visited.Enqueue(visited2); } } count++; } return(0); }
public static LinkedList <MazeNode> GetPath2(MazeNode start, MazeNode finish) { Queue <MazeNode> next = new Queue <MazeNode>(); Queue <MazeNode> prev = new Queue <MazeNode>(); Queue <LinkedList <MazeNode> > visited = new Queue <LinkedList <MazeNode> >(); LinkedList <MazeNode> initial = new LinkedList <MazeNode>(); initial.AddFirst(start); next.Enqueue(start); prev.Enqueue(start); visited.Enqueue(initial); int count = 0; while (next.Count > 0) { MazeNode current = next.Dequeue(); MazeNode previous = prev.Dequeue(); LinkedList <MazeNode> vis = visited.Dequeue(); if (current.Col == finish.Col && current.Row == finish.Row && current.Floor == finish.Floor) { return(vis); } foreach (MazeNode n in current.GetAdjacentNodes()) { LinkedList <MazeNode> visited2 = new LinkedList <MazeNode>(); foreach (MazeNode node in vis) { visited2.AddLast(node); } if (!vis.Contains(n)) { visited2.AddLast(n); next.Enqueue(n); prev.Enqueue(current); visited.Enqueue(visited2); } } count++; } return(null); }
public static MazeNode getNodeOnPath(MazeNode root, int index) { int current = 0; MazeNode node = root; MazeNode prev = root; while (current < index) { foreach (MazeNode n in node.GetAdjacentNodes()) { if (n.OnExitPath && !n.Equals(prev)) { current++; prev = node; node = n; break; } } } return(node); }
public static int DistanceBetweenHelper(List <MazeNode> prev, MazeNode current, MazeNode finish, int distance) { int branchDistance = 0; foreach (MazeNode n in current.GetAdjacentNodes()) { if (n.Equals(finish)) { return(distance + 1); } else if (!prev.Contains(n)) { prev.Add(current); int branchDistance2 = DistanceBetweenHelper(prev, n, finish, distance + 1); if (branchDistance2 > branchDistance) { branchDistance = branchDistance2; } } } return(branchDistance); }
public static List <MazeNode> nodesInSection(MazeNode root) { List <MazeNode> nodes = new List <MazeNode>(); Stack <MazeNode> visited = new Stack <MazeNode>(); visited.Push(root); nodes.Add(root); while (visited.Count > 0) { MazeNode current = visited.Pop(); foreach (MazeNode n in current.GetAdjacentNodes()) { if (!nodes.Contains(n)) { visited.Push(n); nodes.Add(n); } } } return(nodes); }
//function to execute in stalk state, contains transitions, and code to maintain distance from player and attempt to avoid being cornered void stalk() { posTimer = 30; posTimer2 = 25; if (AttackTimer > 0) { AttackTimer -= Time.deltaTime; } //print(AttackTimer); //attack timer reachers 0 attack if (AttackTimer <= 0) { State = InuState.Cornered; return; } AnimState = InuAnim.Creep; //rayDirection = playerTransform.position - transform.position; //rayDirection.y = 0; playerCloseToEnemy = Vector3.Distance(playerTransform.position, transform.position) < StalkDistance; if (!playerCloseToEnemy) { beenTooClose = false; seen = false; seen = SeeObject(PlayerObject, LevelMask, home); if (seen) { State = InuState.Chase; return; } foundFootprint = SeeFootprint(allNodes, LevelMask, home); if (foundFootprint != null) { State = InuState.Follow; return; } else if (StartingNode != null) { State = InuState.Patrol; return; } else { State = InuState.Idle; return; } } //check to see if player is close enough to trigger cornered state playerTooCloseToEnemy = Vector3.Distance(playerTransform.position, transform.position) < StartCorneredDistance; if (playerTooCloseToEnemy) { //signify the player is too close to the inu //print("too close"); beenTooClose = true; //get the distance from player to inu newdir = transform.position - playerTransform.position; //create containers for attempted destinations destinationNode = null; secondDestNode = null; tertDestNode = null; //get current node based on location currentLocation = new Vector3(transform.position.x, home.y + 1.5F, transform.position.z); fromNode = MazeGenerator.getNodeBasedOnLocation(currentLocation); //print("current location " + new Vector3(transform.position.x, home.y + 1.5F, transform.position.z)); //print("from node " + new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); //get the player's current node playerNode = MazeGenerator.getNodeBasedOnLocation(playerTransform.position); //if the change in x is greater than the change in z try to move in the x direction first if (Math.Abs(newdir.x) > Math.Abs(newdir.z)) { //if the change in x is positive if (newdir.x > 0) { //set primary destination to be the node with the next higher value in the x direction destinationNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col + 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); //if change in z is positive if (newdir.z > 0) { //set secondary destination to be the node with the next higher value in the z direction secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row + 1) * 6 + 8)); } if (newdir.z < 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row - 1) * 6 + 8)); } } if (newdir.x < 0) { destinationNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col - 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); if (newdir.z > 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row + 1) * 6 + 8)); } if (newdir.z < 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row - 1) * 6 + 8)); } } } //if the change in x is the same as the change in the z direction, used rand with two possible values if (Math.Abs(newdir.x) == Math.Abs(newdir.z)) { rand = UnityEngine.Random.Range(0, 1); if (rand == 0) { if (newdir.x > 0) { destinationNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col + 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); if (newdir.z > 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row + 1) * 6 + 8)); } if (newdir.z < 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row - 1) * 6 + 8)); } } if (newdir.x < 0) { destinationNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col - 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); if (newdir.z > 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row + 1) * 6 + 8)); } if (newdir.z < 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row - 1) * 6 + 8)); } } } if (rand == 1) { if (newdir.z > 0) { destinationNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row + 1) * 6 + 8)); if (newdir.x > 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col + 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); } if (newdir.x < 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col - 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); } } if (newdir.z < 0) { destinationNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row - 1) * 6 + 8)); if (newdir.x > 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col + 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); } if (newdir.x < 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col - 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); } } } } //if the change in x is less than the change in z try to move in the z direction first if (Math.Abs(newdir.x) < Math.Abs(newdir.z)) { if (newdir.z > 0) { destinationNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row + 1) * 6 + 8)); if (newdir.x > 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col + 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); } if (newdir.x < 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col - 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); } } if (newdir.z < 0) { destinationNode = MazeGenerator.getNodeBasedOnLocation(new Vector3(fromNode.Col * 6 + 8, fromNode.Floor * 30, (fromNode.Row - 1) * 6 + 8)); if (newdir.x > 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col + 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); } if (newdir.x < 0) { secondDestNode = MazeGenerator.getNodeBasedOnLocation(new Vector3((fromNode.Col - 1) * 6 + 8, fromNode.Floor * 30, fromNode.Row * 6 + 8)); } } } //get the list of nodes adjacent to the inu's current node adjacent = fromNode.GetAdjacentNodes(); for (int iter = 0; iter < adjacent.Count; iter++) { //if new node, it is recored as tertiary destination if (adjacent[iter] != destinationNode && adjacent[iter] != secondDestNode && adjacent[iter] != playerNode) { tertDestNode = adjacent[iter]; //check to see if tertiary is behind player and thus not valid inuToPlayer = playerTransform.position - transform.position; inuToTert = new Vector3(tertDestNode.Col * 6 + 8, tertDestNode.Floor * 30, tertDestNode.Row * 6 + 8) - transform.position; if (inuToPlayer.x > 0 && inuToTert.x > 0) { if (inuToPlayer.z > 0 && inuToTert.z > 0) { tertDestNode = null; } if (inuToPlayer.z < 0 && inuToTert.z < 0) { tertDestNode = null; } } if (inuToPlayer.x < 0 && inuToTert.x < 0) { if (inuToPlayer.z > 0 && inuToTert.z > 0) { tertDestNode = null; } if (inuToPlayer.z < 0 && inuToTert.z < 0) { tertDestNode = null; } } } } //check if primary and secondary are valid nodes if (adjacent.Contains(destinationNode) == false) { if (destinationNode != null) { //print("primary not adjacent " + new Vector3(destinationNode.Col * 6 + 8, fromNode.Floor * 30, destinationNode.Row * 6 + 8)); destinationNode = null; } else { //print("no primary dest found"); } } if (adjacent.Contains(secondDestNode) == false) { if (secondDestNode != null) { //print("secondary not adjacent " + new Vector3(secondDestNode.Col * 6 + 8, fromNode.Floor * 30, secondDestNode.Row * 6 + 8)); secondDestNode = null; } else { //print("no secondary dest found"); } } //try nodes in order if (destinationNode == null) { //print("primary not valid"); if (secondDestNode == null) { //print("secondary not valid"); if (tertDestNode == null) { //print("tertiary not valid"); //try to move backwards anyways newdir.y = 0; //normalize to get direction only newdir.Normalize(); //create a scalar scalar = (float)Math.Sqrt(15); //scale direction vector to set distace to go newdir.Scale(new Vector3(scalar, 1, scalar)); //set inu to go from current direction to scalar distance in normalized direction goal = playerTransform.position + newdir; wallDistance = newdir.magnitude; ray = new Ray(playerTransform.position, newdir); //if wall in the way transition to cornered if (Physics.Raycast(ray, out rayHit, wallDistance, LevelMask)) { State = InuState.Cornered; return; } //else move backwards away from player else { agent.ResetPath(); agent.SetDestination(goal); retreating = true; return; } } //move to tertiary destination else { //print("trying to go to tert " + new Vector3(tertDestNode.Col * 6 + 8, fromNode.Floor * 30, tertDestNode.Row * 6 + 8)); agent.ResetPath(); agent.SetDestination(new Vector3(tertDestNode.Col * 6 + 8, fromNode.Floor * 30, tertDestNode.Row * 6 + 8)); retreating = true; return; } } //move to secondary destination else { //print("trying to go to second " + new Vector3(secondDestNode.Col * 6 + 8, fromNode.Floor * 30, secondDestNode.Row * 6 + 8)); agent.ResetPath(); agent.SetDestination(new Vector3(secondDestNode.Col * 6 + 8, fromNode.Floor * 30, secondDestNode.Row * 6 + 8)); retreating = true; return; } } //move to primary destination else { print("trying to go to primary " + new Vector3(destinationNode.Col * 6 + 8, fromNode.Floor * 30, destinationNode.Row * 6 + 8)); agent.ResetPath(); agent.SetDestination(new Vector3(destinationNode.Col * 6 + 8, fromNode.Floor * 30, destinationNode.Row * 6 + 8)); retreating = true; return; } } //if player is not close enough for cornered if (!playerTooCloseToEnemy && beenTooClose == true) { retreating = false; beenTooClose = false; } //if not retrreating maintain distance from player if (retreating != true) { agent.ResetPath(); dest = playerTransform.position; if (Vector3.Distance(transform.position, dest) < 5) { agent.ResetPath(); agent.SetDestination(transform.position); } else { //print("stalking towards player"); agent.SetDestination(dest); } } //if player has tripper kill them, trip not currently implemented if (hasPlayerTripped()) { if (UnityEngine.XR.XRDevice.isPresent) { player = PlayerObject.GetComponentInParent <Actor>(); GameManager.Instance.ActorKilled(actorID, player); } else { GameManager.Instance.ActorKilled(actorID, PlayerObject.GetComponent <Actor>()); } GameManager.Instance.GameOver(); PlayerObject.SetActive(false); print("GameOver"); } }