Hey again!

You can accomplish this using distinct types. The unit tests for AStar are a 
bit convoluted, but that's how they work:

[https://github.com/Nycto/AStarNim/blob/master/test/astar_test.nim#L7-L12](https://github.com/Nycto/AStarNim/blob/master/test/astar_test.nim#L7-L12)

For your example, I believe this should compile:
    
    
    import astar, hashes
    
    type
        Grid = seq[seq[int]]
            ## A matrix of nodes. Each cell is the cost of moving to that node
        
        Point = tuple[x, y: int]
            ## A point within that grid
        
        GridOne = distinct Grid
        
        GridTwo = distinct Grid
        
        AnyGrid = GridOne|GridTwo
    
    template yieldIfExists( grid: AnyGrid, point: Point ) =
        ## Checks if a point exists within a grid, then calls yield it if it 
does
        let exists =
            point.y >= 0 and point.y < grid.len and
            point.x >= 0 and point.x < grid[point.y].len
        if exists:
            yield point
    
    proc `[]`( grid: AnyGrid, index: int ): seq[int] =
        Grid(grid)[index]
    
    converter toGrid(g: GridOne): Grid = Grid(g)
    converter toGrid(g: GridTwo): Grid = Grid(g)
    
    iterator neighbors*( grid: AnyGrid, point: Point ): Point =
        ## An iterator that yields the neighbors of a given point
        yieldIfExists( grid, (x: point.x - 1, y: point.y) )
        yieldIfExists( grid, (x: point.x + 1, y: point.y) )
        yieldIfExists( grid, (x: point.x, y: point.y - 1) )
        yieldIfExists( grid, (x: point.x, y: point.y + 1) )
    
    proc heuristic*( grid: AnyGrid, node, goal: Point ): float =
        ## Returns the priority of inspecting the given node
        asTheCrowFlies(node, goal)
    
    proc cost(grid: GridOne, a, b: Point): float =
        ## Returns the cost of moving from point `a` to point `b`
        float(grid[a.y][a.x])
    
    proc cost(grid: GridTwo, a, b: Point): float =
        ## Returns the cost of moving from point `a` to point `b`
        float(grid[a.y][a.x] - grid[b.y][b.x] + 1)
    
    # A sample grid. Each number represents the cost of moving to that space
    let grid = @[
        @[ 0, 0, 0, 0, 0 ],
        @[ 0, 3, 3, 3, 0 ],
        @[ 0, 3, 5, 3, 0 ],
        @[ 0, 3, 3, 3, 0 ],
        @[ 0, 0, 0, 0, 0 ]
    ]
    
    let start: Point = (x: 0, y: 3)
    let goal: Point = (x: 4, y: 3)
    
    proc print_route(g:AnyGrid, p1,p2:Point):void =
        for point in path[AnyGrid, Point, float](g, p1, p2):
            echo point
    
    echo "Cost Function 1:"
    print_route[GridOne](GridOne(grid), start, goal)
    
    echo "Cost Function 2:"
    print_route[GridTwo](GridTwo(grid), start, goal)
    

Reply via email to