From 73b078ec7a72f800a981c52491981e282f39cfbd Mon Sep 17 00:00:00 2001 From: BOTLester <58360400+BOTLester@users.noreply.github.com> Date: Mon, 4 May 2020 01:50:43 +0200 Subject: [PATCH] A* implemented and working, Task2 Ready --- Game1/Sources/Crops/Crops.cs | 8 +- Game1/Sources/Pathing/A-Star/Astar.cs | 46 ++++------- .../Pathing/A-Star/PathSaver/MinHeap.cs | 2 - .../Sources/Pathing/A-Star/PathSaver/Path.cs | 76 ------------------- route-planning.md | 28 +++++++ 5 files changed, 48 insertions(+), 112 deletions(-) create mode 100644 route-planning.md diff --git a/Game1/Sources/Crops/Crops.cs b/Game1/Sources/Crops/Crops.cs index 64cc648..a9bb2f7 100644 --- a/Game1/Sources/Crops/Crops.cs +++ b/Game1/Sources/Crops/Crops.cs @@ -31,15 +31,15 @@ class Crops public int getCostOnMovement() { - if (Status == 1) + if (Status == 1) //grass { return 1; } - else if (Status == 2) + else if (Status == 2) //dirt { - return 5; + return 8; } - else if (Status == 3) + else if (Status == 3) //crops { return 15; } diff --git a/Game1/Sources/Pathing/A-Star/Astar.cs b/Game1/Sources/Pathing/A-Star/Astar.cs index 808129f..9ab7ae1 100644 --- a/Game1/Sources/Pathing/A-Star/Astar.cs +++ b/Game1/Sources/Pathing/A-Star/Astar.cs @@ -31,6 +31,7 @@ class Astar return allPaths.Peek(); } + // Get all adjacent nodes private List GetAdjacentNodes(Vector2 currentPos) { var adjacentNodes = new List() @@ -53,7 +54,7 @@ class Astar adjacentNodes.Remove(adjacentNodes[i]); } } - + // return if not an obstacle return adjacentNodes.Where( item => crops[(int)item.getCords().X, (int)item.getCords().Y].Status != 0).ToList(); } @@ -63,18 +64,19 @@ class Astar { return (int)(Math.Abs(endNote.X - currentNode.X) + Math.Abs(endNote.Y - currentNode.Y)); } - + // Rotation Cost public int CalculateRotationCost(int currDir, int newDir) { if (currDir == newDir) return 0; else if (Math.Abs(currDir - newDir) == 1 || Math.Abs(currDir - newDir) == 3) - return 3; - else if (Math.Abs(currDir - newDir) == 0 || Math.Abs(currDir - newDir) == 2) //its for turning back, so it never should happen anyway, remove this check then? + return 2; + else if (Math.Abs(currDir - newDir) == 0 || Math.Abs(currDir - newDir) == 2) return 9; return 0; } + // Convert rotation used by sprite, to get direction of first node in next path public int ConvertRotation() { int rotation = 0; @@ -89,50 +91,37 @@ class Astar return rotation; } + // Main function of A* algorithm public Path FindPath() { + int g = 0; + int direction = ConvertRotation(); Path path = new Path(); - //PriorityQueue openList = new PriorityQueue(); MinHeap openList = new MinHeap(); - //PriorityQueue closedList = new PriorityQueue(); MinHeap closedList = new MinHeap(); Nodes target = new Nodes(targetPos); - int direction = ConvertRotation(); Nodes startPos = new Nodes(tractorPos, direction); Nodes current = null; - int g = 0; - //int direction = SmartTractor.update - //openList.Enqueue(startPos); openList.Insert(startPos); - //while (openList.Count > 0) while (openList.GetSize() > 0) { current = openList.getMin(); - //current = openList.Peek(); - //g = current.getG(); closedList.Insert(current); - //closedList.Enqueue(current); openList.removeMin(); - //openList.Dequeue(); direction = current.getDirection(); if (current.getCords() == target.getCords()) break; - - //if (closedList.Exists(target.getCords())) - // break; - var adjacentNodes = GetAdjacentNodes(current.getCords()); - //g++; foreach (var adjacentNode in adjacentNodes) { - if (closedList.Exists(adjacentNode.getCords())) + if (closedList.Exists(adjacentNode.getCords())) // check if adjacent node is on closed list, if it is, skip it continue; - g = current.getG() + crops[(int)adjacentNode.getCords().X, (int)adjacentNode.getCords().Y].getCostOnMovement() + CalculateRotationCost(direction, adjacentNode.getDirection()); - if (!(openList.Exists(adjacentNode.getCords()))) + g = current.getG() + crops[(int)adjacentNode.getCords().X, (int)adjacentNode.getCords().Y].getCostOnMovement() + CalculateRotationCost(direction, adjacentNode.getDirection()); // calculate g - cost from start point + if (!(openList.Exists(adjacentNode.getCords()))) // if adjacent node is not on open list, add it { adjacentNode.setG(g); @@ -140,11 +129,10 @@ class Astar adjacentNode.calculateF(); adjacentNode.setParent(current); openList.Insert(adjacentNode); - //openList.Enqueue(adjacentNode); } else { - if (g + adjacentNode.getH() < adjacentNode.getF()) + if (g + adjacentNode.getH() < adjacentNode.getF()) // check if adjacent node is a better path than the current one { adjacentNode.setG(g); adjacentNode.calculateF(); @@ -153,20 +141,18 @@ class Astar } } - - //openList.BuildMinHeap(openList.GetList()); } - + + // backtrack to create path while (current != null) { path.AddNode(current); current = current.getParent(); } path = path.FlipArray(); + openList.deleteHeap(); closedList.deleteHeap(); - //openList.Clear(); - //closedList.Clear(); return path; } diff --git a/Game1/Sources/Pathing/A-Star/PathSaver/MinHeap.cs b/Game1/Sources/Pathing/A-Star/PathSaver/MinHeap.cs index 7f7b2a5..9e20957 100644 --- a/Game1/Sources/Pathing/A-Star/PathSaver/MinHeap.cs +++ b/Game1/Sources/Pathing/A-Star/PathSaver/MinHeap.cs @@ -121,8 +121,6 @@ class MinHeap if (arr.Count > 0) { //clear the current heap - //Array.Resize(ref arr, input.Length); - //heapSize = 0; for (int i = 0; i < arr.Count; i++) { arr[i] = input[i]; diff --git a/Game1/Sources/Pathing/A-Star/PathSaver/Path.cs b/Game1/Sources/Pathing/A-Star/PathSaver/Path.cs index db5c550..8b00c78 100644 --- a/Game1/Sources/Pathing/A-Star/PathSaver/Path.cs +++ b/Game1/Sources/Pathing/A-Star/PathSaver/Path.cs @@ -61,80 +61,4 @@ class Path return nodes[i]; } - - /* - private int Count = 0; - private int Cost = 0; - private int Efficency; - - - public Nodes getNode(int i) - { - - return nodes[i]; - } - - public void setNode(Vector2 newNode) - { - nodes[Count] = new Nodes(10, newNode); - Count++; - } - - public Nodes Reduce() - { - Count--; - Nodes temp = nodes[0]; - - for (int i = 0; i < Count; i++) - { - nodes[i] = nodes[i + 1]; - } - - return temp; - } - - public Nodes getFinalDest() - { - return nodes[Count]; - } - - public int getCount() - { - return Count; - } - - public Nodes getFirst() - { - return nodes[0]; - } - - public Nodes getByIndex(int i) - { - return nodes[i]; - } - - public int getEfficency() - { - return Efficency; - } - - private void calculateEfficency() - { - for (int i = 0; i < Count; i++) - { - Efficency = Efficency + nodes[i].getCost(); - } - } - - public int getCost() - { - return Cost; - } - - public void setCost(Crops Crop) - { - - } - - */ } \ No newline at end of file diff --git a/route-planning.md b/route-planning.md new file mode 100644 index 0000000..123e382 --- /dev/null +++ b/route-planning.md @@ -0,0 +1,28 @@ +# intelligent tractor environment implementation report + +The environment is a resizable two dimensional grid that has sprites for a farmhouse, crops and empty fields + +House: + +![](https://lh4.googleusercontent.com/tEGhmLT2PAgvXG313YaVewDrUhMYgvY1PPmPpISbcW2BRz4UPfDph3-86YDHjHl4YdyCYAx4qhzB2fTlmA2Gh5nyg6oLM92Nwg-UtV3tKw3nLBe3RZvr47efqYMElmaQASTr-xMt) + +The tractor (in white) and crop (in red) on the field: + +![](https://lh4.googleusercontent.com/vd2n3rGPXDMLaaGBGBtjxVRftNryut-NYPstA4_CJwtRDrIVKVoAt-YrSZhcTysnk4cPXNEtssbVx02O9-DHUlV_JkY7nudSqanG7vCnMVMXQHSDnVjhDG8q98OelzNfxNXsMrbH) + +The simulation can increase in speed or even be halted with the arrow keys, the current speed is displayed at the bottom left of the window The current environment spawns crops in randomly generated locations and the tractor tracks the location of crops and it will haul the target back to the house as well as fertilize newly planted crops. + +As a task is complete on a tile its stage level will increase by one all the way up to 4 depending when it is fully grown and can be harvested, + +1. The soil will not support crops. + +2. Soil is ready for crops to be planted. + +3. Crops are planted and need fertilization. + +4. Crops are ready for harvest. + + +After the crops have been harvested they will return to stage 2. + +A short video of how the project works:[video](https://uam-my.sharepoint.com/:v:/g/personal/domhof1_st_amu_edu_pl/Ec1ThqI2DSZNob2-6IrfPvYBe9_G2xfK8Ffn04dSklsWIQ?e=OrTqmy)