I have a 2D int array which I processed and got from an image. Each index can be thought as weight of that pixel. I want to find a path between 2 indexes (I'll give these indexes as input) that has the least cost. It would be great if the direction of movements can be modified (like only down&left, up&left. or all. etc. otherwise it may be down, left and right)
How can i do that in C#?
Regardless of language, I would calculate the cost for a direct path first. This will became the first base line. Then I would recursively search for a shorter path. You can make a few boundary checks to reduce the recursion.
Any path that is >= the base line (or current best) is terminated
Any path that would hit an index twice is terminated
Any successful path sets the new base line (or best)
The A* algorithm (as was already tagged :)) is a good choice for this.
See, for example, How to implement an A* algorithm?
Related
In one of my university courses (in Data-structures and Algorithmics), we are given a bonus assignment based on the game Sokoban:
With one Major exception: We only have one crate to push to our goal.
Example input
8 8
MMMMMMMM
M.....?M
M....TTM
M....TTM
M..!...M
M....+.M
M......M
MMMMMMMM
Here the first line gives the dimensions (b x h) of the board (8 by 8 in this case). This is followed up by h lines oh b characters. The meaning of these characters is as follows: . A walkable space, ? the goal (red point in the gif), ! the crate, and + is our position.
We are asked to output the shortest solution to the puzzle. (Note that a puzzle might be unsolveable.) We output this in 2 lines, the first tells us how many moves, and the second tells us the correct path. For the example, this would be:
Example Output
10
WWNNNWNEEE
Now, finding an algorithm that works isn't really an issue. Seeing as we're looking for the shortest path, and the nodes on this specific graph are in essence unweighted, I've implemented a breadth first search. In broad strokes, my current implementation looks like this:
0. Since the maze doesn't change, describe each state as a whole number based on the coordinates
of the crate and the player. - This defines a state uniquely and reduces memory costs.
1. Create a dictionary of visited states.
2. Get the input positions of the goal, crate and player.
3. Set up a Queue of move sequences.
4. Pop a move sequence from the Queue.
5. If this move sequence wins the game, go to step 8.
6. Make new move sequences which are copies of the original, each with a different legal move appended.
7. Append these new move sequences to the Queue.
8. Go to step 4
9. Print the output.
This is, of course a relatively simple algorithm. The problem is that it isn't fast enough. In one of the final test cases, we're thrown a 196 x 22 maze like "level" which has a solution that takes 2300 steps. We're asked to solve this level within 10 seconds, but it takes my algorithm more than 10 minutes.
Because of that, I'm kinda at a loss. I've already managed to increase the algorithm's speed 10 fold, and I still have 2 orders of magnitude to go...
Hence why I'm asking here: What makes this algorithm so slow, and how can I speed it up?
Yes, your comprehensive BFS search will be slow. You spend a large amount of your tree search in moves that are utterly wasted, your player thrashing around the maze area to no avail.
Change the focus of your goal: first, solve the maze for the crate rather than sending the player every which way. Include a heuristic for moving the crate closer to the goal spot. Make sure that the crate moves are possible: that there is a "push from " spot available for each move.
One initial heuristic is to make a maze fill by raw distance to the goal start at either the goal (what I've done here) and increment the steps through the maze, or start at the box and increment from there.
MMMMMMMM
M54321?M
M6543TTM
M7654TTM
M876567M <== crate is on the farther 6
M987678M <== player is on the nearer 7
Ma98789M
MMMMMMMM
Here, you would first try to find legal pushes to move the box along the path 654321?. You can also update this by making a penalty (moving the player without pushing) for any direction change.
These heuristics will give you a very good upper bound for a solution; you can then retrace decision points to try other paths, always keeping your "shortest solution" for any position.
Also keep track of where you've been, so that you don't waste time in position loops: never repeat a move (position and direction).
Does that help you get going?
Instead of using a pure dfs search of the player's movements, consider only the crate moves available to you at the time. For instance, in the very first frame of your gif, at the beginning of the simulation, the only crate move possible is the top one to the right one square.
An analogy would be for a game of chess on the first move, you would not consider any queen or bishop moves since they are all blocked by pawns.
After you've successfully found the sequence of crate moves leading to the solution, come back and trace the player moves necessary to construct the sequence of crate moves.
This improves time complexity because the time complexity will be based on the number of crates present in the map instead of total squares.
I am trying to implement a pathfinding algorithm, but I think I'm running into terminology issues, in that I'm not quite sure how to explain what I need the algorithm to do.
I have a regular grid of nodes, and I am trying to find all nodes within a certain "Manhattan Distance".
Finding the nodes within, say, 5, is simple enough.
But I am interested in a "Weighted Manhattan Distance", where certain squares "cost" twice as much (or more) to enter. For instance, if orange squares cost 2 to enter, and purple squares cost 10, the graph I'm interested in looks like this:
Firstly, is there a term for this? It's hard to look up info on things when you're not entirely sure what they're called in the first place.
Secondly, how can I calculate which nodes fall within my parameters? I'm not looking for a full solution, necessarily, just some hints to get started; when I realized my implementation would require three Dictionarys, I began to think there might be an easier way of handling things.
For terminology, you're basically asking for all points within a certain distance on an arbitrary (positive) weighted graph. The use of differing weights means it no longer corresponds to a specific metric such as Manhattan distance.
As for algorithms, Dijkstra's algorithm is probably what you want. The basic idea is to maintain the minimum cost to each square that you've found so far, and a priority queue of the best squares to explore next.
Unlike traditional Dijkstra's where you keep going until you find the minimal path to every square, you'll want to stop adding nodes to the queue if the distance to them is too long. Once you're done, you'll have a list of all squares whose shortest path from the starting square is at most x, which sounds like what you want.
Eric Lippert provides an excellent blog-series on writing an A-* path finding algorithm in C# here:
Part 1:http://blogs.msdn.com/b/ericlippert/archive/2007/10/02/path-finding-using-a-in-c-3-0.aspx
Part 2: http://blogs.msdn.com/b/ericlippert/archive/2007/10/04/path-finding-using-a-in-c-3-0-part-two.aspx
Part 3: http://blogs.msdn.com/b/ericlippert/archive/2007/10/08/path-finding-using-a-in-c-3-0-part-three.aspx
Part 4: http://blogs.msdn.com/b/ericlippert/archive/2007/10/10/path-finding-using-a-in-c-3-0-part-four.aspx
You are probably best to go with Dijkstra's algorithm with weighted graph, like described here:
http://www.csl.mtu.edu/cs2321/www/newLectures/29_Weighted_Graphs_and_Dijkstra's_Algorithm.html
(There is algorithm description near the middle of the page.)
Manhattan distance in your case probably just means you don't want the diagonal paths in the graph.
I started work on a dungeon crawler in C# and I've already coded the level generation.
However, I've run into a problem. My level map is stored in a 32x32 multidimensional array, and each tile is stored as a string. All the tiles except for the following (all of these names are the variable names that represent that tile) (mongroveplant, tree, hjalaplant, vnosplant, barraplant, weedplant, naroplant, deathweedplant, venustrap, strangulator, statue, emptiness and stonewall) cannot be walked over.
These tiles (which can be walked over), which constitute a much longer list, are found here: Walkable Tiles. In each entry in the 32x32 multidimensional array, every entry is a string.
How do I create a pathfinding algorithm that avoids all the tiles listed above, but can go through all the tiles listed in the link? I am trying to go from the "start" tile to the "exitlevel" tile.
The first thing I would remove is the notion of string. Parsing string isn't quick in term of a video game. What you want, is to have flags for each tiles (bitfields). In the end, you will love flags because you can combine them!
[Flags]
public enum TileDescription
{
Walkable,
Trap,
Altar,
Door
}
They can also be stored at a int, which take far less space. Speed and space, two amazing notions.
As for the path-finding algo, there's plenty of them out-there. But basically, you have a start point, a end point, and you must find the quickest way between both. The idea is to check the nearest "nodes" and see if you get closer or not of your goal. Each time, you repeat the check with the new node. If you get trapped, you rewind to the nodes that still had available paths.
You have some nice basic algo :
http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
http://en.wikipedia.org/wiki/A*_search_algorithm
However, long range pathfinding is ALWAYS extremely costly. You will have to limit the pathfinding to a specific range around the origin. Parsing a whole 32x32 maze could take a lot of time to find the quickest route. In most case, when you are beyond a specific range, you move your NPC up to the closest point, then repeat the pathfinding when it reaches it, or while reaching it. The trick to pathfinding is to do it over many frames and never to try to process it all at once.
Was wondering if anyone has knowledge on implementing pathfinding, but using scent. The stronger the scent in the nodes surrounding, is the way the 'enemy' moves towards.
Thanks
Yes, I did my university final project on the subject.
One of the applications of this idea is for finding the shortest path.
The idea is that the 'scent', as you put it, will decay over time. But the shortest path between two points will have the strongest scent.
Have a look at this paper.
What did you want to know exactly??
Not quite clear what the question is in particular - but this just seems like another way of describing the Ant colony optimization problem:
In computer science and operations
research, the ant colony optimization
algorithm (ACO) is a probabilistic
technique for solving computational
problems which can be reduced to
finding good paths through graphs.
Well, think about it for a minute.
My idea would to divide the game field into sections of 32x32 (or whatever size your character is). Then run some checks every x seconds (so if they stay still the tiles around them will have more 'scent') to figure out how strong a scent is on any given tile. Some examples might be: 1) If you cross over the tile, add 3; 2) if you crossed over an adjacent tile, add 1.
Then add things like degradation over time, reduce every tile by 1 every x seconds until it hits zero.
The last thing you will need to worry about is using AI to track this path. I would recommend just putting the AI somewhere, and telling it to find a node with a scent, then goto an adjacent node with a higher/equal value scent. Also worry about crossing off paths taken. If the player goes up a path, then back down it another direction, make sure the AI does always just take the looped back path.
The last thing to look at with the AI would be to add a bit of error. Make the AI take the wrong path every once in a while. Or lose the trail a little more easily.
Those are the key points, I'm sure you can come up with some more, with some more brainstorming.
Every game update (or some other, less frequent time frame), increase the scent value of nodes near to where the target objects (red blobs) are.
Decrease all node scent values by some fall-off amount to zero.
In the yellow blob's think/move function get available nodes to move to. Move towards the node with the highest scent value.
Depending on the number of nodes the 'decrease all node scent values' could do with optomisation, e.g. maybe maintaining a a list of non-zero nodes to be decreased.
I see a big contradiction between scent model and pathfinding. For a hunter in the nature finding the path by scent means finding exactly the path used by the followed subject. And in games pathfinding means finding the fastest path between two points. It is not the same.
1. While modelling the scent you will count the scent concentration in the point as the SUM of the surrounding concentrations multiplied by different factors. And searching for the fastest path from the point means taking the MINIMUM of the times counted for surrounding points, multiplied by the different parametres.
2. Counting the scent you should use recursive model - scent goes in all directions, including backward. In the case of the pathfinding, if you have found the shortest paths for points surrounding the target, they won't change.
3 Level of scent can rise and fall. In pathfinding, while searching for minimum, the result can never rise.
So, the scent model is really much more complicated than your target. Of course, what I have said, is true only for the standard situation and you can have something very special...
I'm working on a project where I need to perform pathfinding to find the route which costs the least. I don't really care if it's the shortest route possible. So far it seems A* is out of the question and I honestly do not understand Prim's algorithm.
Let me explain the kind of maps that I need to find routes on. This is an example map:
+------|-*----
+------|----|-
+--|--------|-
+#-|----------
The "*" is the start location, the "#" is the destination. The "+" signs in a line indicate a direct route which a) costs the same as a single step, and b) halves the cost of the entire route.
This means there are 10 "steps" from the start position to the destination via the "+" route, which ends up with a cost of 5. There are 15 steps to use the left-most "|" route ("|" is a lower cost than "-", but worse than "+"), which ends up with a cost of 15. Obviously, the route with a cost of 5 is the route to use.
Now I'm having trouble implementing this in C#. I currently have a "step" function which moves and returns if the way was blocked or the cost of the step, and the new position. This works well, but at the moment it is extremely naive in that it'll go down a "|" if it finds one before a "+" (which means the entire trip costs significantly more, as it hasn't found the faster route).
I was thinking of marking each location as "visited", but it's completely plausible that the lowest-cost route will loop back on itself. There are also many different paths, each of which is unique, and each of which may use different path segments (that may have already been visited by a previous run). Obviously each path needs to be traversed in order to find the cheapest path, but I can't figure out how to do that without ending up searching the same routes over and over again.
If it makes it simpler, I can limit any movement to only move towards the destination (ie, can't go back up again after going down).
If anyone could provide some insight, that'd be great!
From what I understand, the '-' fields in your map are graph nodes. Each '-' node has at most 8 edges to neighboring '-' fields. 8 if you allow diagonal movement, otherwise only 4 neighboring '-' nodes are valid. There is no edge between a '-' node and a '|' node.
This is enough to implement a simple depth-first search / breadth-first-search in which you keep a queue of unvisted nodes (LIFO for depth-first, FIFO for breadth-first) and a list of visited nodes (to avoid cycling). Both algorithms will be relatively inefficient, but can be easily improved upon.
I'm not sure what the meaning of your '+' nodes is. Is moving from one '+' to the next '+' mode a free move? If so, you can model this using edge costs. A move from or to a '-' node has cost 1, a move from '+' to '+' node has cost 0.
The breadth-first-search algorithm can be extended to Dijkstra's algorithm that calculates the shortest path between your source and destination as long as all graph edges are non-negative:
http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
The Dijkstra algorithm can be further improved with the addition of a simple heuristic, making it the A* algorithm. If you have the coordinates of your goal in 2D coordinates, you could use the euclidian distance between a node and the goal as a rough estimate of which node is best to follow. If the '+' fields are something of a tunnel through your map with zero cost to move, the A* algorithm may not help that much because heuristically moving towards your destination will often be wrong if you should have moved towards the tunnel. If there are multiple tunnels or tunnels not leading to your destination, there may not be an heuristic better than the naive Dijkstra algorithm.
Please note that it is impossible for the lowest-cost route to contain a loop: If the lowest-cost route contained a loop, stripping the loop would still yield a valid route to the goal with lower cost contradicting the assumption that we started from a route with lowest-cost.
Have a look at Cormen's Introduction to Algorithms, or the relevant Wikipedia pages:
http://en.wikipedia.org/wiki/Shortest_path
http://en.wikipedia.org/wiki/Breadth-first_search
http://en.wikipedia.org/wiki/Depth-first_search
http://en.wikipedia.org/wiki/A*_search_algorithm