What's a decent level-generation algorithm for a game similar to Unblock Me?
My first attempt was to start with a solved level and work backwards. I started with the red horizontal rectangle next to the exit on the right side of the board. Initially the board has zero other pieces. So I tried to add pieces pseudo-randomly up to the desired piece count (say seven). Levels limited to only horizontal or only vertical pieces are not very interesting so I alternated between horizontal and vertical pieces while adding. Finally I tried to scramble the pieces by moving them randomly. After working through a few examples it became obvious that this method often generates uninteresting levels. Also the minimum move count is unknown.
The next attempt approaches the problem in a different way. Levels are generated randomly. Then a search algorithm finds the minimum number of moves to solve the puzzle (if it's possible). While I haven't implemented this yet I think it will create some interesting levels. Since the board is relatively small (10x10 upper bound) I think the run time will be acceptable for generating levels that are bundled with the app. Also the minimum move count is known which is important for scoring.
I doubt the first approach works as is. However a variation that I haven't considered could work. My only reservation with the second approach is the potential code complexity. I think it will be a BFS with a memo table and a BoardState object. I'd like to hear some alternatives before diving into the second approach.
I would do like this:
Generate a random state of the game where the red rectangle is next to the exit
Calculate the full state space for the board starting from that state
Choose one of the states in the state space that is furthest away from a solved state as the actual problem. I would use as distance measure the number of moves of distinct pieces, i.e. count multiple moves of the same piece in a row as 1
If the generated state space is too small, remove pieces and redo
If the generated state space is large but distance from any state to solution is small, add pieces and redo
Related
I've tried searching for a while, but haven't come across a solution, so figured I would ask my own.
Consider an MxM 2D grid of holes, and a set of N balls which are randomly placed in the grid. You are given some final configuration of the N balls in the grid, and your goal is to move the balls in the grid to achieve this final configuration in the shortest time possible.
The only move you are allowed to make is to move any contiguous subsection of the grid (on either a row or column) by one space. That sounds a bit confusing; basically you can select any set of points in a straight line in the grid, and shift all the balls in that subsection by one spot to the left or right if it is a row, or one spot up or down if it is a hole. If that is confusing, it's fine to consider the alternate problem where the only move you can make is to move a single ball to any adjacent spot. The caveat is that two balls can never overlap.
Ultimately this problem basically boils down to a version of the classic sliding tile puzzle, with two key differences: 1) there can be an arbitrary number of holes, and 2) we don't a priori know the numbering of the tiles - we don't care which balls end up in the final holes, we just want to final holes to be filled after it is all said and done.
I'm looking for suggestions about how to go about adapting classic sliding puzzle solutions to these two constraints. The arbitrary number of holes is likely pretty easy to implement efficiently, but the fact that we don't know which balls are destined to go in which holes at the start is throwing me for a loop. Any advice (or implementations of similar problems) would be greatly appreciated.
If I understood well:
all the balls are equal and cannot be distinguished - they can occupy any position on the grid, the starting state is a random configuration of balls and holes on the grid.
there are nxn = balls + holes = number of cells in the grid
your target is to reach a given configuration.
It seems a rather trivial problem, so maybe I missed some constraints. If this is indeed the problem, solving it can be approached like this:
Consider that you move the holes, not the balls.
conduct a search between each hole and each hole position in the target configuration.
Minimize the number of steps to walk the holes to their closest target. (maybe with a BFS if it is needed) - That is to say that you can use this measure as a heuristic to order the moves in a flavor of A* maybe. I think for a 50x50 grid, the search will be very fast, because your heuristic is extremely precise and nearly costless to calculate.
Solving the problem where you can move a hole along multiple positions on a line, or a file is not much more complicated; you can solve it by adding to the possible moves/next steps in your queue.
If you're not familiar with it, the game consists of a collection of cars of varying sizes, set either horizontally or vertically, on a NxM grid that has a single exit.
Each car can move forward/backward in the directions it's set in, as long as another car is not blocking it. You can never change the direction of a car.
There is one special car, usually it's the red one. It's set in the same row that the exit is in, and the objective of the game is to find a series of moves (a move - moving a car N steps back or forward) that will allow the red car to drive out of the maze.
I've been trying to think how to generate instances for this problem, generating levels of difficulty based on the minimum number to solve the board.
Any idea of an algorithm or a strategy to do that?
Thanks in advance!
The board given in the question has at most 4*4*4*5*5*3*5 = 24.000 possible configurations, given the placement of cars.
A graph with 24.000 nodes is not very large for todays computers. So a possible approach would be to
construct the graph of all positions (nodes are positions, edges are moves),
find the number of winning moves for all nodes (e.g. using Dijkstra) and
select a node with a large distance from the goal.
One possible approach would be creating it in reverse.
Generate a random board, that has the red car in the winning position.
Build the graph of all reachable positions.
Select a position that has the largest distance from every winning position.
The number of reachable positions is not that big (probably always below 100k), so (2) and (3) are feasible.
How to create harder instances through local search
It's possible that above approach will not yield hard instances, as most random instances don't give rise to a complex interlocking behavior of the cars.
You can do some local search, which requires
a way to generate other boards from an existing one
an evaluation/fitness function
(2) is simple, maybe use the length of the longest solution, see above. Though this is quite costly.
(1) requires some thought. Possible modifications are:
add a car somewhere
remove a car (I assume this will always make the board easier)
Those two are enough to reach all possible boards. But one might to add other ways, because of removing makes the board easier. Here are some ideas:
move a car perpendicularly to its driving direction
swap cars within the same lane (aaa..bb.) -> (bb..aaa.)
Hillclimbing/steepest ascend is probably bad because of the large branching factor. One can try to subsample the set of possible neighbouring boards, i.e., don't look at all but only at a few random ones.
I know this is ancient but I recently had to deal with a similar problem so maybe this could help.
Constructing instances by applying random operators from a terminal state (i.e., reverse) will not work well. This is due to the symmetry in the state space. On average you end up in a state that is too close to the terminal state.
Instead, what worked better was to generate initial states (by placing random cars on the grid) and then to try to solve it with some bounded heuristic search algorithm such as IDA* or branch and bound. If an instance cannot be solved under the bound, discard it.
Try to avoid A*. If you have your definition of what you mean is a "hard" instance (I find 16 moves to be pretty difficult) you can use A* with a pruning rule that prevents expansion of nodes x with g(x)+h(x)>T (T being your threshold (e.g., 16)).
Heuristics function - Since you don't have to be optimal when solving it, you can use any simple inadmissible heuristic such as number of obstacle squares to the goal. Alternatively, if you need a stronger heuristic function, you can implement a manhattan distance function by generating the entire set of winning states for the generated puzzle and then using the minimal distance from a current state to any of the terminal state.
I'm trying to implement a polyline simplification algorithm. The original article can be found here: http://archive.is/Tzq2. It seems straightforward in concept but I don't understand the sample algorithm (I think it's poorly worded) pseudocode supplied and was hoping someone could provide some insight. From the article, I gathered that the basic idea is to
Calculate the effective area (formed by the triangle between three consecutive points on a line) for each point and delete those with 0 area
Starting with the smallest area, compare the point's area with a threshold, and if the area is below that threshold, delete it from the polyline.
Move to the two adjacent points and recalculate their areas as they've changed
Go back to 2 until all point areas under the threshold have been removed
The algorithm is as follows (copied verbatim from the article):
Compute the effective area of each point
Delete all points with zero area and store them in a separate list with this area
REPEAT
Find the point with the least effective area and call it the current point. If its calculated area is less than that of the last point to be eliminated, use the latter's area instead. (This ensures that the current point cannot be eliminated without eliminating previously eliminated points.)
Delete the current point from the original list and add this to the new list together with its associated area so that the line may be filtered at run time.
Recompute the effective area of the two adjoining points (see Figure 1b).
UNTIL
The original line consists of only 2 points, namely the start and end points.
I'm confused with the 'if' clause in the first step under 'REPEAT'... could anyone clarify?
FWIW Mike Bostock, the creator of d3.js, wrote a tight javascript implementation of this algorithm (Visvalingam's Algorithm).
Source code
Demo
Discussion on Hacker News
The essence of the algorithm is ranking of points by their significance. Significance of the point is approximated by its effective area.
Suppose you have eliminated Point A and then recalculated the effective area of Point B. The new area can be larger or smaller than the old one. It can be smaller than the effective area of A. However, the algorithm still views B as more significant than A.
The purpose of the if clause is to ensure that Point B is more significant than A in the final list, that's all.
I was confused by this too, went back and read the article again, and afaict it's not needed if you're removing points as you go - aka if you're doing a one-off simplification with a fixed area threshold. afaict the javascript implementation works this way, so it actually doesn't need the 'if' statement (but it has it anyway, oh well).
The 'if' statement is needed if you're keeping all the points around. In that case, you're storing the 'effective area' with each point so that later you can filter them, perhaps using an interactive slider that controls the # of output points. By storing that larger effective area, you preserve the proper ordering.
I am trying to fit more than one line to a list of points in 2D. My points are quite low in number (16 or 32).
These points are coming from a simulated environment of a robot with laser range finders attached to its side. If the points lie on a line it means that they detected a wall, if not, it means they detected an obstacle. I am trying to detect the walls and calculate their intersection, and for this I thought the best idea is to fit lines on the dataset.
Fitting one line to a set of points is not a problem, if we know all those points line on or around a line.
My problem is that I don't know how can I detect which sets of points should be classified for fitting on the same line and which should not be, for each line. Also, I don't even now the number of points on a line, while naturally it would be the best to detect the longest possible line segment.
How would you solve this problem? If I look at all the possibilities for example for groups of 5 points for all the 32 points then it gives 32 choose 5 = 201376 possibilities. I think it takes way too much time to try all the possibilities and try to fit a line to all 5-tuples.
So what would be a better algorithm what would run much faster? I could connect points within limit and create polylines. But even connecting the points is a hard task, as the edge distances change even within a single line.
Do you think it is possible to do some kind of Hough transform on a discrete dataset with such a low number of entries?
Note: if this problem is too hard to solve, I was thinking about using the order of the sensors and use it for filtering. This way the algorithm could be easier but if there is a small obstacle in front of a wall, it would distract the continuity of the line and thus break the wall into two halves.
A good way to find lines in noisy point data like this is to use RANSAC. Standard RANSAC usage is to pick the best hypothesis (=line in this case) but you can just as easy pick the best 2 or 4 lines given your data. Have a look at the example here:
http://www.janeriksolem.net/2009/06/ransac-using-python.html
Python code is available here
http://www.scipy.org/Cookbook/RANSAC
The first thing I would point out is that you seem to be ignoring a vital aspect of the data, which is you know which sensors (or readings) are adjacent to each other. If you have N laser sensors you know where they are bolted to the robot and if you are rotating a sensor you know the order (and position) in which the measurements are taken. So, connecting points together to form a piecewise linear fit (polylines) should be trivial. Once you had these correspondances you could take each set of four points and determine if they can be modeled effectively by only 2 lines, or something.
Secondly, it's well known that finding a globally optimal fit for even two lines to an arbitrary set of points is NP-Hard as it can be reduced to k-means clustering, so I would not expect to find an efficient algorithm for this. When I used the Hough transform it was for finding corners based on pixel intensities, in theory it is probably applicable to this sort of problem but it is just an approximation and it is probably going to take a fair bit of work to figure out and implement.
I hate to suggest it but it seems like you might benefit by looking at the problem in a slightly different way. When I was working in autonomous navigation with a laser range finder we solved this problem by discretizing the space into an occupancy grid, which is the default approach. Of course, this just assumes the walls are just another object, which is not a particularly outrageous idea IMO. Beyond that, can you assume you have a map of the walls and you are just trying to find the obstacles and localize (find the pose of) the robot? If so, there are a large number of papers and tech reports on this problem.
A part of the solution could be (it's where I would start) to investigate the robot. Questions such as:
How fast is the robot turning/moving?
At what interval is the robot shooting the laser?
Where was the robot and what was its orientation when a point was found?
The answers to these questions might help you better than trying to find some algorithm that relies on the points only. Especially when there are so very few.
The answers to these questions give you more information/points. E.g., if you know the robot was at a specific position when it detected a point, there are no points in between the position of the robot and the detected point. that is very valuable.
For all the triads, fit a line through them and compute how much the line is deviating or not from the points.
Then use only the good (little-deviating) triads and merge them if they have two points at common, and the grow the sets by appending all triads that have (at least) two points in the set.
As the last step you can ditch the triads that haven't been merged with any other but have some common element with result set of at least 4 elements (to get away with crossing lines) but keep those triads that did not merge with anyone but does not have any element in common with sets (this would yield three points on the right side of your example as one of the lines).
I presume this would find the left line and bottom line in the second step, and the right line the third.
This evening I tried to solve a wood puzzle so I wondered which is the best way to find a solution to this kind of problem programmaticaly.
The aim is to combine a set of solids (like tetris pieces in three dimensions) together to form a shape in a feasable way that takes into account the fact that pieces can be attached or slided into the structure only if they fit the kind of movement (ignore rotations, only 90° turns).
Check this picture out to understand what I mean.
In my latest CS class we made a generic puzzle solver that worked by having states represented as objects in C++. Each object had a method to compare the state it represented to another state. This was used for memoization, to determine if states had already been seen. Each state also had a method to generate states directly reachable from that state (i.e. rotating a block, placing a block, shifting a block). The solver worked by maintaining a queue of states, popping a state off the front of the queue, checking to see if it was the desired state (i.e. puzzle solved). If not, the memoization (we used a hashed set) was checked to see if the state had already been seen. If not, the states reachable from the current state were generated and appended to the rear of the queue. An empty queue signaled an unsolvable puzzle.
Conceptualizing something like that for 3D would be hard, but that is the basic approach to computerized puzzle solving.
Seems like an easier subset of a three-dimensional polyomino packing problem. There are various scholarly papers on that subject.
As it is a more or less small problem because for a computer there is a small number of combinations possible I would try a simple search algorithm.
I mean an algorithm that checks every possible configuration and goes on from the result of this configuration until it ends up in a end configuration, in your case the cube.
The problem seams to be writing a program that is able to do all the state checks and transformations from one state to another. Because you have to see if the configuration is physically possible.
If the puzzle you want to handle is that one in the photo you have linked, then it's probably feasible to just search through a tree of possible solutions until you find your way to the bottom.
If each puzzle piece is a number of cubes attached at their faces, and I am to solve the puzzle by fitting each piece into a larger cube, 4 times on each edge as the composing cubes, then I'd proceed as follows.
Declare an arbitrary cube of each piece as its origin. Observe that there are 24 possible rotations for each puzzle piece, one orientation for each possible face of the origin cube facing upwards, times 4 possible rotations about the vertical axis in that position.
Attempt to cull the search space by looking for possible orientations that produce the same final piece, if a given rotation, followed by a translation of the origin cube to any of the other cubes of the piece results in exactly the same occupied volume as a previously considered rotation, cull that rotation from future consideration.
Pull a piece out of the bag. If there are no pieces in the bag, then this is a solution. Loop through each cell of the solution volume, and each rotation of the pulled piece for each cell. If the piece is completely inside the search volume, and does not overlap with any other piece, recurse into this paragraph. Otherwise, proceed to the next rotation, or if there are no more rotations, proceed to the next cell, or if there are no more cells, return without a solution.
If the last paragraph returns without a solution, then the puzzle was unsolvable.