def test_winner_2(self): """Get the winner.""" board = Board([[1, 2, 3, 4, 3, 2]], workers={ self.workers[0]: (0, 0), self.workers[2]: (0, 1) }) self.assertFalse(rulechecker.get_winner(board)) board.move_worker(self.workers[2], Direction.EAST) self.assertEqual(rulechecker.get_winner(board), "player2")
def _play_game(self, players): """ Plays a game out and returns the result of the game. :param list players: List of two Uuids in order of who goes first :rtype tuple(PlayerResult, Uuid): the result of the game """ # start phase for player in players: player_guard = self.uuids_to_player[player] try: player_guard.start_of_game() except PlayerError: return (PlayerResult.NEFARIOUS, player) # placement phase for worker_num in range(Worker.NUM_WORKERS): for player in players: current_player_guard = self.uuids_to_player[player] place_result = self._place_worker(current_player_guard) if place_result is PlayerResult.OK: continue else: return (place_result, player) # play phase id_and_players = zip(players, [self.uuids_to_player[player] for player in players]) for player_uuid, player in itertools.cycle(id_and_players): turn_result = self._play_turn(player) if turn_result is PlayerResult.OK: continue else: return (turn_result, player_uuid) workers = [w for w in self.board.workers if w.player == player_uuid] if rulechecker.is_game_over(copy.deepcopy(self.board), workers): return (PlayerResult.OK, rulechecker.get_winner(self.board))
def test_winner_move_no_build(self): board = Board( [[0, 0, 1, 0], [0, 4, 4], [4, 4]], workers={ self.workers[0]: (0, 0), self.workers[1]: (1, 0), self.workers[2]: (0, 1), self.workers[3]: (0, 3) }) self.assertEqual(rulechecker.get_winner(board), "player2")
def test_winner_lock_in(self): board = Board( [[0, 1, 3, 4, 3, 0], [1, 2, 4, 4, 4, 3]], workers={ self.workers[0]: (0, 0), self.workers[1]: (0, 5), self.workers[2]: (1, 0), self.workers[3]: (0, 1) }) self.assertEqual(rulechecker.get_winner(board), "player2")
def do_survive(board, pname, depth, worker=None, move_dir=None, build_dir=None): """Given a game state, and a look-ahead depth and an optional turn, return whether or not the given player name survives up to the depth number of rounds. :param Board board: A game board :param str pname: A player name :param int depth: the number of look-ahead rounds :param Worker worker: an optional worker to move and/or build :param Direction move_dir: The direction to move the given worker if a worker was given :param Direction build_dir: An optional direction the worker builds in :rtype bool: if we survived depth number of rounds """ copied_board = copy.deepcopy(board) if move_dir: copied_board.move_worker(worker, move_dir) if build_dir: copied_board.build_floor(worker, build_dir) else: # if there's no build, you must win this turn return rulechecker.get_winner(copied_board) == pname checkwin = rulechecker.get_winner(copied_board) if checkwin == pname: # if we won, we survived logger.info( str(pname) + " won a case Board:" + str(board) + " at Depth:" + str(depth)) depth -= 1 return True elif checkwin: logger.info( str(pname) + " won a case Board:" + str(board) + " at Depth:" + str(depth)) # if we lost, we died return False # base case, if there's no winner, we survived if depth == 0: logger.info("player" + pname + "lived with this move:" + str(copied_board) + " depth:" + str(depth)) return not rulechecker.get_winner(copied_board) # recursive case opp_workers = [w for w in copied_board.workers if pname != w.player] our_workers = [w for w in copied_board.workers if pname == w.player] enemy_turns = TreeStrategy.next_turn(opp_workers, copied_board) viable_move = False if move_dir: for enemy_worker, enemy_move, enemy_build in enemy_turns: next_board = copy.deepcopy(copied_board) next_board.move_worker(enemy_worker, enemy_move) if enemy_build: next_board.build_floor(enemy_worker, enemy_build) winner = rulechecker.get_winner(next_board) if (winner and winner != pname): #enemy found a way to kill you on their move, return False logger.info("player " + str(winner) + " kills with this move:" + str(next_board) + " depth:" + str(depth)) return False if depth > 1: our_turns = TreeStrategy.next_turn(our_workers, next_board) safe = False # check that we have a safe move for our_worker, our_move, our_build in our_turns: if TreeStrategy.do_survive(next_board, pname, depth - 2, worker=our_worker, move_dir=our_move, build_dir=our_build): logger.info("player " + str(pname) + " survived with this move:" + str(next_board) + " depth:" + str(depth)) continue else: safe = True break if safe: viable_move = True # fell through # if depth was 1, that means that we were checking if the enemy could kill us, and if so that means this should # be True cause they failed to kill us # if depth was 2 or more that means searching for more moves failed, and we died logger.info("player " + str(pname) + " depth:" + str(depth) + " viable_move" + str(viable_move)) return depth < 2 or viable_move else: our_turns = TreeStrategy.next_turn(our_workers, copied_board) for our_worker, our_move, our_build in our_turns: if TreeStrategy.do_survive(copied_board, pname, depth - 2, worker=our_worker, move_dir=our_move, build_dir=our_build): logger.info("player " + str(pname) + " survived with this move:" + str(copied_board) + " depth:" + str(depth)) return True logger.info("player " + str(pname) + " can't survive with this board:" + str(copied_board) + " depth:" + str(depth)) return False
def test_no_winner(self): """Get the winner.""" board = Board(workers={self.workers[0]: (0, 2)}) self.assertFalse(rulechecker.get_winner(board))
def test_winner_1(self): """Get the winner.""" board = Board([[0, 0, 3, 0, 0, 0]], workers={self.workers[0]: (0, 2)}) self.assertEqual(rulechecker.get_winner(board), "player1")