There is a square grid with obstacles. On that grid, there are two members of a class Person. They face a certain direction (up, right, left or down). Each person has a certain amount of energy. Making the persons turn or making them move consumes energy (turning consumes 1 energy unit, moving consumes 5 energy units).
My goal is to make them move as close as possible next to each other (expressed as the manhattan distance), consuming the least amount of energy possible. Keep in mind there are obstacles on the grid.
How would I do this?
I would use a breadth-first search and count a minimal energy value to reach each square. It would terminate when the players meet or there is no more energy left.
I'll make assumptions and remove them later.
Assuming the grid is smaller than 1000x1000 and that you can't run out of energy..:
Assuming they can't reach each other:
for Person1,Person2, find their respective sets of reachable points, R1,R2.
(use Breadth first search for example)
sort R1 and R2 by x value.
Now go through R1 and R2 to find the pair of points that are closest together.
hint: we sorted the two arrays so we know when points are close in terms of their x coordinate. We never have to go further apart on the x coordinate than the current found minimum.
Assuming they can reach each other: Use BFS from person1 until you find person2 and record the path
If the path found using BFS required no turns, then that is the solution,
Otherwise:
Create 4 copies of the grid (call them right-grid, left-grid, up-grid, down-grid).
the rule is, you can only be in the left grid if you are moving left, you can only be in the right grid if you are moving right, etc. To turn, you must move from one grid to the other (which uses energy).
Create this structure and then use BFS.
Example:
Now the left grid assumes you are moving left, so create a graph from the left grid where every point is connected to the point on its left with the amount of energy to move forwards.
The only other option when in the left-grid is the move to the up-grid or the down-grid (which uses 1 energy), so connect the corresponding gridpoints from up-grid and left-grid etc.
Now you have built your graph, simply use breadth first search again.
I suggest you use pythons NetworkX, it will only be about 20 lines of code.
Make sure you don't connect squares if there is an obstacle in the way.
good luck.
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.
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 working on a snake game (Nibbles in Linux) that is played on a 60*60 field, with four snakes competing for an apple which is randomly placed.
I've implemented the movement of my snake with the A* (A star) Algorithm.
My problem is this: When I'm not the nearest snake to the apple, I don't want to go to get the apple, because my chance to get it is lower than at least one snake, so I want to look for a place that I hope at the next place that an apple is generated , Then I'll be the nearest snake to that apple. I mean that I'm looking for a place which is nearest to the maximum number of potential locations.
Please suggest any good way or any algorithm that can help me to find this place.
Here is an image of the game. The red points are the snakes' heads.
I tested some ways and Finally I decided to use this way:
I think the best way is to make a 2D array with size:60*60 , then for each node(x) of the array, calculate how many nodes of the field-which are walkable!(not block), is this node(x) nearest to.
then the answer will be The maximum amount, then I set this node the goal.
but because I must find the next move in less than 0.1sec and to do this work, there is 4 loops of size:60, (60^4) and when I found it, A* algorithm will be run too , this work would never be done in less than 0.1 sec.
So , since the Snake can't move Diagonally and it goes just: up,down,right,left, I decided not to check all the nodes,Since in each cycle(0.1sec) , I can just move 1 unit, I decided to check just 4 nodes(up,down,left,right) and move to a node which It's amount is Max.
now it's working almost right. ;)
Since you have already implemented A*, after you generate your map, you could use A* to create a map of values for each cell based on the total cost from each cell to visit every other cell. If you generate this after you've placed your blocks, then your weighted map will account for their presence.
To generate this, off the top of my head, I would say you could start from each cell, and assign it one point for each cell it can visit in one turn. For example, a cell in the corner would get two points for the first move, because it can only access two other cells. It would get five points for the second turn, because it can access five cells in two moves. Repeat until you've visited all the other squares, and then you have the score for that square.
From that point, if an apple appears and your snake is not the closest to it, your snake could head for the highest weighted cell, which you've calculated beforehand.
Edit: Please see comments below for a more advantageous solution.
If you are nearest to apple you should walk to get it but if you are far apart from apple your best chance is walking in a middle of map, you should find strategy to how to occupy the middle of map.
You can divide your map to four zooms (clockwise), upper left, upper right, bottom right and bottom left (1,2,3,4). We check this between two snakes: If apple currently is in zoom 1 (assume center for average) and you are in center of map, your opponent can be in zooms 1,2,3,4 (again assume it's in the center of this zooms to take average in simpler way) if it's in zoom 1 it has better chance (1-0) if it's in zoom 2 or 4, your distance is sqrt(2)/2 and your opponent distance is 1, so you are nearest, and finally if your opponent is in zoom 3 your distance is sqrt(2)/2 and your opponent distance is sqrt(2), so in 3 cases with one oppnent you have better chance.
But because your shape has some blocks, you should calculate center position in other way, in fact, for each point in your grid calculate its distance to all other points. this will take 60^2 * 60^2 which can be done fast. and find cells with minimum total sums(you can select best 10 cells), this cells can be your centers, everytime you should move from one center to another (except when you are nearest to apple or your snake eats apple and wants comback to nearest centers) .
Nearest to the maximum number of locations is the center as others have stated. Nearer to the maximum number of locations than the other snakes is a much, different and harder questions. In that case, I would A* the head of each snake to see who has the most squares under control. That's the base score. Next, as I'm drawing a blank, I'd Monte Carlo a random set of points around the map and choose the point that gave the highest score as a destination. If you had the processing power, you could try every point on the grid and choose the best as K.G. suggested, but that could get pretty intense.
The true test is when you find your point, figure out how far in the future it takes you to get there, and running some AI for the other snakes to see if they will intercept you. You start getting into plys like chess. :)
I am now looking for an elegant algorithm to recursively find neighbors of neighbors with the geohashing algorithm (http://www.geohash.org).
Basically take a central geohash, and then get the first 'ring' of same-size hashes around it (8 elements), then, in the next step, get the next ring around the first etc. etc.
Have you heard of an elegant way to do so?
Brute force could be to take each neighbor and get their neighbors simply ignoring the massive overlap. Neighbors around one central geohash has been solved many times (here e.g. in Ruby: http://github.com/masuidrive/pr_geohash/blob/master/lib/pr_geohash.rb)
Edit for clarification:
Current solution, with passing in a center key and a direction, like this (with corresponding lookup-tables):
def adjacent(geohash, dir)
base, lastChr = geohash[0..-2], geohash[-1,1]
type = (geohash.length % 2)==1 ? :odd : :even
if BORDERS[dir][type].include?(lastChr)
base = adjacent(base, dir)
end
base + BASE32[NEIGHBORS[dir][type].index(lastChr),1]
end
(extract from Yuichiro MASUI's lib)
I say this approach will get ugly soon, because directions gets ugly once we are in ring two or three. The algorithm would ideally simply take two parameters, the center area and the distance from 0 being the center geohash only (["u0m"] and 1 being the first ring made of 8 geohashes of the same size around it (=> [["u0t", "u0w"], ["u0q", "u0n"], ["u0j", "u0h"], ["u0k", "u0s"]]). two being the second ring with 16 areas around the first ring etc.
Do you see any way to deduce the 'rings' from the bits in an elegant way?
That depends on what you mean by Neighbor. I'm assuming this is being used in the context of a proximity search. In that case I would think that your best bet would be to search from the outermost ring inward.
Assume you can find the outermost set (longest proximity) in the searchable Universe. Store that as the new Universe and then find the next inner set in that Universe. This search should subtract that inner set from the Universe. Store the old Universe (the outermost ring) and repeat this process until you hit the center. Each search after the first one will reduce your search area and give you a ring.
Start by constructing the sides immediately around the central geohash i.e. top, right, bottom and left, initially each of these will only comprise a single geohash and a corner. Then recursively iterate the sides using the adjacent function with direction as corresponds that side (i.e. expand left for the left side) whilst maintaining an appropriate result set and the sides for the next iteration. You also need to handle the diagonal/corner geohash for each side (e.g. left-top for left, top-right for top, if using a clockwise association). For an example of the procedure see this implementation I did in Lua or Javascript (but with additional functionality), which start with a call to Grid().
I'm programming a Risk like game in Codigniter and JQuery. I've come up with a way to create randomly generated maps by making a full layout of tiles then deleting random ones. However, this sometimes produces what I call islands.
In risk, you can only attack one space over. So if one player happens to have an island all to them self, they would never be able to loose.
I'm trying to find a way that I can check the map before the game begins to see if it has islands.
I have already come up with a function to find out how many adjacent spaces there are to each space, but am not sure how to implement it in order to find islands.
Each missing spot is also identified as "water."
I'm not allowed to use image tags:
http://imgur.com/xwWzC.gif
There's a standard name for this problem but off the top of my head the following might work:
Pick any tile at random
Color it
Color its neighbours
Color its neighbours' neighbours
Color its neighbours' neighbours' neighbours, etc.
When you're done (i.e. when all neighbours are colored), loop through the list of all tiles to see whether there are any still/left uncolored (if so, they're an island).
How do you do the random generation? Probably the best way is to solve it at this time. When you're generating the map, if you notice that you just created is impossible to get to, you can resolve it by adding the appropriate element.
Though we'll need to know how you do the generation.
Here's your basic depth-first traversal starting at a random tile, pseudo-coded in python-like language:
visited = set()
queue = Queue()
r = random tile
queue.add(r)
while not queue.empty():
current = queue.pop()
visited.add(current)
for neighbor in current.neighbors():
if neighbor not in visited:
queue.add(neighbor)
if visited == set(all tiles):
print "No islands"
else:
print "Island starting at ", r
This hopefully provides another solution. Instead of "island" I'm using the term "disconnected component" since it only matters whether all tiles are reachable from all others (if there are disconnected components then a player cannot win via conquest if his own territories are all in one component).
Iterate over all 'land' tiles (easy enough to do) and for each tile generate a node in a graph.
For each vertex, join it with an undirected edge to the vertices representing its neighbour tiles (maximum of 6).
Pick any vertex and run depth-first search (or bread-first) from it.
If the set of vertices found by the DFS is equal to the set of all vertices then there are no disconnected components, otherwise a disconnected component (island) exists.
This should (I think) run in time O(n) where n is the number of land tiles.
Run a blurring kernel over your data set.
treating the hex grid as an image ( it is , sort of)
value(x,y) = average of all tiles around this (x,y)
this will erode beaches slightly, and eliminate islands.
It is left as an exercise for the student to run an edge-detection kernel over the resulting dataset to populate the beach tiles.