-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmovepaths.py
More file actions
76 lines (65 loc) · 2.47 KB
/
movepaths.py
File metadata and controls
76 lines (65 loc) · 2.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
"""Provides various classes used for finding, storing, and manipulating move
path data."""
from functools import lru_cache
from tripeg.game import BaseGame
class DummyGame(BaseGame):
"""Used to convert 'MainGame' objects into a more streamlined
version in order to iterate over move paths at maximum speed."""
def __init__(self, game=None):
"""Initialize self. See help(type(self)) for accurate signature."""
if game and game.started:
self.started = True
self.board = game.board.copy()
self.peg_count = game.peg_count
self.moves = game.moves.copy()
else:
super().__call__()
class Node:
"""Wrapper for data allowing it to function as a node."""
def __init__(self, data=None):
"""Initialize self. See help(type(self)) for accurate signature."""
self.data = data
class PathFinder:
"""Provides methods to find move paths that meet various criteria.
Should be called after the player makes a move.
"""
_game = None
best_path = None
best_score = None
def __call__(self, game):
"""Call self as function."""
if not game:
self._game = DummyGame()
elif not isinstance(game, DummyGame):
self._game = DummyGame(game)
else:
self._game = game
moves = self._game.moves
self.possible_paths = dict.fromkeys(range(1,9))
root = Node(moves[-1])
self._find_paths(root)
self._find_paths.cache_clear()
found_scores = [score for score in self.possible_paths.keys() if
self.possible_paths[score]]
self.best_score = min(found_scores)
self.best_path = self.possible_paths[self.best_score]
@lru_cache(None)
def _find_paths(self, node):
"""Finds possible paths and records them in 'possible_paths'."""
legal_moves = self._game.find_legal_moves()
if not legal_moves:
score = self._game.peg_count
if not self.possible_paths[score]:
self.possible_paths[score] = self._game.moves.copy()
else:
children = []
for peg in legal_moves:
for move in legal_moves[peg]:
children.append(Node((peg, move)))
for child in children:
self._game.move(*child.data)
self._find_paths(child)
try:
self._game.undo()
except IndexError:
pass