class Move(object): @classmethod def choose_best_move(self, moves, end_positions): possibilities = {} for move in moves: moves_by_num = possibilities.get(move.get_num_possible_moves(), tuple()) moves_by_num = moves_by_num + (move, ) possibilities[move.get_num_possible_moves()] = moves_by_num #get the move with the least possible position, if there's more than one, go by weight fewest_moves = min(possibilities) lowest_weight = 20 best_move = None for move in possibilities[fewest_moves]: move_weight = move.get_position().get_weight() if end_positions != None: move_weight = move._check_closed_tour(move_weight, end_positions) if move_weight != None and move_weight < lowest_weight: lowest_weight = move_weight best_move = move return best_move def __init__(self, position, visited_positions): self.knight = Knight(position) self.knight.visited_positions = visited_positions self.position = position ###is this the source of the bug somehow? self.possible_moves = self.knight.get_possible_moves( ) #should be able to remove previous position/ None def _check_closed_tour(self, move_weight, end_positions): if self.get_position() in end_positions: move_weight += 10 return move_weight def get_position(self): return self.position def get_num_possible_moves(self): return len(self.possible_moves) def print_possible_moves(self): for i in self.get_possible_moves(): print "\t", i return "end of possible moves" def get_possible_moves(self): return self.possible_moves def __str__(self): return self.position.__str__()
class Move(object): @classmethod def choose_best_move(self, moves, end_positions): possibilities = {} for move in moves: moves_by_num = possibilities.get(move.get_num_possible_moves(), tuple()) moves_by_num = moves_by_num + (move,) possibilities[move.get_num_possible_moves()] = moves_by_num #get the move with the least possible position, if there's more than one, go by weight fewest_moves = min(possibilities) lowest_weight = 20 best_move = None for move in possibilities[fewest_moves]: move_weight = move.get_position().get_weight() if end_positions != None: move_weight = move._check_closed_tour(move_weight, end_positions) if move_weight != None and move_weight < lowest_weight: lowest_weight = move_weight best_move = move return best_move def __init__(self, position, visited_positions): self.knight = Knight(position) self.knight.visited_positions = visited_positions self.position = position ###is this the source of the bug somehow? self.possible_moves = self.knight.get_possible_moves() #should be able to remove previous position/ None def _check_closed_tour(self, move_weight, end_positions): if self.get_position() in end_positions: move_weight += 10 return move_weight def get_position(self): return self.position def get_num_possible_moves(self): return len(self.possible_moves) def print_possible_moves(self): for i in self.get_possible_moves(): print "\t", i return "end of possible moves" def get_possible_moves(self): return self.possible_moves def __str__(self): return self.position.__str__()
class Tour(object): def __init__(self, rows, columns, start_position, verbosity=0, closed=False, move_limit=None, time_limit=None): self.verbosity = Verbose(verbosity) self.closed = closed self.board = Board(rows, columns, self.verbosity.verbose_int) self.start_position = self._generate_start_position(start_position) self.retrace = 0 #just in case I want to set up a retrace counter self.end_positions = None self.move_limit = move_limit self.time_limit = time_limit def run(self): self.knight = Knight(self.start_position, self.verbosity.verbose_int) self.knight.add_to_board(self.board) if self.closed == True: self.end_positions = self.knight.get_possible_moves() count = 0 duration = 0 largest_tour = 0 start = time.time() complete = False while len(self.knight.visited_positions) < self.board.size and self._check_limit(count, duration): #garner stats largest_tour = self.verbosity.min_max(self, largest_tour) self.verbosity.potential_OBOB(self) self.verbosity.progress(count) if len(self.knight.visited_positions) < 4: largest_tour = len(self.knight.visited_positions) if self.time_limit != None and count%1000 == 0: duration = time.time()-start #find the next move possible_positions = self.knight.get_possible_moves() self.verbosity.possible_moves(self.knight.get_current_position(), possible_positions) if len(possible_positions) == 0: previous_position = self.knight.retrace() t = Trace(count, previous_position, retrace=True) count += 1 continue initial_moves = [] for position in possible_positions: #the position already has a weight when it's created if self._check_closed_tour(position, count) == True: #either the tour is complete, or the knight retraced and we return to the while loop complete = True break move = Move(position, self.knight.get_visited_positions()[:]) initial_moves.append(move) if len(initial_moves) != 0 and complete != True: best_move = Move.choose_best_move(initial_moves, self.end_positions) if not self.knight.set_position(best_move.get_position()): raise MoveError(best_move.get_position()) t = Trace(count, best_move.get_position(), retrace=False) count += 1 end_time = round(time.time() - start,3) return self.knight, count, self.board, end_time def _check_closed_tour(self, position, count): if len(self.knight.visited_positions) == (self.board.size -1) and self.closed == True: if position in self.end_positions: t = Trace(count, position, retrace=False) self.knight.set_position(position) #final position of the closed tour has been reached else: previous_position = self.knight.retrace() t = Trace(count, previous_position, retrace=True) return True def _check_limit(self, count, duration): if self.move_limit != None and count > self.move_limit: raise GameError() elif self.time_limit != None and duration > self.time_limit: raise GameError() else: return True def _generate_start_position(self, start_position): error1 = "The %s value of your start position must be an integer. Please enter the starting location in the following format: 4.5" error2 = "the %s (the %s value of the starting position) does not fit on the board" row_column = start_position.split(".") assert len(row_column) is 2, "start position must contain exactly one '.' period" try: row = int(row_column[0]) except ValueError: print error1 %("first") exit(1) try: column = int(row_column[1]) except ValueError: print error1 %("second") exit(1) assert 0 < row <= self.board.rows, error2 %("row","first") assert 0 < column <= self.board.columns, error2 %("column","second") return Position(row, column, self.board, self.verbosity.verbose_int)