I'm currently working on implementing the AI for a tile-based video game. There are multiple enemies, which can each move a single tile per turn. These enemies can also throw balls to each other any distance within a straight line, but the throwing only works when there is an enemy ready to catch the object. Given these conditions, how can we find the shortest sequence of coordinated moves for one enemy A to throw a ball to another enemy B?
Essentially, we want to move enemy A and enemy B so that they end up within a straight line of each other.
My first and very rough idea is to use a basic BFS and spread outwards from enemy A, one tile at a time. At each step of the BFS, we then note down all the tiles which can be thrown to from the current point P (basically just fanning outwards from point P in straight lines. I could also first calculate these and save them in a table called Throwable for memoization). We record the distance from enemy B to those throwable tiles. At the end of the BFS, we then take the point such that (distance from enemy A to point P) + (distance from enemy B to Throwable[P]) is minimized.
However, this seems like a very inefficient and brute-force approach. Is there some more efficient algorithm for this?
Related
I have a general graph/path-finding question that I had for an interview.
Suppose you are trying to get to a specific node on a 2D graph, and there are enemy units that are transversing the graph's nodes, searching for you: what is the best way to maximize the chances of you reaching the goal without encountering an enemy unit?
I am very curious of the best algorithm or general approach to handle this.
P.S: You know where the enemy units are located
Assuming that you want to do what a human in a dangerous maze would do: Just go ahead and run away whenever you see an enemy, here is a simple idea:
Run breadth first search once starting from the goal over the whole graph to store the distance to the goal in every node. In this step, ignore the enemies. Of course this is assuming that you have some distance measure in your graph. Otherwise just counting up the number of nodes during the bfs will do for some applications. Also keep the distance of the last node to the goal, let us call this quantity maxdist.
Run a "small" breadth first search from every enemy towards all directions. Small, because you stop this after a distance of k, where k is the number of graph nodes you want to keep away from enemies or some other suitable metric (this represents the "seeing"). Do a similar thing in this bfs: store the distance towards this enemy where the enemy sits in, denote it as d_i for an arbitrary node i. In this bfs you overwrite the distance to the goal in node i by maxdist + k - d_i. Notice that this quantity is always at least as high as maxdist. In this step you need to be careful on how to update this node i when another enemy has written into it (keep the larger value).
Now, in every timestep you pick as the next node the one node in your neighborhood that has closest distance to the goal. Since nodes that are "close" to an enemy are always at least as expensive as maxdist, you are automatically avoiding enemies. And if you get cornered by enemies from two sides, you will automatically stay in the middle between the two, hoping for as long as possible that one of them turns around.
This might not necessarily maximize your chances, especially not if you can do predictions about the enemy movement. Furthermore this behaves "stupid" as it would run towards an enemy even if you can't pass it until it "sees" it, from where it would turn around.
But it is a general approach, that might even be the best one can do, especially if you cannot see enemies from too far away and if you have no information about their movement, but you have a map to see where you are and where the goal is.
In the two-ball game, n > 4 kickers are positioned on the playing field and do not move (i.e.\ change their locations) during the game. Four of the players are distinguished: two of them, denoted as s1 and s2, are called starting players, and two others, denoted as t1 and t2, are called terminal players. At the beginning, player s1 has got a white ball and s2 possesses a black ball. Then each starting player can kick the ball directly to the corresponding terminal player but he can also kick the ball to any other player on the field and this player can pass the ball to the next one, and so on. The aim is that at the end the white ball is in possession of t1 and the black ball in possession of t2. So, it seems the game is quite simple. However, to avoid ball collisions, the constraint of the game is that no ball trajectories cross each other and that no player (including starting and terminal ones) has more than one ball contact. For simplicity, we assume the trajectory of a ball moving from one player to the next one is a line segment.
Note:This is problem on spoj and I need just suggestions which algorithm are required to solve this efficiently and why they are required.Link for problem is SPOJ TBGAME Question
I am trying to create an algorithm for 'fleeing' and would like to first find points which are 'safe'. That is to say, points where they are relatively distant from other points.
This is 2D (not that it matters much) and occurs within a fixed sized circle.
I'm guessing the sum of the squared distances would produce a good starting equation, whereby the highest score is the furthest away.
As for picking the points, I do not think it would be possible to solve for X,Y but approximation is sufficient.
I did some reading and determined that in order to cover the area of a circle, you would need 7 half-sized circles (with centers forming a hex, and a seventh at the center)
I could iterate through these, all of which are within the circle to begin with. As I choose the best scoring sphere, I could continue to divide them into 7 spheres. Of course, excluding any points which fall outside the original circle.
I could then iterate to a desired precision or a desired level.
To expand on the approach, the assumption is that it takes time to arrive at a location and while the location may be safe, the trip in between may not. How should I incorporate the distance in the equation so that I arrive at a good solution.
I suppose I could square the distance to the new point and multiply it by the score, and iterate from there. It would strongly favor a local spot, but I imagine that is a good behavior. It would try to resolve a safe spot close by and then upon re-calculating it could find 'outs' and continue to sneak to safety.
Any thoughts on this, or has this problem been done before? I wasn't able to find this problem specifically when I looked.
EDIT:
I've brought in the C# implementation of Fortune's Algorithm, and also added a few points around my points to create a pseudo circular constraint, as I don't understand the algorithm well enough to adjust it manually.
I realize now that the blue lines create a path between nodes. I can use the length of these and the distance between the surrounding points to compute a path (time to traverse and danger) and weigh that against the safety (the empty circle it is trying to get to) to determine what is the best course of action. By playing with how these interact, I can eliminate most of the work I would have had to do, simply by using the voronoi. Also my spawning algorithm will use this now, to determine the LEC and spawn at that spot.
You can take the convex hull of your set of locations - the vertices of the convex hull will give you the set of "most distant" points. Next, take the centroid of the points you're fleeing from, then determine which vertex of the convex hull is the most distant from the centroid. You may be able to speed this up by, for example, dividing the playing field into quadrants - you only need to test the vertices that are in the furthermost quadrant (e.g., if the centroid is in the positive-x positive-y quadrant, then you only need to check the vertices in the negative-x negative-y quadrant); if the playing field is an irregular shape then this may not be an option.
As an alternative to fleeing to the most distant point, if you have a starting point that you're fleeing from (e.g. the points you're fleeing from are enemies, and the player character is currently at point X which denotes its starting point), then rather than have the player flee to the most distant point you can instead have the player follow the trajectory that most quickly takes them from the centroid of the enemies - draw a ray from the enemies' centroid through the player's location, and that ray gives you the direction that the player should flee.
If the player character is surrounded then both of these algorithms will give nonsense results, but in that case the player character doesn't really have any viable options anyway.
I would like to make a shape recognition program that would trace a mouse and record it's location at each 1/2 second. How could I use these points to find a rough polygon? In other words, if you just draw a shape resembling a triangle or square, it will more likely be a be a 50-100-gon, how can I simplify it to get the shape I were trying to draw? I know that you could do a genetic algorithm, but do not know exactly how that would work, and I would like to know any alternatives.
edit: convex hulls will not work, concavity is needed to be preserved.
i'll give this a shot.
lets call the position when the mouse click down event happens point START
every interval take another position called CURR
the lets call the previous CURR, PREV
calculate the slope (delta y/delta x) between CURR and PREV,
calculate the slope of the line between CURR and START
define some threshold for a difference between the two slopes
if the slope crosses the threshold,
store the line between START AND CURR as a SIDE
define CURR as a new START
repeat until CURR is within a certain radius of the original START or crosses one of the previous sides
you might be able to determine the shape simply by counting sides.
For each point along the 100-agon, find the area of the tiny triangle formed by that point and the points on either side. Remove the point that created the smallest triangle. Repeat until the smallest triangle is larger than some threshold.
I'm looking for an algorithm that would move a point around an arbitrary closed polygon that is not self-crossing in N time. For example, move a point smoothly around a circle in 3 seconds.
1) Calculate the polygon's perimeter (or estimate it if exact time of circling
is not critical)
2) divide the perimieter by the time desired for circling
3) move point around polygon at this speed.
Edit following ire and curses' comment.
Maybe I read the question too literally, I fail to see the difficulty or the points raised by ire_and_curses.
The following describes more specifically the logic I imagine for step #3. A more exact description would require knowing details about the coordinate system, the structure used to describe the polygon, and indication abou the desired/allowed animation refreshing frequency.
The "travellng point" which goes around the polygon would start on any edge of the polygop (maybe on a vertex, as so to make the start and end point more obvious) and would stay on an edge at all time.
From this starting point, be it predetermined or randomly selected), the traveling point would move towards towards a vertex, at the calculated speed. Once there it would go towards the other vertex of the edge it just arrived to, and proceed till it returns to the starting point.
The equations for calculating the points on a given edge are the same that for tracing a polygon: simple trig or even pythagoras (*). The visual effect is based on refreshing the position of the traveling point at least 15 times or so per second. The refresh frequency (or rather its period) can be used to determine the distance of two consecutive points of the animation.
The only less trivial task is to detect the end of a given edge, i.e. when the traveling point needs to "turn" to follow the next edge. On these occasions, a fractional travel distance needs to be computed so that the next point in the animation is on the next edge. Special mention also for extremely short edges, as these may require the fractional distance logic to be repeated (or done differently).
Sorry for such a verbose explanation for a rather straight forward literally ;-) algorithm...
Correction: as pointed out by Jefromi in comment for other response, all that is needed with regard to the tracing is merely to decompose the x and y components of the motion. Although we do need Pythagoras for calculating the distance between each vertex for the perimeter calculation, and we do need to extrapolate because the number of animation steps on an edge is not [necessarily] a integer.
For the record, a circle is not a polygon--it's the limit of a regular polygon as the number of sides go to infinity, but it's not a polygon. What I'm giving you isn't going to work if you don't have defined points.
Assuming you have your polygon stored in some format like a list of adjacent vertices, do a O(n) check to calculate the perimeter by iterating through them and computing the distance between each point. Divide that by the time to get the velocity that you should travel.
Now, if you want to compute the path, iterate back through your vertices again and calculate from your current position where your actual position should be on the next timestep, whatever your refresh time step may be (if you need to move down a different edge, calculate how much time it would take to get to the end of your first edge, then continue on from there..). To travel along the edge, decompose your velocity vector into its components (because you know the slope of the edge from its two endpoints).
A little code might answer this with fewer words (though I'm probably too late for any votes here). Below is Python code that moves a point around a polygon at constant speed.
from turtle import *
import numpy as nx
import time
total_time = 10. # time in seconds
step_time = .02 # time for graphics to make each step
# define the polygone by the corner points
# repeat the start point for a closed polygon
p = nx.array([[0.,0.], [0.,200.], [50.,150.], [200.,200.], [200.,0.], [0.,0.]])
perim = sum([nx.sqrt(sum((p[i]-p[i+1])**2)) for i in range(len(p)-1)])
distance_per_step = (step_time/total_time)*perim
seg_start = p[0] # segment start point
goto(seg_start[0], seg_start[1]) # start the graphic at this point
for i in range(len(p)-1):
seg_end = p[i+1] # final point on the segment
seg_len = nx.sqrt(sum((seg_start-seg_end)**2))
n_steps_this_segment = int(seg_len/distance_per_step)
step = (seg_end-seg_start)/n_steps_this_segment # the vector step
#
last_point = seg_start
for i in range(n_steps_this_segment):
x = last_point + step
goto(x[0], x[1])
last_point = x
time.sleep(step_time)
seg_start = seg_end
Here I calculated the step size from the step_time (anticipating an graphics delay) but one could calculate the step size, from whatever was needed, for example, the desired speed.