I am attempting to create a pathfinding algorithm for a game. Basically, after the player rolls a number, I need to determine all possible locations that the player can end up on a grid. The player cannot move directly backwards after a given step, and the player can only move one grid square per step.
The problem is, right now I am attempting to brute force the solution by recursively navigating along the graph and manually checking each valid move.
Pseudocode:
// Recursive function for navigating one step at a time.
function navigate($stamina, $coords, $coords_previous)
{
// If the movement stamina has not been spent.
if ($stamina != 0)
{
// Note: there may be less than four neighboring
// cells in a given location due to obstacles.
foreach ($neighboring_cells as $coords_neighboring)
{
// If the coordinates of the neighbor are not the same as the
// coordinates of the previous move (we can't move backwards)
if ($coords_neighboring != $coords_previous)
{
$stamina--;
// Recurse.
navigate($stamina, $coords_neighboring, $coords);
}
}
}
else
{
// No more stamina.
// Add $coords to our array of endpoints.
}
}
This works for small rolls (low $stamina values). However, as $stamina increases, this methodology starts to become super redundant. This is due to the fact that the player can move in circles over and over again, exponentially increasing the number of potential endpoints.
My question is, what can be done to decrease redundancy in the above function?
Define a state as a combination of a grid position and a facing (i.e., the direction the player moved in to get there). This is useful because we can define successors of a given state: in particular, those at adjacent grid positions (with appropriate facings) other than the one the player just came from.
Then compute the set of states reachable in n steps. For n=0, this is just the player's initial position (with a special "no facing" value if the first move can be in any direction). To compute it for n+1, generate all valid moves from each of the states in the previous set, discarding any duplicates. When you reach the set for $stamina steps, just discard the facings (and any duplicate positions).
In terms of graph algorithms
This is similar to a breadth-first search on a graph whose vertices are the states and whose edges connect a state to its successor states. However, here we don't disregard new (longer) paths to a state, since some positions might be reachable (in exactly $stamina steps!) only via looping back. One could also include the remaining stamina in the state (and define no edges away from a state with 0 moves left); then you would perform a normal graph search and collect all the leaves.
In either case these would probably be implicit graphs, but the algorithm is clearer implemented directly rather than in terms of a graph.
Related
Iam nooby in godot, I have to use A* to traslate the player to the goal position, but I do not know how to start, pls help!! basically I have just 2 tiles in the tilemap, 1 of them is allowed to pass over it, I have to extract I guess the allowed tile and calculate the distance between the position player with the position goal, getting the real distance and then check cell per cell which has the lowest cost, but I do not know how to do that :c
func get_player_init_pos():
var pos = map_to_world(Vector2(54,1))pos.y += half_cell_size.y
return pos
func is_tile_vacant(pos, direction):
var curr_tile = world_to_map(pos)
var next_tile = get_cellv(curr_tile + direction)
var next_tile_pos = Vector2()
if(next_tile == 0):
next_tile_pos = map_to_world(curr_tile + direction)
else:next_tile_pos = pos
return next_tile_pos
I have this, the first part of the code is to locate the player in the map and the second is for check the tile walls in the map
You could roll your own path finding algorithm. However, there is little point in doing so, since Godot has a AStar class you can use. However, you probably don't need to use that either, because Godot has a navigation system. And that is what I'm going to suggest you to use.
First of all, you can specify both navigation and collision polygons on your tiles. You need to have the navigation polygons. Go ahead and do them.
Second you want to have a Navigation2D in the scene tree and have your TileMap as a child.
And third, you can ask the Navigation2D for a path with get_simple_path, you pass the start and end positions as arguments and you get an array of points that make up the path.
Since you mention A*, I'll briefly explain using the AStar too anyway.
First, you need to add the cells with add_point. It requires ids. It is a good idea to be clever with the ids so you can compute the id for a given position. For example x * width + y if you know the size.
So you can iterate over the tiles in your TileMap and call add_point for each one (You don't need to add cell that are not passable).
Then you need to specify the connections with connect_points (it takes the ids of the points as parameters).
And finally you can call get_point_path passing the start and end ids. Again it gives you a array of points.
Given (N+1) points. All the N points lie on x- axis. Remaining one point (HEAD point) lies anywhere in the coordinate plane.
Given a START point on x- axis.
Find the shortest distance to cover all the points starting from START point.We can traverse a point multiple times.
Example N+1=4
points on x axis
(0,1),(0,2),(0,3)
HEAD Point
(1,1) //only head point can lie anywhere //Rest all on x axis
START Point
(0,1)
I am looking for a method as of how to approach this problem.
Whether we should visit HEAD point first or HEAD point in between.
I tried to find a way using Graph Theory to simplify this problem and reduce the paths that need to be considered. If there is an elegant way to represent this problem using graphs to identify a solution, I was not able to find it. This approach becomes very inefficient as the n increases - the time and memory is O(2^n).
Looking at this as a tree graph, the root node would be the START point, then each of its child nodes would be the points it is connected to.
Since the START point and the rest of the points aside from the HEAD all lay on the x-axis, all non-HEAD points only need to be connected to adjacent points on the x-axis. This is because the distance of the path between any two points is the sum of the distances between any adjacent points along the path between those two points (the subset of nodes representing points on the x-axis does not need to form a complete graph). This reduces the brute force approach some.
Here's a simple example:
The upper left shows the original problem: points on the x-axis along with the START and HEAD points.
In the upper right, this has been transformed into a graph with each node representing a point from the original problem. The edges represent the paths that can be taken between points. This assumes that the START point only represents the first point in the path. Unlike the other nodes, it is only included in the path once. If that is not the case and the path can return to the START point, this would approximately double the possible paths, but the same approach can be followed.
In the bottom left, the START point, a, is the root of a tree graph, and each node connected to the START point is a child node. This process is repeated for each child node until either:
A path that is obviously not optimal is identified, in which case that node can just be excluded from the graph. See the nodes in red boxes; going back and forth between the same nodes is unnecessary.
All points are included when traversing the tree from the root to that node, producing a potential solution.
Note that when creating the tree graph, each time a node is repeated, its "potential" child nodes are the same as the first time the node was included. By "potential", I mean cases above still need to be checked, because the result might include a nonsensical path, in which case that node would not be included. It is also possible a potential solution results from the path after its child nodes are included.
The last step is to add up the distances for each of the potential solutions to determine which path is shortest.
This requires a careful examination of the different cases.
Assume for now START (S) is on the far left, and HEAD (H) is somewhere in the middle the path maybe something like
H
/ \
S ---- * ----*----* * --- * ----*
Or it might be shorter to from H to and from the one of the other node
H
//
S ---- * --- * -- *----------*---*
If S is not at one end you might have something like
H
/ \
* ---- * ----*----* * --- * ----*
--------S
Or even going direct from S to H on the first step
H
/ |
* ---- * ----*----* |
S
A full analysis of cases would be quite extensive.
Actually solving the problem, might depend on the number of nodes you have. If the number is small < 10, then compete enumeration might be possible. Just work out every possible path, eliminate the ones which are illegal, and choose the smallest. The number of paths is I think in the order of n!, so its computable for small n.
For large n you can break the problem into small segments. I think its enough just to consider a small patch with nodes either side of H and a small patch with nodes either side of S.
This is not really a solution, but a possible way to think about tackling the problem.
(To be pedantic stackoverflow.com is not the right site for this question in the stack exchange network. Computational Science : algorithms might be a better place.
This is a fun problem. First, lets try to find a brute force solution, as Poosh did.
Observations about the Shortest Path
No repeated points
You are in an Euclidean geometry, thus the triangle inequality holds: For all points a,b,c, the distance d(a,b) + d(b,c) <= d(a,c). Thus, whenever you have an optimal path that contains a point that occurs more than once, you can remove one of them, which means it is not an optimal path, which leads to a contradiction and proves that your optimal path contains each point exactly once.
Permutations
Our problem is thus to find the permutation, lets call it M_i, of the numbers 1...n for points P1...Pn (where P0 is the fixed start point and Pn the head point, P1...Pn-1 are ordered by increasing x value) that minimizes the sum of |(P_M_i)-(P_M_(i-1))| for i from 1 to n, || being the vector length sqrt(v_x²+v_y²).
The number of permutations of a set of size n is n!. In this case we have n+1 points, so a brute force approach testing all permutations would have complexity (n+1)!, which is higher than even 2^n and definitely not practical, so we need further observations to improve this.
Next Steps
My next step would now be to see if there are any other sequences that can be proven to be not optimal, leading to a reduction in the number of candidates to be tested.
Paths of non-head points
Lets look at all paths (sequences of indices of points that don't contain a head point and that are parts of the optimal path. If we don't change the start and end point of a path, then any other transpositions have no effect on the outside environment and we can perform purely local optimizations. We can prove that those sequences must have monotonic (increasing or decreasing) x coordinate values and thus monotonic indices (as they are ordered by ascending x coordinate between indices 0 and n-1):
We are in a purely one dimensional subspace and the total distance of the path is thus equal to the sum of the absolute values of the differences in x coordinates between one such point and the next. It is clear that this sum is minimized by ordering by x coordinate in either ascending or descending order and thus ordering the indices in the same way. Note that this is true for maximal such paths as well as for all continuous "subpaths" of them.
Wrapping it up
The only choices we have left are:
where do we place the head node in the optimal path?
which way do we order the two paths to the left and right?
This means we have n values for the index of the head node (1...n, 0 is fixed as the start node) and 2x2 values for sort order. So we have 4n choices which we can all calculate and pick the shortest one. One of the sort orders probably determines the other but I leave that to you.
Anyways, the complexity of this algorithm is O(4n) = O(n). Because reading in the input of the problems is in O(n) and writing the output is as well, I believe that is an algorithm of optimal complexity. However, if we could reformulate the problem somewhat, so that we could read and write the input and output in some compressed form, as in only the parameters that we actually need to solve the problem, then it is possible that we could do better.
P.S.: I'm not a mathematician so I probably used wrong words for some concepts and missed the usual notation for the variables and functions. I would be glad for some expert to check this for any obvious errors.
I have a QGraphicsPathItem which is drawn from a list of cartesian x,y points.
What would be the best (performance wise) method of determining when the cursor is hovered over one of these points I presently iterate through the source list and compare each point with the cursor position.
Regards
Qt does not provide a built-in solution for what you want. You should reimplement QGraphicsScene::mouseMoveEvent and check in it which point (if any) is hovered (with a certain margin), i.e. determine which point is within a certain distance of the current mouse position (QGraphicsSceneMouseEvent::pos).
The most computation intensive task is determining the closest point. A naive approach is to iterate over all the points, but general optimised implementation exists:
QuadTree: 2D implementation
k-d tree: Multidimensional implementation
Nearest Neighbor Search: broad overview
Caching the last result and using the triangle inequality may be important to improve the performance of this method:
If currently the mouse hovers a point P, the next time you can just validate if it still hovers this point.
If currently no point is hovered and the nearest point from location P (the last mouse position for which you calculated the nearest point) is at a distance d, then you should not check if an hover occur if: norm(P - QGraphicsSceneMouseEvent::pos()) < d - hoverThreshold
I usually use the QGraphicScene's itemAt() method to check for graphic items under the cursor.
I am trying to create a physically plausible 2d physics engine. I have read many documents about detection of collisions, contact resolving, interpenetrations, projection, separating axis theorem (SAT) methods, etc.
Projection via SAT appears to be one physically plausible method for dealing with overlapping ("penetrating") objects. This works fine for objects with no rotation, but I can't figure out how to deal with rotations.
Imagine two polygons in rotation that will collide:
I need to understand how to project the point of contact and the time when this happens.
any help will be appreciated!
The problem is that you are assuming both bodies are moving at the same time, which will be a huge pain to calculate the exact collision point.
You can update the position of each body sequentially, and apply the collisions accordingly:
(I know the bodies are not rotated in this example, but I have no means right now to draw rotated forms, but the same idea applies, sorry)
First, the rectangle is moved, and checks for collision.
Then, the pentagon moves, and collides with the rectangle, updating its position.
And last, the triangle position is also checked for collition and updated.
About how to calculate the collision point, you can apply this:
Position calculateValidPosition(Position start, Position end)
Position middlePoint = (start + end) /2
if (middlePoint == start || middlePoint == end)
return start
if( isColliding(middlePont) )
return calculateValidPosition(start, middlePoint)
else
return calculate(middlePoint, end)
Note that
Position middlePoint = (start + end) /2
not only calculates the body's middle position, but also should calculate it's middle rotation:
If rotation is X at the begining of the movement, and Y at the end, the middle point rotatiln is just (X+Y)/2
Note this algorithm leaves a lot of room for optimization (like making it non-recursive)
This solution might seem not really accurate, but it will only work incorrectly when the speed of the bodies is way greater than the body's size, which will only happen if a really small body moves really fast. In the rest of scenarios the result is "good enough" for a game.
I'm making a program that selects an area within a canvas by clicking a sequence of points. The points clicked are linked by some lines this way: every new point is linked with the first and the last ones. I'm looking for an algorithm that computes the area of the resulting polygon.
Intersections are allowed, and here is the complexity, so the algorithm must manage this case by finding the polygon according to the ordered sequence of points clicked and calculating its area.
After many searches, the best I've found is this http://sigbjorn.vik.name/projects/Triangulation.pdf, but I would need something easier to implement in Processing.js.
First cut the line segments where they intersect. If the input set is small, you can simply check every pair. Otherwise use an R-Tree. Then compute a constrained (Delaunay) Triangulation. Then determine the inner triangles using rayshooting and sum up their areas.
hth