class Player(object): def __init__(self, algorithm, number): '''Initializes a Player object. Must be given an algorithm (a strategy for the player to use, in the form of a function like bfs from bfs.py) and a number to use as the player ID slash player starting location.''' # each player has a strategy (e.g. bfs, dfs) self.algorithm = algorithm # self.status is True if the player has legal moves remaining. self.status = True # each player has its own graph. self.graph = Graph() # number is the starting corner. self.number = number # 0 = top left, 1 = top right, 2 = bottom left, 3 = bottom right self.start_corner = self.graph.get_corners()[self.number] self.turn_count = 0 def play_on_corner(self): '''Plays in the player's starting corner. This is not a legal move by the normal rules of the game and thus requires its own method so that game.py and graph.py know this move is acceptable.''' self.graph.play_piece(self.start_corner, self.number, [], first=True) def take_turn(self, other_graphs): '''Plays a piece according to the rules of the game. Needs the graphs of all of the other players so that multiple players can interact.''' # find all of the playable nodes. playable = self.graph.get_susceptible_nodes(other_graphs) # if there are no playable nodes, the player is 'dead'. if len(playable) == 0: print "Player %s is out of places to play." % self.number self.status = False # use the algorithm self.algorithm to put a piece down. if isinstance(self.algorithm, list): if isinstance(self.algorithm[0], int): seed = randint(0, 100) if seed < self.algorithm[0]: visited = self.algorithm[1](self.graph, self.start_corner) else: visited = self.algorithm[2](self.graph, self.start_corner) elif isinstance(self.algorithm[2], int): if self.turn_count < self.algorithm[2]: visited = self.algorithm[0](self.graph, self.start_corner) else: visited = self.algorithm[1](self.graph, self.start_corner) else: visited = self.algorithm(self.graph, self.start_corner) for node in visited: if node in playable: self.graph.play_piece(node, self.number, other_graphs) self.turn_count += 1 break
class GraphTestCase(unittest.TestCase): def setUp(self): self.graph = Graph() def test_size(self): for i in xrange(3): random_size = randint(2, 30) random_graph = Graph(size=random_size) self.assertEqual(len(random_graph.nodes), random_size**2) def test_corner_degree(self): for i in [0, 19, -1, -20]: self.assertEqual(self.graph.nodes[i].get_degree(), 2) def test_side_degree(self): for i in xrange(1, 19): self.assertEqual(self.graph.nodes[i].get_degree(), 3) def test_center_degree(self): for i in xrange(21, 39): self.assertEqual(self.graph.nodes[i].get_degree(), 4) def test_horizontal_links(self): size = self.graph.size for i in xrange(size): for j in xrange(size): node = self.graph.nodes[size*i+j] try: last_node = self.graph.nodes[size*i+j-1] except IndexError: last_node = False try: next_node = self.graph.nodes[size*i+j+1] except IndexError: next_node = False last_connection = False next_connection = False for edge in node.edges: nodes = [node.edges[edge].node1, node.edges[edge].node2] if last_node in nodes: last_connection = True if next_node in nodes: next_connection = True if j != 0: self.assertEqual(last_connection, True) if j != size-1: self.assertEqual(next_connection, True) def test_vertical_links(self): size = self.graph.size for i in xrange(size): for j in xrange(size): node = self.graph.nodes[size*i+j] try: above_node = self.graph.nodes[size*i+j-size] except IndexError: above_node = False try: below_node = self.graph.nodes[size*i+j+size] except IndexError: below_node = False above_connection = False below_connection = False for edge in node.edges: nodes = [node.edges[edge].node1, node.edges[edge].node2] if above_node in nodes: above_connection = True if below_node in nodes: below_connection = True if i != 0: self.assertEqual(above_connection, True) if i != size-1: self.assertEqual(below_connection, True) def test_no_excess_links(self): size = self.graph.size for i in xrange(size): for j in xrange(size): node = self.graph.nodes[size*i+j] try: last_node = self.graph.nodes[size*i+j-1] except IndexError: last_node = False try: next_node = self.graph.nodes[size*i+j+1] except IndexError: next_node = False try: above_node = self.graph.nodes[size*i+j-size] except IndexError: above_node = False try: below_node = self.graph.nodes[size*i+j+size] except IndexError: below_node = False for edge in node.edges: nodes = [node.edges[edge].node1, node.edges[edge].node2] left = last_node in nodes and node in nodes right = next_node in nodes and node in nodes up = above_node in nodes and node in nodes down = below_node in nodes and node in nodes self.assertTrue(left or right or up or down) def test_get_playable_nodes(self): self.assertEqual(len(self.graph.get_playable_nodes([])), 0) def test_get_corners(self): self.assertEqual(len(self.graph.get_corners()), 4) for i in [0, 19, -1, -20]: self.assertTrue(self.graph.nodes[i] in self.graph.get_corners()) def test_playing_corner(self): corners = self.graph.get_corners() self.graph.play_piece(corners[0], first=True) self.assertEqual(corners[0].get_directed_degree(), 3) def test_get_diagonal_nodes(self): # test one from the center center = (self.graph.size**2) / 2 + (self.graph.size / 2) cn = self.graph.nodes[center] ul = self.graph.nodes[center - self.graph.size - 1] ur = self.graph.nodes[center - self.graph.size + 1] dl = self.graph.nodes[center + self.graph.size - 1] dr = self.graph.nodes[center + self.graph.size + 1] self.assertEqual(self.graph.get_diagonal_nodes(cn), [ul, dl, ur, dr]) # TODO: one from the right edge # TODO: one from the left edge # TODO: one from the top edge # TODO: one from the bottom edge # TODO: for now, top left and bottom right will handle the above # only one corner for the top left tl = self.graph.nodes[0] tldr = self.graph.nodes[self.graph.size + 1] self.assertEqual(self.graph.get_diagonal_nodes(tl), [tldr]) # same for the bottom right br = self.graph.nodes[-1] brul = self.graph.nodes[-1 * self.graph.size - 2] self.assertEqual(self.graph.get_diagonal_nodes(br), [brul]) def test_get_adjacent_nodes(self): # test one from the center center = (self.graph.size**2) / 2 + (self.graph.size / 2) cn = self.graph.nodes[center] l = self.graph.nodes[center - 1] r = self.graph.nodes[center + 1] u = self.graph.nodes[center - self.graph.size] d = self.graph.nodes[center + self.graph.size] self.assertEqual(self.graph.get_adjacent_nodes(cn), [l, r, u, d]) # TODO: one from the right edge # TODO: one from the left edge # TODO: one from the top edge # TODO: one from the bottom edge # TODO: for now, top left and bottom right will handle the above # only one corner for the top left tl = self.graph.nodes[0] tlr = self.graph.nodes[1] tld = self.graph.nodes[self.graph.size] self.assertEqual(set(self.graph.get_adjacent_nodes(tl)), set([tlr, tld])) # same for the bottom right br = self.graph.nodes[-1] brl = self.graph.nodes[-2] bru = self.graph.nodes[-1*self.graph.size-1] self.assertEqual(set(self.graph.get_adjacent_nodes(br)), set([brl, bru])) def test_is_played(self): pass