def sa(pos, grid, n, m, t, start_T=500, c=0.95): best_path = [] T = start_T counter = 0 moves_manager = MovesManager(grid, pos, n, m) start = time.time() while time.time() - start < t: T = start_T counter = 0 print(time.time() - start, t) cur_pos = pos.copy() cur_path = [] while (not moves_manager.check_for_exit( cur_pos, grid)) and time.time() - start < t: cur_pos = pos.copy() cur_path = moves_manager.random_moves(cur_pos, grid, n, m, (n - 2) * (m - 2)) if time.time() - start >= t: return best_path if len(best_path) == 0 or len(cur_path) < len(best_path): best_path = cur_path.copy() treshold = min(n, m) * len(cur_path) while counter < treshold and T > 0 and time.time() - start < t: temp_path = gen_neighbour(cur_path) temp_path, exit_found = moves_manager.explore( pos.copy(), temp_path, grid) if exit_found: if len(temp_path) <= len(cur_path): cur_path = temp_path.copy() if len(cur_path) < len(best_path): best_path = cur_path.copy() elif uniform(0, 1) <= calculate_probability( len(temp_path) - len(cur_path), T): cur_path = temp_path.copy() T = decrease_temperature(T, c) else: counter += 1 return best_path
def __init__(self, width=800, height=600, master=None): super().__init__(master, width=width, height=height) self.master = master self.loaded_images = dict( ) # kept to not be recycled by garbage collector key is piece's starting position self.images = dict( ) # keeping piece images based on piece starting position as key self.offset_x = -40 self.offset_y = -20 self.width = 60 self.game = ChessGame() self.moves_manager = MovesManager() self.moving = False self.moving_piece = None self.moving_piece_key = "" self.actual_moves_ids = [] self.moves = [] self.panel_top = tk.PanedWindow(master=self, width=530, height=40) self.panel_top.grid(column=0, row=1) self.panel_mid = tk.PanedWindow(master=self, width=530, height=550) self.panel_mid.grid(column=0, row=2) self.panel_bot = tk.PanedWindow(master=self, width=530, height=40) self.panel_bot.grid(column=0, row=3) self.canvas = self.create_board() self.canvas.pack(side=tk.LEFT) self.canvas.bind("<Button-1>", self.click_callback) # self.canvas.bind("<B1-Motion>", self.mouse_move_callback) TODO drag and drop ? self.text = [] self.add_annotations() self.populate_board() self.text_box = self.create_text() # TODO konfigurovatelny cas pre tahy v nejakom menu mozno self.configured_time = "05:00" self.time_p1 = strptime(self.configured_time, "%M:%S") self.time_p2 = strptime(self.configured_time, "%M:%S") self.timers = self.create_timers() self.running_timer = None
def search(pos, grid, n, m, t, p, starters): best_path = [] elite_percentage = 0.5 moves_manager = MovesManager(grid, pos, n, m) population = Population(p, starters, moves_manager) start_time = time.time() while check_time(start_time, t): best_path = get_best_path(population) population.recombinate(elite_percentage) population.mutate() print(best_path, len(best_path), time.time()-start_time) return best_path
def sa(pos, grid, n, m, t, p, starters): best_path = [] counter = 0 elite_percentage = 0.5 moves_manager = MovesManager(grid, pos, n, m) population = Population(p, starters, moves_manager) start_time = time.time() while check_time(start_time, t): best_word = search_for_words(population, dic, puzzles, best_word) population.recombinate(elite_percentage) population.mutate() print(best_word, time.time()-start_time) return best_path
def __init__(self, population_size, all_puzzles, starter_words, start_pos): self.start_pos = start_pos self.all_puzzles = all_puzzles self.moves_manager = MovesManager() self.population_size = population_size self.generation = self._gen_generation(starter_words, start_pos)
class Population: def __init__(self, population_size, all_puzzles, starter_words, start_pos): self.start_pos = start_pos self.all_puzzles = all_puzzles self.moves_manager = MovesManager() self.population_size = population_size self.generation = self._gen_generation(starter_words, start_pos) def __iter__(self): for inhabitant in self.generation: yield inhabitant def _random_word(self, length): return [random.choice(self.all_puzzles) for _ in range(length)] def _gen_generation(self, starter_words, pos): min_size = min([len(word) for word in starter_words]) max_size = max([len(word) for word in starter_words]) generation = [] for word in starter_words: generation.append(Inhabitant(list(word))) for _ in range(len(starter_words), self.population_size): word = self.moves_manager.random_moves() generation.append(Inhabitant(word)) return generation def sorted_generation(self): return sorted(self.generation, key=lambda x: x.value, reverse=True) def make_selection(self, elite_percentage, percentage=0.5): selection = [] sorted_generation = self.sorted_generation() selection_size = int(self.population_size * percentage) elite_size = int(elite_percentage * selection_size) for inhabitant in sorted_generation[:elite_size]: selection.append(inhabitant) if elite_size - selection_size < 0: for inhabitant in sorted_generation[elite_size - selection_size:]: selection.append(inhabitant) return selection def recombinate(self, elite_percentage=0.6): selection = self.make_selection(elite_percentage) permutation = np.random.permutation(len(selection)) new_generation = [] new_generation.append(Inhabitant(selection[0].gene.copy())) new_generation.append(Inhabitant(selection[1].gene.copy())) for i in range(1, len(permutation)): pivot = random.randint( 0, min( len(selection[permutation[i % len(permutation)]]), len(selection[permutation[(i + 1) % len(permutation)]]), ) // 2, ) new_word = ( selection[permutation[i % len(permutation)]][:pivot] + selection[permutation[(i + 1) % len(permutation)]][pivot:]) if len(new_generation) < self.population_size: new_generation.append(Inhabitant(new_word)) new_word = ( selection[permutation[(i + 1) % len(permutation)]][:pivot] + selection[permutation[i % len(permutation)]][pivot:]) if len(new_generation) < self.population_size: new_generation.append(Inhabitant(new_word)) self.generation = new_generation def mutate( self, min_swap_probability=0.2, max_swap_probability=0.7, inverse_probability=0.001, shift_probability=0.001, insert_probability=0.9, ): swap_probability = random.uniform(min_swap_probability, max_swap_probability) for inhabitant in self.generation[1:]: if decision(insert_probability): insert_amount = random.randint(1, 2) if decision(0.5): # remove decision possible_chars = self._random_word(insert_amount) if decision(0.33): inhabitant.gene += possible_chars elif decision(0.5): inhabitant.gene = possible_chars + inhabitant.gene else: insert_index = random.randint(1, len(inhabitant.gene)) inhabitant.gene = inhabitant.gene[: insert_index] + possible_chars + inhabitant.gene[ insert_index:] else: if (len(inhabitant) - insert_amount > 0): if decision(0.5): inhabitant.gene = inhabitant.gene[insert_amount:] else: inhabitant.gene = inhabitant.gene[:-insert_amount] else: if decision(shift_probability): shift_range = random.randint(1, 3) for _ in range(shift_range + 1): inhabitant.gene = [inhabitant.gene[-1] ] + inhabitant.gene[:-1] for i in range(len(inhabitant.gene) // 2): if decision(swap_probability): random_id = random.randint(0, len(inhabitant) - 1) inhabitant.gene[i], inhabitant.gene[random_id] = ( inhabitant.gene[random_id], inhabitant.gene[i], ) if decision(inverse_probability): inhabitant.gene = inhabitant.gene[::-1]
class Application(tk.Frame): def __init__(self, width=800, height=600, master=None): super().__init__(master, width=width, height=height) self.master = master self.loaded_images = dict( ) # kept to not be recycled by garbage collector key is piece's starting position self.images = dict( ) # keeping piece images based on piece starting position as key self.offset_x = -40 self.offset_y = -20 self.width = 60 self.game = ChessGame() self.moves_manager = MovesManager() self.moving = False self.moving_piece = None self.moving_piece_key = "" self.actual_moves_ids = [] self.moves = [] self.panel_top = tk.PanedWindow(master=self, width=530, height=40) self.panel_top.grid(column=0, row=1) self.panel_mid = tk.PanedWindow(master=self, width=530, height=550) self.panel_mid.grid(column=0, row=2) self.panel_bot = tk.PanedWindow(master=self, width=530, height=40) self.panel_bot.grid(column=0, row=3) self.canvas = self.create_board() self.canvas.pack(side=tk.LEFT) self.canvas.bind("<Button-1>", self.click_callback) # self.canvas.bind("<B1-Motion>", self.mouse_move_callback) TODO drag and drop ? self.text = [] self.add_annotations() self.populate_board() self.text_box = self.create_text() # TODO konfigurovatelny cas pre tahy v nejakom menu mozno self.configured_time = "05:00" self.time_p1 = strptime(self.configured_time, "%M:%S") self.time_p2 = strptime(self.configured_time, "%M:%S") self.timers = self.create_timers() self.running_timer = None def create_board(self): """ Method creates new chess board on tkinter canvas and returns it""" canvas = tk.Canvas(master=self.panel_mid, width=530, height=550) canvas.configure(scrollregion=(self.offset_x, self.offset_y, 20, 20)) # x1 y1 x2 y2 for i in range(8): y = i * self.width for j in range(8): x = j * self.width if ((j + 1) % 2) == 0: if ((i + 1) % 2) == 0: canvas.create_rectangle(x, y, x + self.width, y + self.width, outline="#808080", fill="#fff") # biela else: canvas.create_rectangle(x, y, x + self.width, y + self.width, outline="#808080", fill="#999") # cierna else: if ((i + 1) % 2) == 1: canvas.create_rectangle(x, y, x + self.width, y + self.width, outline="#808080", fill="#fff") # biela else: canvas.create_rectangle(x, y, x + self.width, y + self.width, outline="#808080", fill="#999") # cierna return canvas def add_annotations(self): """ Method adds numbers and letters to board sides """ for i in range(8): self.text.append( self.canvas.create_text(-self.width / 2, (self.width / 2) + (i * self.width), font=("Purisa", 12), anchor="nw")) self.canvas.itemconfig(self.text[i], text=str((i - 8) * -1)) for i in range(8): self.text.append( self.canvas.create_text((self.width / 2) + (i * self.width), self.width * 8 + 10, font=("Purisa", 12), anchor="nw")) self.canvas.itemconfig(self.text[i + 8], text=string.ascii_lowercase[i]) def populate_board(self): """ Method adds images on canvas board """ for key, value in self.game.white_pieces.items(): x_pos = self.width * value.x_pos y_pos = self.width * value.y_pos img = self.load_image("images/" + value.image, value.starting_position) self.place_image_on_canvas(x_pos, y_pos, img, "images/" + value.image, value.starting_position) for key, value in self.game.black_pieces.items(): x_pos = self.width * value.x_pos y_pos = self.width * value.y_pos img = self.load_image("images/" + value.image, value.starting_position) self.place_image_on_canvas(x_pos, y_pos, img, "images/" + value.image, value.starting_position) def load_image(self, image_name, piece_name): """ Helper method for loading images """ img = ImageTk.PhotoImage(Image.open(image_name)) self.loaded_images[piece_name] = (img, image_name) return img def place_image_on_canvas(self, x, y, img, image_name, piece_starting_position): image_id = self.canvas.create_image(x, y, image=img, tags=(image_name, "piece"), anchor="nw") self.images[piece_starting_position] = image_id def remove_image_from_canvas(self, piece_starting_position): print("Removing image on key ", piece_starting_position) self.canvas.delete(self.images[piece_starting_position]) def move_image_on_canvas(self, new_x, new_y, piece_starting_position): self.remove_image_from_canvas(piece_starting_position) img, image_name = self.loaded_images[piece_starting_position] self.place_image_on_canvas(self.width * new_x, self.width * new_y, img, image_name, piece_starting_position) def show_moves_on_canvas(self, moves): for move in moves: # If K is in moves there is check # TODO toto asi nebude potrebne ked bude spravne spraveny check if move != "K": self.actual_moves_ids.append( self.canvas.create_oval( move[0] * self.width + 15, move[1] * self.width + 15, move[0] * self.width + 15 + (self.width / 2), move[1] * self.width + 15 + (self.width / 2), fill="green")) def clear_moves_on_canvas(self): for move in self.actual_moves_ids: self.canvas.delete(move) """ Create textbox on right side and method to write to it """ def create_text(self): text_box = tk.Text(master=self.panel_mid, height=28, width=31) text_box.insert(tk.END, "Welcome.\nIt's been a long minute.\n\n") scrollbar = tk.Scrollbar(master=self.panel_mid, command=text_box.yview, orient=tk.VERTICAL) text_box.config(yscrollcommand=scrollbar.set) scrollbar.pack(side=tk.RIGHT, fill=tk.Y, expand=False) text_box.configure(state=tk.DISABLED) text_box.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True) return text_box def write_text(self, text): self.text_box['state'] = tk.NORMAL self.text_box.insert(tk.END, text) self.text_box['state'] = tk.DISABLED """ Timers """ def create_timers(self): timers = [] timer1_textbox = tk.Label(master=self.panel_top, height=1, width=8) timer1_textbox.configure(text=str(self.time_p1.tm_min).zfill(2) + ":" + str(self.time_p1.tm_sec).zfill(2)) timer1_textbox.pack(side=tk.TOP, expand=True) timers.append(timer1_textbox) timer2_textbox = tk.Label(master=self.panel_bot, height=1, width=8) timer2_textbox.configure(text=str(self.time_p2.tm_min).zfill(2) + ":" + str(self.time_p2.tm_sec).zfill(2)) timer2_textbox.pack(side=tk.RIGHT, expand=True) timers.append(timer2_textbox) return timers def start_opponents_timer(self, timer, p): """ Starts timer on opponents clock and stops players timer :param timer: timer from timer array :param p: index of opponent 1 - white, 2 - black """ if self.running_timer is not None: self.after_cancel(self.running_timer) self.running_timer = None self.running_timer = self.after(1000, self.show_time, timer, p) else: # First move self.running_timer = self.after(1000, self.show_time, timer, p) def show_time(self, timer, p): if p == 2: sec = self.time_p1.tm_sec min = self.time_p1.tm_min else: sec = self.time_p2.tm_sec min = self.time_p2.tm_min sec = sec - 1 if sec < 0: sec = 59 min = min - 1 if min <= 0: self.stop_game(p) if p == 2: self.time_p1 = strptime(str(min) + ":" + str(sec), "%M:%S") else: self.time_p2 = strptime(str(min) + ":" + str(sec), "%M:%S") timer.configure(text=str(min).zfill(2) + ":" + str(sec).zfill(2)) self.running_timer = self.after(1000, self.show_time, timer, p) """ Other game methods """ # TODO undo funkcionalitu def undo_move(self): raise NotImplemented def raise_check(self): self.write_text("+ ") self.game.is_game_checked = True def remove_check(self): self.game.is_game_checked = False def stop_game(self, p): print("Game stopped because of timeout, player " + str(p) + " wins") self.canvas.unbind("<Button-1>", self.click_callback) self.after_cancel(self.running_timer) if p == 1: self.write_text("# 1-0") else: self.write_text("# 0-1") def click_callback(self, event): """ On click event callback """ # print("clicked at ", event.x+self.offset_x, event.y+self.offset_y) # x = string.ascii_lowercase[math.ceil((event.x + self.offset_x) / self.width) - 1] # y = (math.ceil((event.y + self.offset_y) / self.width) - 9) * -1 self.clear_moves_on_canvas() x = math.ceil((event.x + self.offset_x) / self.width) - 1 y = math.ceil((event.y + self.offset_y) / self.width) - 1 if 0 <= x < 8 and 0 <= y < 8: board_value = self.game.board[x][y] if self.moving: # check if second click isn't on another piece if board_value != "" and board_value[ 0] == self.game.current_player_color: self.calculate_moves_for_moving_piece(x, y) else: self.move_piece(x, y) # method moves moving_piece self.moving = False else: self.calculate_moves_for_moving_piece( x, y) # method sets moving_piece def mouse_move_callback(self, event): """ On mouse move event callback """ # TODO drag and drop figuriek print("moving at ", event.x + self.offset_x, event.y + self.offset_y) def move_piece(self, x, y): if (x, y) in self.moves: # print("clicked on move", x, y) # print(" board: ", self.game.board[x][y]) captured = False if self.game.is_game_checked: self.remove_check() self.move_image_on_canvas(x, y, self.moving_piece.starting_position) if self.game.board[x][y] != "": if self.game.board[x][y].startswith("w"): self.remove_image_from_canvas(self.game.white_pieces[( self.game.board[x][y])[1:]].starting_position) elif self.game.board[x][y].startswith("b"): self.remove_image_from_canvas(self.game.black_pieces[( self.game.board[x][y])[1:]].starting_position) captured = True self.game.board[self.moving_piece.x_pos][ self.moving_piece.y_pos] = "" self.game.board[x][y] = self.moving_piece_key # Needed for move text _previous_x_position = self.moving_piece.x_pos _previous_y_position = self.moving_piece.y_pos self.moving_piece.x_pos = x self.moving_piece.y_pos = y # TODO toto sa da pouzit pre vyhadzovani s en passant if not self.moving_piece.moved: self.moving_piece.moved = True # pprint(self.game.board) made_move = string.ascii_lowercase[x] + str(((y - 8) * -1) % 9) if self.moving_piece.color == "w": self.write_text(str(self.game.current_turn) + ". ") print(self.moving_piece) print(self.moving_piece.name) # POPIS notacie : # TODO En passant vyhodenia - exd6e.p. - pesiak z e isiel na d6 a vyhodil toho na e5 cez en passant # TODO Ak mozu robit pohyby rovnake figurky na rovnake pole treba rozlisit, priorita # TODO 1. ak su rozdielne zaciatocne polia - Bdb8 je strelec ktory bol na zaciatku na d poli ak ten druhy strelec je na inom poli # TODO 2. zapise sa riadok ak su na rovnakom stlpci - R1a3 # TODO 3. zapise sa riadok aj stlpec ak nestaci jeden - Qh4e1 - vyhodenie je Qh4xe1 # TODO Zmena pesiaka na kralovnu napr. - e8Q # TODO Navrh remizy je oznaceny = # TODO Rosady (castling) # TODO Na strane krala - 0-0 # TODO Na strane kralovnej - 0-0-0 # TODO podmienky kedy sa da spravit rosada # TODO Sach (check) - prida na koniec + # TODO Sachmat (checkmate) - prida sa na koniec # # TODO Po skonceni sa 1-0 znamena ze biely vyhral, 0-1 ze cierny vyhral # TODO 1|2-1|2 indikuje remizu # TODO sach - kral sa musi pohnut tak aby uz nemal check # TODO sach - ina figurka sa moze pohnut tak aby zakryla krala if not captured: self.write_text(self.moving_piece.name + made_move + " ") elif self.moving_piece.name == "": self.write_text(string.ascii_lowercase[_previous_x_position] + "x" + made_move + " ") else: self.write_text(self.moving_piece.name + "x" + made_move + " ") if self.game.current_player_color == 'w': self.start_opponents_timer(self.timers[0], 2) else: self.start_opponents_timer(self.timers[1], 1) self.game.next_move() is_check = self.moves_manager.check_for_check( self.moving_piece, self.game.board) if is_check: self.raise_check() self.moving_piece.position = made_move def calculate_moves_for_moving_piece(self, x, y): """ Calculating moves for pieces. Has to set self.moves :param x: x coordinate on board :param y: y coordinate on board """ # print("clicked at ", x, y) # print(self.game.board[x][y]) board_value = self.game.board[x][y] player_color = self.game.current_player_color if board_value != "" and board_value[ 0] == self.game.current_player_color: # TODO tu sa musia vediet pohnut okrem krala aj figurky ktore mozu zabranit sachu if self.game.is_game_checked and board_value != self.game.current_player_color + "K": return self.moving = True self.moving_piece_key = board_value if self.game.current_player_color == "w": self.moving_piece = self.game.white_pieces[board_value[1:]] elif self.game.current_player_color == "b": self.moving_piece = self.game.black_pieces[board_value[1:]] piece = self.moving_piece if piece.color == player_color: self.moves = self.moves_manager.get_moves( piece, self.game.board) self.show_moves_on_canvas(self.moves)