I have an idea of creating yet another maze game. However, there is a key difference: maze changes on-the-fly during the game. When I think of the problem the following restrictions come into my mind:
there is main route in the maze which never changes
the main route is the only route which leads to the finish
maze mutation should not block paths back to the main route
It also would be nice to control (affect game difficulty):
how much of the maze gets changed during a single mutation
optionally disable restriction #3 (i.e. player can get blocked in the maze for a while)
EDIT:
The question is: can you suggest an algorithm (or give your ideas) for described maze generation/mutation, which will not violate given restrictions?
You could:
Block a path at random (or using some sneaky criteria).
Scan the maze to see if it has been partitioned into 2 regions that are no longer connected.
If disconnected, you can knock down a wall at random so long as it neighbors both regions.
If your maze has only one path between any two points, step 2 will always split the maze and so #3 will always be needed.
Make a graph connecting all the cells of the maze and the walkable connections between them. To modify the maze, first pick a random wall to knock down, which generates a new edge in the graph. Then find a cycle in the graph that contains that edge, and delete a random, non-main-path edge in that cycle, which will erect an edge somewhere else.
This algorithm ensures that if all cells were reachable at the start, they will remain so. You probably want that feature so you can't ever get trapped.
This is probably quite straightforward. Generate the maze using the standard depth-first-search algorithm. Store the list of cells that form the (only) path from start to exit in a list. When you decide you want to mutate the maze, do the following:
Reset the entire maze to the default state (all walls in place), with the exception of any cell along the critical path, and optionally, a few cells within line-of-sight of the player's current location.
Re-execute the breadth-first search algorithm from the start, with one modification: when choosing which unvisited neighbour to explore, prefer edges that already have the wall removed.
The modification in the second step will ensure that the algorithm first explores the existing paths, then adds on side-passages and so forth from there. It's not even strictly necessary to preserve the critical path if you don't want to - you can regenerate the entire maze except where the user's standing, and it'll remain valid.
I think this ought to always produce a valid tree in the same way the original algorithm would, but I'm not 100% sure about the implications of preserving the cells around the user, which may not be on the critical path. I'm positive the reconfigured maze will always be solvable from where the user is standing, though.
This is a pretty neat idea, too. I love the idea of the maze rearranging itself substantially wherever the user isn't looking. If you're doing this in first-person, you could even use the camera view to change the walls behind the user when they're not looking!
Related
I'm making a game engine for a board game called Blockade and right now I'm trying to generate all legal moves in a position. The rules aren't exactly the same as the actual game and they don't really matter. The gist is: the board is a matrix and you move a pawn and place a wall every move.
In short, I have to find whether or not a valid path exists from every pawn to every goal after every potential legal move (imagine a pawn doesn't move and a wall is just placed), to rule out illegal moves. Or rather, if I simplify it to a subproblem, whether or not the removal of a few edges (placing a wall) removes all paths to a node.
Brute-forcing it would take O(k*n*m), where n and m are the board dimensions and k is the number of potential legal moves. Searching for a path (worst case; traversing most of the board) is very expensive, but I'm thinking with dynamic programming or some other idea/algorithm it can be done faster since the position is the same the wall placement just changes, or rather, in graph terms, the graph is the same which edges are removed is just changed. Any sort of optimization is welcome.
Edit:
To elaborate on the wall (blockade). A wall is two squares wide/tall (depending on whether it's horizontal or vertical) therefore it will usually remove at least four edges, eg:
p | r
q | t
In this 2x2 matrix, placing a wall in the middle (as shown) will remove jumping from and to:
p and t, q and r, p and r, and q and t
I apologize ahead of time if I don't fully understand your question as it is asked; there seems to be some tacit contextual knowledge you are hinting at in your question with respect to knowledge about how the blockade game works (which I am completely unfamiliar with.)
However, based on a quick scan on wikipedia about the rules of the game, and from what I gather from your question, my understanding is that you are effectively asking how to ensure that a move is legal. Based on what I understand, an illegal move is a wall/blockade placement that would make it impossible for any pawn to reach its goal state.
In this case, I believe a workable solution that would be fairly efficient would be as follows.
Define a path tree of a pawn to be a (possibly but not necessarily shortest) path tree from the pawn to each reachable position. The idea is, you want to maintain a path tree for every pawn so that it can be updated efficiently with every blockade placement. What is described in the previous sentence can be accomplished by observing and implementing the following:
when a blockade is placed it removes 2 edges from the graph, which can sever up to (at most) two edges in all your existing path trees
each pawn's path tree can be efficiently recomputed after edges are severed using the "adoption" algorithm of the Boykov-Komolgrov maxflow algorithm.
once every pawns path tree is recomputed efficiently, simply check that each pawn can still access its goal state, if not mark the move as illegal
repeat for each possible move (reseting graphs as needed during the search)
Here are resources on the adoption algorithm that is critical to doing what is described efficiently:
open-source implementation as part of the BK-maxflow: https://www.boost.org/doc/libs/1_66_0/libs/graph/doc/boykov_kolmogorov_max_flow.html
implementation by authors as part of BK-maxflow: https://pub.ist.ac.at/~vnk/software.html
detailed description of adoption (stage) algorithm of BK maxflow algorithm: section 3.2.3 of https://www.csd.uwo.ca/~yboykov/Papers/pami04.pdf
Note reading the description of the adopton algorithm included in the last
bullet point above would be most critical to understanding how to adopt
orphaned portions of your path-tree efficiently.
In terms of efficiency of this approach, I believe on average you should expect on average O(1) operations for each adopted edge, meaning this approach should take about O(k) time to compute where k is the number of board states which you wish to compute for.
Note, the pawn path tree should actually be a reverse directed tree rooted at the goal nodes, which will allow the computation to be done for all legal pawn placements given a blockade configuration.
A few suggestions:
To check if there's a path from A to B after ever
Every move removes a node from the graph/grid. So what we want to know is if there are critical nodes on the path from A to B (single points that could be blocked to break the path. This is a classic flow problem. For this application you want to set the vertex capacity to 1 and push 2 units of flow (basically just to verify that there are at least 2 paths). If there are 2 paths, no one block can disconnect you from the destination. You can optimize it a bit by using an implicit graph, but if you're new to this maybe create the graph to visualize it better. This should be O(N*M), the size of your grid.
Optimizations
Since this is a game, you know that the setup doesn't change dramatically from one step to another. So, you can keep track of the two paths. If the blocade is not placed on any of the paths, you can ignore it. You already have 2 paths to destination.
If the block does land on one of the paths, cancel only that path and then look for another (reusing the one you already have).
You can also speed up the pawn movement. This can be a bit trick, but what you want is to move the source. I'm assuming the pawn moves only a few cells at a time, maybe instead of finding completely new paths, you can simply adjust them to connect to the new position, speeding up the update.
I am new to game programming I currently am using unity's 2D power to remake an 2D game for sake of practice. So I am just little confuse about one thing, so far every enemy in my game was dumb(they move on predefined paths) but this enemy, alien-copter, flies and follow the player wherever the player goes. My question is should I implement any pathfinding algorithm? I had studied A* but I trying to figure out if A* is gonna be helpful in my envoirnment because player will be moving and the enemy have to keep on looking for shortest path. I tried to write code for this AI my code was working perfect when there were no obstacles but my game has obstacles so I want something efficient so what do you people think should I implement A* or any other algorithm or not?
As regards AI, if you have obstacles in your game, you will need to implement pathfinding of some sort. Note, that just taking the shortest block (node) is not an option because such algorithm is not complete, i.e. the path may not be found even if there is one. Imagine a going after b:
(wall)(wall)(wall)
(free)(free)a (wall) b
(wall)(wall)(wall)
The shortest (best) path is to the left since up, down and right are blocked. On the next move however, the best move is to go right because it's closer. That's how a will get trapped in a loop. So yes you are right, you do need to get the path from a to b. It will typically be in the form of a list of nodes. Then you just select head (aka element at index 0) of the list.
A* is the perfect option in your case. It is complete, efficient and it will even give you the shortest path. Path recomputation shouldn't be an issue for a small game. Furthermore, if obstacles in your game grid are static for the duration of the game you can precompute paths and cache them. For instance, path from (x,y) to (x1,y1) is [(a,b), (c,d) ...]. So you can store it in some sort of map data structure where key is the two points - start, target and value - the path. This will of course depend on whether you want to classify an enemy as an obstacle for other enemies and other gameplay factors
I'm trying to find a solution for pathfinding in a trains game where there are different kinds of bifurcations. I want the train to go from one rail to another, everything is implemented except the pathfinding.
I need to get a list of rails so the train can follow. Now, the problem is how do I get the list.
I've tried A*, didn't work because it stops searching if the node (rail) is already visited. This is a problem, because maybe the way to reach a point is by travelling through the longest route.
Tried flood fill, this time made it not stop searching if already visited, the problem is how do I reconstruct the path and how does it choose that it can't go backwards again.
The thing is that there are cases in which the train must go through a rail multiple times to reach its destination.
Any ideas?
Starting point is A, end B. As you see the green path is the way it should travel. The balck circle are the rails which the train will step more than once, in this case 2 times.
And obviously, you need to come from 2 black to get to 3 red. You can't just go 1black->2red->1red->3red.
Looking at this picture
It appears your problem would be represented well by a directed graph. Give each stop and each junction two nodes in the graph, one for each direction of the train. Dijkstra's algorithm works perfectly on directed graphs, so once you have the problem in that form, the rest is easy.
So for example, in the picture above, starting from A, we move to junction 1. From there, there's only one place to move to, junction 2, so there'd be an arrow from A --> junction 1 and an arrow from junction 1 --> junction 2. Regardless of which choice you make, you end up at junction 1, but moving in the other direction, so we create a separate node from there. From there, you have the option of going to A or B.
Notice that I removed one of the J1's, since it is superfluous (there's only one place to go).
If the train can stop and turn around at stops like A, we can connect those two nodes by edges in both directions, or just combine them into one node.
You can give the edges weights to specify distances.
Flood fill should really do the thing (I used it in a similar case) - but you only need to work with switches and segments carefully.
Algorithms should be allowed to pass the same segment in different direction, but not in the same. I.e. each segment really should be regarded as two separate.
to reconstruct the path you should assign numbers to segments while flooding them, so that each reached from N-1 is marked with N - then while move backward, tracking segments should be done so that numbers steadily decrease by one.
It is really kind of BFS.
I have a grid with a start, finish, and some walls. Units take the shortest path (moving only up/down/left/right) from the start to the finish, without passing through walls.
The user is allowed to add as many extra walls as they want to change the path.
However, notice that no matter how many walls are added or where they're added, there are some squares that can never be part of the shortest path!
These squares can never be part of the shortest path!
I'm looking for a way to detect which squares can never be part of the shortest path.
The above cases are easy enough to find; but there are more complex cases. Consider:
In the above image, none of the squares with red dots can ever be part of the best path, because there's only one entrance to that area, and it's only two spaces wide. If it were three spaces wide, or if any one of the walls were removed, most of those squares could potentially be part of the best path.
I've been trying to figure out a way to detect cases like the above (mostly using min-cuts and flood-fills), but without success. Does anyone know of a way to solve this problem?
Consider any path from S to F. That path could be a shortest path (if you delete every other square) unless you can take "shortcuts" using only those tiles. This only happens when you have two adjacent squares that aren't adjacent in the path. So you need to consider all pairs of adjacent squares; anything they disconnect from S or F (without disconnecting S from F) can't be part of a shortest path. Also, tiles that can be disconnected by a single square can't be part of any path (that doesn't repeat vertices) from S to F, so they need to go too.
Let N be the number of squares in the grid. For any particular pair of squares (there are O(N) of them), what gets disconnected can be computed in O(N) time with a floodfill, so this is O(N^2). Which is cheaper than min-cut, which you mentioned trying, so I assume its cheap enough for you.
first we see that, the areas can be blocked by one or two adjacent grids will never be in any shortest path.
see the case in your example, it's those two yellow grids who make the dots blocked.
blocked by one grid is easy to understand. When blocked by two:
if not adjacent, we may add extra walls to make it the only path, go
in through one and go out from the other one, so we may need the
inside ones.
if adjacent, we can always go from one directly to the other, so we
still don't need the grids inside that area.
So here's comes the algorithm:
enumerate each empty grid
put a wall on it and use flood-fill to find the blocked areas, they
are of no use.
try put a wall on one of it's four adjacent grid(if empty), use
flood-fill to find the blocked areas, they are of no use.
I'm working on a simple multiplayer game in which 2-4 players are placed at separate entrypoints in a maze and need to reach a goal point. Generating a maze in general is very easy, but in this case the goal of the game is to reach the goal before everyone else and I don't want the generation algorithm to drastically favor one player over others.
So I'm looking for a maze generation algorithm where the optimal path for each player from the startpoint to the goal is no more than 10% more steps than the average path. This way the players are on more or less an equal playing field. Can anyone think up such an algorithm?
(I've got one idea as it stands, but it's not well thought out and seems far less than optimal -- I'll post it as an answer.)
An alternative to freespace's answer would be to generate a random maze, then assign each cell a value representing the number of moves to reach the end of the maze (you can do both at once if you decide that you're starting at the 'end'). Then pick a distance (perhaps the highest one with n points at that distance?) and place the players at squares with that value.
What about first selecting the position of the players and goal and an equal length path and afterwards build a maze respecting the defined paths? If the paths do not intersect this should easily work, I presume
I would approach this by setting the goal and each player's entry point, then generating paths of similar length for each of them to the goal. Then I would start adding false branches along these paths, being careful to avoid linking to other player's paths, or having a branch connect back to the path. So essentially every branch is a dead end.
This way, you guarantee the paths are similar in length. However it won't allow players to interact with each other. You can however put this in, by creating links between branches such that branch entry points on either path are at a similar distance away from the goal. And on this branch you can branch off more dead ends for fun and profit :-)
The easiest solution I can come up with is to randomly generate an entire maze like normal, then randomly pick the goal point and player startpoints. Once this is done, calculate the shortest path from each startpoint to the goal. Find the average and start 'smoothing' (remove/move barriers -- don't know how this will work) the paths that are significantly above it, until all of the paths are within the proper margin. In addition, it could be possible to take the ones that are significantly below the average and insert additional barriers.
Pick your exit point somewhere in the middle
Start your N paths from there, adding 1 to each path per loop,
until they are as long as you want them to be.
There are your N start points, and they are all the same length.
Add additional branches off of the lines, until the maze is full.