[SOLVED] Astar ID (2D Tilemap), need different weight when moving from land to water, then from water to water.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By eod

Turn based strategy game.
Character can move through water and land.
I’ve built a small tilemap, with water and land tiles.
I’ve built an AStar, with each point connected to it’s neighbor, including it’s diagonal neighbor.
Bidirection movement between points is enabled.

I have set weights for each point:
Land tile weight = 2
Water tile weight = 3

Here’s a section of the tilemap:

  • Weights are shown
  • “x” is my character
  • “o” is where I want my character to go to

Say the character has 20 movement points. If I call get_point_path(id of "x", id of "o") I would get this path:

With the character having 5 movement points left over.
(e.g. 20 -2 -3 -3 -3 -2 -2 = 5)

How can I modify my AStar (or add a new Astar or whatever) so that moving from land tile to water tile has a tile weight (movement cost) = 6? But, when moving from a water tile to water tile, the tile weight remains = 3?

With the tile weight for land to water in place:

With the character having 2 movement points left over.
*(e.g. 20 -2 -6 -3 -3 -3 -2 -2 = 2)

Solutions I have considered:

  • Make all coastal water tiles have a weight = 6; But now, if character was in the water, moving along the coast would be 6 movement points each tile instead of the desired 3.
  • Create two AStar IDs with the same “position”. Have one be of weight 3 and one of weight 6. Have a “one-way” directional connections from land to the water tile of weight 6. Have a “one-way” directional connections from water to water with weights of 3. Not sure that Astar can handle this specific set-up properly though… maybe I need to use get_point_position() instead for this to work.
:bust_in_silhouette: Reply From: aa

Interesting question. I’m no expert but I can’t see a clear way of doing this by reading the documentation. I suppose to make it work properly as stated you’d have to create some sort of meta system. Potentially you could make something that kept track of movement paths until each such transition border was reached, recalculate from that point and then process all these paths together in a sort of… astar of astars?

A simpler solution might be to expand your tile types here from 2 to 3 so that you have Land, Water and Land-Water-Transition tiles. So that:

[L] [L] [T] [W] [W] would equal [2] [2] [6] [3] [3] without any more fuss.

Thanks for your response.

So that was one solution I tried, and the land to water transition with weight 6 would be correct. However, if the character was on water, travelling from a water tile to a coastal tile would have a weight cost of 6, instead of 3:

[W][comment0-T][L] would equal [3][comment0-6][2], but I would want: [3][comment0-3][2]

What I am doing currently (seems to work so far) is adding 2 different AStar points with the same position, but different connections to their neighbors. For instance, say the center tile in both below have the same AStar position but are different AStar points, I would connect them as follows:

e.g. [Land][comment0-Water][Water]

Center tile is water w/ coastal weight 6 if moving from land to water
[2]<->[6] ->[3]

Center tile is water w/ water weight 3 if moving from water to water
[2]<- [3]<->[3]

Having 2 AStar IDs allows both get_id_path() and get_point_path() to return the correct shortest path based on weight and where the character resides.

The code just gets complicated really quickly … and I have a gut feeling something more elegant can exist.

eod | 2020-01-03 14:42

I see, yeah in that case my simple solution wouldn’t work. With your solution, how does that work if you have a situation where you have to calculate an astar path that goes in and out of water several times? Or is that not a requirement?

aa | 2020-01-03 17:24

I wanted to wait until I got my solution working before responding, and it does end up working, just lots of extra logic code.

Yes, it works going in and out of water several times. Because of the one-way connections between the AStar points, it will always choose a “Watercoast” tile when going from Land to Water, and that weight is 6. If a unit is already in the water, then the AStar path will choose the “Water” tile and its weight of 3 when calculating shortest path.

What would be nice, is if we could do this simply by entering a “to_weight” when connecting points, i.e.
void connect_points ( int id, int to_id, bool bidirectional=true, int to_weight )

Though I imagine a lot more coding would have to be done to accommodate that, keep things organized with the class and backward compatibility.

eod | 2020-01-04 03:28