10
\$\begingroup\$

I'm having issues coming up with a specific search term for this, but how would one go about finding the possible moves in a 2D turn-based strategy game (i.e. FF:Tactics, Fire Emblem, Advance Wars).

enter image description here

I'm not so much thinking about terrain (or even collision) at this point. I'm just wondering what algorithm I can use to figure out that X entity can move 5 tiles and attack 2 farther tiles than that.

I know I can use something like Dijkstra to find the distance between two points. One possible implementation is starting at the players location and then branching off from there until the distance returned by Dijkstra is greater than the move count.

Just wondering if someone could point me in the right direction (i.e. name of algorithms, technique, articles, etc).

\$\endgroup\$
5
  • \$\begingroup\$ I'm thinking it's called path finding, for a search term? If you use path finding then you could have counters to handle what you need \$\endgroup\$
    – Exikle
    Sep 9, 2013 at 12:48
  • \$\begingroup\$ This is essentially part of path finding (calculating meta data for movement costs). You only determine locations that are within range, but you don't necessarily determine the route you'd take as well. \$\endgroup\$
    – Mario
    Sep 9, 2013 at 21:44
  • 1
    \$\begingroup\$ It's not real-time (RTS) if it's turn-based à la FFTactics. :p \$\endgroup\$
    – Alayric
    Sep 9, 2013 at 22:24
  • \$\begingroup\$ In 2d, you could use Taxicab/Manhattan calculation en.wikipedia.org/wiki/Taxicab_geometry \$\endgroup\$ Sep 11, 2013 at 14:41
  • \$\begingroup\$ My Dijkstra's/BFS alike solution here - gamedev.stackexchange.com/a/195239/93428 \$\endgroup\$ Aug 15, 2021 at 2:00

3 Answers 3

5
\$\begingroup\$

I think a bounded Dijkstra is precisely what you want to use. The way that Dijkstra finds the distance between two points is it maps out the distance to every node from an origin node, and then 'selects' the shortest path from this distance map. You want to do virtually the same thing, except you want the distance node graph it creates as output, rather than a path to any particular point.

The one modification you'll want to make is to skip calculating the distance from nodes that have already exceeded your maximum movement range. Then you'll have a node graph of all of the nodes that the unit can travel to, plus a border, so just cut out the nodes that have a distance greater than the movement allowance.

Viola.

In other words, pretty much what you described in your question is what you need to do. It also has the benefit of being able to use the output to do the pathfinding, without need to do any further calculations.

\$\endgroup\$
7
  • \$\begingroup\$ I think Dijkstra's is overkill in this case. The OP doesn't need a path to all possible movement destinations, just a yes/no answer on whether an agent can get there. He can compute a path later once the user has picked one. \$\endgroup\$ Sep 9, 2013 at 15:13
  • \$\begingroup\$ The cost of using Dijkstra's algorithm to calculate the path after a destination has been decided upon is almost exactly the same as using it upfront (unless you use a heuristic approach like A* for pathing). Not doing it up front simply creates redundant work, as Dijkstra would answer both the questions 'where can I go' and 'how do I get there?'. It also allows for the addition of complications to the environment that change the movement cost, though that may be unnecessary for the application. Further, the approach is well documented, which is helpful to the implementer. \$\endgroup\$
    – TASagent
    Sep 9, 2013 at 17:18
  • 1
    \$\begingroup\$ On looking over Mario's answer, he actually describes Dijkstra's algorithm, except he inverts the distance, and doesn't mention it is Dijkstra. \$\endgroup\$
    – TASagent
    Sep 9, 2013 at 17:20
  • 2
    \$\begingroup\$ Wouldn't say it's Dijkstra, because you're not really looking for a shortest route nor are you trying to reach some specific point. It is essentially the first part of Dijkstra's Algorithm, that's true though. The problem with your wording, using Dijkstra, can be misleading and I think this is also what confused Michael. He probably thought you suggested using Dijkstra once for each field/cell. \$\endgroup\$
    – Mario
    Sep 9, 2013 at 21:41
  • 1
    \$\begingroup\$ Ending up using this approach as it worked well and is very easy to extend to handle obstacles. \$\endgroup\$
    – NRaf
    Sep 11, 2013 at 21:57
12
\$\begingroup\$

Most simple (and probably most naive) approach I can think of right now:

  • Start at your character and mark all surrounding fields as steps - 1.
  • Iterate over all newly marked fields and once again mark their surrounding fields as steps - 1 where steps would be the current field's step number, unless the new field has an already higher number.
  • Repeat the last step till you're running out of steps.
\$\endgroup\$
2
2
\$\begingroup\$

I think what you're looking for might be Manhattan Distance. Assuming no obstacles, you can say that a square is reachable simply if:

|toX-fromX| + |toY-fromY| < maxMoveDistance

This algorithm may not be the right direction to go if you're going to have obstacles later; one possible way to adapt it might involve having obstacles cast 'shadows' and re-evaluating from the nearest point.

EDIT (Because I have a bit more spare time now):

By 'shadows' I mean something like this, if 0 is a reachable square, C is the character, and X is an obstacle:

 012345678
0    0
1   00
2  000X
3 000C000
4  00000
5   000
6    0
 012345678

Since (5, 2) is an obstacle, you start by assuming that you can't get to anything with x>=5 AND y<=2. You can then recalculate from another square; if you want to go to (5, 1) you could calculate the manhattan distance from (4, 1) and see if that + the distance from the character to (4, 1) is less than the player's movement distance.

This is a fairly trivial example, but if you have multiple obstacles and/or a bit longer movement range, it should be able to handle the complexity.

Whether it'd actually be any better than just flood-filling, either in programming complexity or execution efficiency, I have no clue. Just seemed like a more interesting way to solve the problem.

\$\endgroup\$
2
  • \$\begingroup\$ What do you mean by casting shadows? \$\endgroup\$
    – NRaf
    Sep 10, 2013 at 22:33
  • 1
    \$\begingroup\$ Edited for clarification. \$\endgroup\$
    – Tin Wizard
    Sep 11, 2013 at 14:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .