This reddit question[1] made me think about edge-to-edge pathfinding. A* works whenever you can give it “locations” (possibly abstract) and “connections” between locations. For pipe connectivity the locations are tile edges. The connections are whatever you can get to with a straight pipe or a bent pipe.
Coordinates
I’m going to use the tile edge coordinates from here[2] except I’ll use top-left coordinates: tile 0,0 will have 0,0,W on the left and 1,0,W on the right. It will have 0,0,N on the top and 0,1,N on the bottom.
Connectivity
Rules for vertical edge: i,j,W →
- i-2,j-1,N [red]
- i-2,j+2,N [red]
- i+1,j-1,N [red]
- i+1,j+2,N [red]
- i-5,j,W [blue]
- i+5,j,W [blue]
Rules for horizontal edge: i,j,N →
- i+2,j+1,W [red]
- i+2,j-2,W [red]
- i-1,j+1,W [red]
- i-1,j-2,W [red]
- i,j-5,N [blue]
- i,j+5,N [blue]
Demo
(implement interactive demo showing connectivity)
1 - draw grid 2 - mark an edge on the grid in a color 3 - mouse position to closest edge (diamond tile shape) 4 - mouse hover handler to update which edge we're looking at
Demo 2
(implement interactive demo showing pathfinding)
5 - neighbors() function for A* that implements our movement rules, and filters for edges actually on the map 6 - pathfinding code using edge coordinates and neighbors() 7 - mouse drag handler to move start/end point of A* 8 - output drawing code that distinguishes two different types of pipe pieces