4

I'm developing a game similar to Pacman: consider this maze:

maze.

Each white square is a node from the maze where an object located at P, say X, is moving towards node A in the right-to-left direction. X cannot switch to its opposite direction unless it encounters a dead-end such as A. Thus the shortest path joining P and B goes through A because X cannot reverse its direction towards the rightmost-bottom node (call it C). A common A* algorithm would output:

to get to B from P first go rightward, then go upward;

which is wrong. So I thought: well, I can set the C's visited attribute to true before running A* and let the algorithm find the path. Obviously this method doesn't work for the linked maze, unless I allow it to rediscover some nodes (the question is: which nodes? How to discriminate from useless nodes?). The first thinking that crossed my mind was: use the previous method always keeping track of the last-visited cell; if the resulting path isn't empty, you are done. Otherwise, when you get to the last-visited dead-end, say Y, (this step is followed by the failing of A*) go to Y, then use standard A* to get to the goal (I'm assuming the maze is connected). My questions are: is this guaranteed to work always? Is there a more efficient algorithm, such as an A*-derived algorithm modified to this purpose? How would you tackle this problem? I would greatly appreciate an answer explaining both optimal and non-optimal search techniques (actually I don't need the shortest path, a slightly long path is good, but I'm curious if such an optimal algorithm running as efficiently as Dijkstra's algorithm exists; if it does, what is its running time compared to a non-optimal algorithm?)

EDIT For Valdo: I added 3 cells in order to generalize a bit: please tell me if I got the idea:

sketch.

Bentaye
  • 9,403
  • 5
  • 32
  • 45
Peanut
  • 175
  • 11

1 Answers1

2

Good question. I can suggest the following approach.

Use Dijkstra (or A*) algorithm on a directed graph. Each cell in your maze should be represented by multiple (up to 4) graph nodes, each node denoting the visited cell in a specific state.

That is, in your example you may be in the cell denoted by P in one of 2 states: while going left, and while going right. Each of them is represented by a separate graph node (though spatially it's the same cell). There's also no direct link between those 2 nodes, since you can't switch your direction in this specific cell.

According to your rules you may only switch direction when you encounter an obstacle, this is where you put links between the nodes denoting the same cell in different states.

You may also think of your graph as your maze copied into 4 layers, each layer representing the state of your pacman. In the layer that represents movement to the right you put only links to the right, also w.r.t. to the geometry of your maze. In the cells with obstacles where moving right is not possible you put links to the same cells at different layers.

Update:

Regarding the scenario that you described in your sketch. It's actually correct, you've got the idea right, but it looks complicated because you decided to put links between different cells AND states.

I suggest the following diagram: Maze diagram

The idea is to split your inter-cell AND inter-state links. There are now 2 kinds of edges: inter-cell, marked by blue, and inter-state, marked by red.

Blue edges always connect nodes of the same state (arrow direction) between adjacent cells, whereas red edges connect different states within the same cell.

According to your rules the state change is possible where the obstacle is encountered, hence every state node is the source of either blue edges if no obstacle, or red if it encounters an obstacle (i.e. can't emit a blue edge). Hence I also painted the state nodes in blue and red.

If according to your rules state transition happens instantly, without delay/penalty, then red edges have weight 0. Otherwise you may assign a non-zero weight for them, the weight ratio between red/blue edges should correspond to the time period ratio of turn/travel.

valdo
  • 12,632
  • 2
  • 37
  • 67
  • It's perfect! A bit expensive maybe: even though the construction is done during loading, n cells require at most 4n nodes, plus A* complexity is 4n in the worst case, leading to a 4 times slower search, which, I think, should be avoided in real-time games: actually I don't know if, given 1000 cells, the game is still responsive, do you? – Peanut Oct 12 '17 at 20:16
  • Speaking practically, 1000 cells doesn't sounds frightening. Even with standard Dijkstra, without messing with A*, sounds fine. Note that during the search you'll have a cloud of visited cells, and a layer of candidate cells surrounding the cloud. So that you'll have order of 4000^(1/2) nodes in the tree at most. So that the complexity is order of 4N * log[(4N)^(1/2)] = 2N * log(N) – valdo Oct 13 '17 at 18:11
  • P.S. On which device do you intend to run this? I'm running a similar algorithm with **very** much larger input on mid-range android tablet - and it's fine. – valdo Oct 13 '17 at 18:16
  • Well I'm running it on a last-gen computer so that'll be fine...can you explain a little bit more why the complexity is given by Nlog(N)? – Peanut Oct 13 '17 at 18:24
  • Tomorrow I will edit my question putting a sketch of your idea applied to the maze, so that you can tell me if I get it...now I'm a bit sleepy – Peanut Oct 13 '17 at 19:29
  • The complexity of Dijkstra algorithm on an abstract graph is given by E * log(N), whereas E is the total number of edges, and N is the total number of nodes. In our case E is of order of N, hence this gives us N * log(N) – valdo Oct 14 '17 at 18:00
  • please check the last link – Peanut Oct 15 '17 at 08:18
  • Thanks mate, unfortunately I don't have enough reputation to thumb up your answer which is perfect! I was wondering, since I can switch direction also in the cell with 4 neighbors where should I put the inter-cell links? Switching direction inside the same cell costs 0, so a link between those 4 states can even cause the algorithm to reverse direction which is not allowed. Any suggestions? (Sorry, I forgot to add this rule but I thought it quite obvious) – Peanut Oct 15 '17 at 15:58
  • Let me clarify my last comment: I can switch from dir1 to dir2 if and only if dir2 isn't the opposite of dir1 (i.e. left-right, up-down) or the cell in question has only 1 neighbor – Peanut Oct 15 '17 at 16:06
  • Well, inter-state links should be according to your rules, which you know best. You are free to define them in a way you like, there are no limitations. Also, zero weight is fine in Dijkstra algorithm, there's no problem with it. Edges are only required to have non-negative weight. – valdo Oct 15 '17 at 19:16
  • P.S. So, the rule should be IMHO: for every node you should put inter-state links to other states which are 90deg. of yours (i.e. not opposite), if they exist of course. In addition, in case of a dead-end, i.e. you have neither inter-cell nor inter-state, you are allowed to put link to an "opposite" state. – valdo Oct 15 '17 at 19:45
  • Umhh...consider the cell surrounded by 4 cells: since I can turn direction from left to up I put a link left-up, then since I can turn direction from up to right I add the link up-right...similarly I add the link right-down and down-left...it then follows that if I'm coming from the right heading to the left I CAN switch back to the opposite direction because there exist a inter-cell links path that costs 0...or am I getting something wrong? – Peanut Oct 16 '17 at 12:50
  • You're right, dude! And you know what this means? This means that you need **more** states, so that you know that if you already made a turn in the cell you can't do it any more. Or, alternatively, another definition of states. – valdo Oct 16 '17 at 17:15
  • P.S. every state can be split into 2: before you changed direction and after this. That is, your state describes not only where are you going, but also did you already change the direction in this cell. This is a straightforward solution. You can also think to redefine states/edges to achieve the same with fewer nodes. – valdo Oct 16 '17 at 18:21
  • Can you give me a hint? – Peanut Oct 18 '17 at 20:44