1

I'm trying to make an algorithm of any sort that can find the solution with the lowest move count. I'm coding in GML using GMS2 and it's for a game that I'm making myself.

This is a picture of the most simple level

The reason I call it a complicated 2d puzzle game is because of how many types of blocks there are. The goal is to connect the two blocks and the player gets a trophy for solving it in a low move count, but I don't want to have to find the most efficient solutions by hand for every level, especially some of the super complicated levels.

This is an example of a level with all block types in it

The black boxes with an X on them are immovable and act as obstacles

The two blocks you're supposed to connect and the small blue blocks are simple movable blocks and can be moved in any of the four cardinal directions as long as the space is open

The long blue blocks act the same way but require an open space their same size to move into a spot

The red blocks act as a normal movable block, but cannot be placed next to each other. They can still be diagonal from each other though

And the green blocks can only be moved in the directions indicated on the block, meaning only left and right or only up and down

My first thought was to make a depth first search algorithm to just brute force all possible game states until it finds the quickest solution but I'm unsure of how to pull that off.

If anyone has any ideas for methods I could use or information that could help at all then I'm open to all feedback since I don't really know much about algorithms or machine learning at all, thanks in advance!

  • You may be interested in this, an overview of "sokoban" solvers. http://sokoban.dk/wp-content/uploads/2016/02/Timo-Virkkala-Solving-Sokoban-Masters-Thesis.pdf . Your game is presumably different from sokoban, but it appears to have much in common. The number of states in these sorts of games can quickly make it difficult to solve using naive searches. – Paul Hankin Oct 20 '22 at 09:55

1 Answers1

2

The standard approach is a breadth-first search. Looking at this hashmap and native queues I believe you can code it in GML, though that wouldn't be my first choice. (Python would be because you can have complex objects as dictionary keys. Dictionary being what Python calls a hashmap. Without that you'll need to serialize/deserialize objects to use them as keys. Serialize being a complicated word meaning, "write out a text representation". Ideally a compact text representation.)

The idea looks like this:

Create hashmap of position and last move
initialize it with start position and last move is none
put start position into a queue of positions to analyze
while stuff in queue and not yet solved:
    pop position from queue
    for each valid move from position:
        if resulting position is solved:
            it is solved and we have final position
        if resulting position is NOT in hashmap:
            add position + move to hashmap
            add position to queue
if no final position:
    there is no answer
else:
    path = []
    prev_move = hashmap of final position
    while prev_move is not none:
        add prev_move to start of path
        unto prev_move from final position to get new final position

And if it is solvable, then path will wind up being the shortest path from the starting position to any position where it is solved.

Note that the number of possible positions explodes, so you can only solve fairly small puzzles. With ideas like A* search you can make this slightly more efficient, but given how much backtracking tends to be involved, not much.

btilly
  • 43,296
  • 3
  • 59
  • 88
  • To put some numbers to the last claim, I've calculated a loose upper bound on OP's complex puzzle at 19,675,656,000 possible board states. I do not have a good lower bound. – Dillon Davis Oct 19 '22 at 21:47
  • You can probably do quite a lot with BFS and/or A* with a good heuristic. I think @Chris Currier should take a look at this blog of pretty much an identical task for inspiration: https://www.snellman.net/blog/archive/2018-07-23-optimizing-breadth-first-search/ – ldog Oct 20 '22 at 18:54
  • Thank you guys for the awesome replies and comments! I'm currently trying to make a hashmap system like the original reply said, and it's going well so far. I know A* is very useful for subjects like this, but I don't really know what it is or how it works, if someone could explain then I would be forever grateful. Thanks guys! – Chris Currier Oct 20 '22 at 23:34
  • I have another question about using BFS to find a solution. Almost all solutions require multiple blocks to be moved in a row, how would the algorithm move multiple blocks? All instances of BFS that I find online are only tracking one subject and how close it is to its goal, but to get a good solution I need to move multiple subjects. Any thoughts? – Chris Currier Oct 21 '22 at 12:37