Search code examples
graph-theorypath-findinggodot

How can I make individual paths acyclical while allowing multiple paths to traverse the same vertices?


I am recreating an old family favorite board game in Godot (Rail Baron). You roll dice and then move that far along railroads (edges) from stop to stop (vertices). essentially it's "exercises in graph theory: the game".

The function I've written to find all vertices k moves away from a given node (giving the legal moves after a die roll) doesn't work because if a node has been visited before, the function won't recur on that node, meaning each node can only be traveled once while looking for all paths. I know I could just ignore the requirement that nodes only be traversed once per path, but that would become very computationally expensive as I would be generating many possible routes that no human would ever take - and it's also against the game rules (your train has to continue in the same direction as long as it's on one railroad).

Can I have my cake and eat it too?

Here's a pdf of the game board to help visualize the graph https://www.railgamefans.com/rbp/files/u21sm.pdf

and here is my pathfinding function. My graph is represented as an adjacency list.

var visited = []
func get_move_options(i, stop):
    var counter = i
    visited.append(stop)
    while counter > 0:
        counter -= 1
        for neighbor in adjList[stop]:
            if not neighbor.name in visited:
                get_move_options(counter, neighbor.name)
    var stopNodeHighlight = get_parent().get_node(stop).get_node('Highlight')
    if stopNodeHighlight:
        stopNodeHighlight.visible = true

Solution

  • Instead of the visited array/list have a 'parent' parameter the node from witch you came from. Then simply check if neighbor.name != parent If you are on a node where you can turn back freely (If you can turn right back on crossroads) you can set parent to something invalid.

    func get_move_options(i, stop,parent):
        var counter = i
        if  ... : (you can turn back from here (train is not on rail? you can put i>2 to check if we are on a crossroad))
            parent="Something unrealistic like null or this stupid string"
        while counter > 0:
            counter -= 1
            for neighbor in adjList[stop]:
                if not neighbor.name != parent:
                    get_move_options(counter, neighbor.name,stop)
        var stopNodeHighlight = get_parent().get_node(stop).get_node('Highlight')
        if stopNodeHighlight:
            stopNodeHighlight.visible = true
    

    Note: If I made a syntax error sorry I don't know the language