Remove hardcoding of adjacent positions

Allowed moves can now be added to `moves` and most things should just work. Additionally, `new_pos`, `diff_pos` and `manhattan_dist` have been moved to graph.py and `AdjacencyList` has been made universe agnostic.

Breaking API change: `NoPositionException` has been removed and graph functions will now raise a `NoPathException` when input positions are not valid for a given graph.