Neodroid  0.2.0
Machine Learning Environment Prototyping Tool
RandomWalk.cs
Go to the documentation of this file.
1 using System.Collections.Generic;
2 using UnityEngine;
3 
4 namespace droid.Runtime.Utilities.Sampling {
5  public class RandomWalk : MonoBehaviour //Self-Avoiding Random Walk algorithm
6  {
7  //How many steps do we want to take before we stop?
8  public int stepsToTake;
9 
10  //Final random walk positions
11  List<Vector3> _random_walk_positions;
12 
13  //The walk directions we can take
14  List<Vector3> _all_possible_directions = new List<Vector3> {
15  new Vector3(0f, 0f, 1f),
16  new Vector3(0f, 0f, -1f),
17  new Vector3(-1f, 0f, 0f),
18  new Vector3(1f, 0f, 0f)
19  };
20 
21  void Update() {
22  if (Input.GetKeyDown(KeyCode.Return)) {
23  this._random_walk_positions = this.GenerateSelfAvoidingRandomWalk();
24 
25  //Debug.Log(randomWalkPositions.Count);
26  }
27 
28  //Display the path with lines
29  if (this._random_walk_positions != null && this._random_walk_positions.Count > 1) {
30  for (var i = 1; i < this._random_walk_positions.Count; i++) {
31  Debug.DrawLine(this._random_walk_positions[i - 1], this._random_walk_positions[i]);
32  }
33  }
34  }
35 
36  public List<Vector3> GenerateSelfAvoidingRandomWalk() {
37  //Create the node we are starting from
38  var start_pos = Vector3.zero;
39 
40  var current_node = new WalkNode(start_pos, null, new List<Vector3>(this._all_possible_directions));
41 
42  //How many steps have we taken, so we know when to stop the algorithm
43  var steps_so_far = 0;
44 
45  //So we dont visit the same node more than once
46  var visited_nodes = new List<Vector3> {start_pos};
47 
48  while (true) {
49  //Check if we have walked enough steps
50  if (steps_so_far == this.stepsToTake) {
51  //Debug.Log("Found path");
52 
53  break;
54  }
55 
56  //Need to backtrack if we cant move in any direction from the current node
57  while (current_node._PossibleDirections.Count == 0) {
58  current_node = current_node._PreviousNode;
59 
60  //Dont need to remove nodes thats not a part of the final path from the list of visited nodes
61  //because there's no point in visiting them again because we know we cant find a path from those nodes
62 
63  steps_so_far -= 1;
64  }
65 
66  //Walk in a random direction from this node
67  var random_dir_pos = Random.Range(0, current_node._PossibleDirections.Count);
68 
69  var random_dir = current_node._PossibleDirections[random_dir_pos];
70 
71  //Remove this direction from the list of possible directions we can take from this node
72  current_node._PossibleDirections.RemoveAt(random_dir_pos);
73 
74  //Whats the position after we take a step in this direction
75  var next_node_pos = current_node._Pos + random_dir;
76 
77  //Have we visited this position before?
78  if (!this.HasVisitedNode(next_node_pos, visited_nodes)) {
79  //Walk to this node
80  current_node = new WalkNode(next_node_pos,
81  current_node,
82  new List<Vector3>(this._all_possible_directions));
83 
84  visited_nodes.Add(next_node_pos);
85 
86  steps_so_far += 1;
87  }
88  }
89 
90  //Generate the final path
91  var random_walk_positions = new List<Vector3>();
92 
93  while (current_node._PreviousNode != null) {
94  random_walk_positions.Add(current_node._Pos);
95 
96  current_node = current_node._PreviousNode;
97  }
98 
99  random_walk_positions.Add(current_node._Pos);
100 
101  //Reverse the list so it begins at the step we started from
102  random_walk_positions.Reverse();
103 
104  return random_walk_positions;
105  }
106 
107  //Checks if a position is in a list of positions
108  bool HasVisitedNode(Vector3 pos, List<Vector3> list_pos) {
109  var has_visited = false;
110 
111  foreach (var t in list_pos) {
112  var dist_sqr = Vector3.SqrMagnitude(pos - t);
113 
114  //Cant compare exactly because of floating point precisions
115  if (dist_sqr < 0.001f) {
116  has_visited = true;
117 
118  break;
119  }
120  }
121 
122  return has_visited;
123  }
124 
125  //Help class to keep track of the steps
126  class WalkNode {
127  //The position of this node in the world
128  public Vector3 _Pos;
129 
130  public WalkNode _PreviousNode;
131 
132  //Which steps can we take from this node?
133  public List<Vector3> _PossibleDirections;
134 
135  public WalkNode(Vector3 pos, WalkNode previous_node, List<Vector3> possible_directions) {
136  this._Pos = pos;
137 
138  this._PreviousNode = previous_node;
139 
140  this._PossibleDirections = possible_directions;
141  }
142  }
143  }
144 }
List< Vector3 > GenerateSelfAvoidingRandomWalk()
Definition: RandomWalk.cs:36