def war_detector(self): """ Проверка на осуществление перехода с боем - Проверка на то, чтоб была фигура, которую мы атакуем - Поиск и установление координат фигуры, выставление в self.command_dict - Проверка на то, чтоб цвет фигуры был не наш """ d = self.command_dict board_obj = self.board_obj x_start = d["from"]["x"] y_start = UtilClass.char2xint(d["from"]["y"]) x_finish = d["to"]["x"] y_finish = UtilClass.char2xint(d["to"]["y"]) # Соседние точки относительно точки назначения middle_points = np.array([ e for e in [[x_finish - 1, y_finish - 1], [x_finish - 1, y_finish + 1]] if board_obj.detect_element(*e) ]) # Возможные точки, где стоит фигура validated_points = np.array([ e for e in [[x_start + 1, y_start + 1], [x_start + 1, y_start - 1]] if board_obj.detect_element(*e) ]) attack_points = [] for i in np.arange(middle_points.shape[0]): for j in np.arange(validated_points.shape[0]): if (middle_points[i][0] == validated_points[j][0] and middle_points[i][1] == validated_points[j][1]): attack_points = middle_points[i] break # Если нет точек пересечения if len(attack_points) == 0: self.results_list.append(False) return self.command_dict["enemy"] = {} self.command_dict["enemy"]["x"], self.command_dict["enemy"][ "y"] = attack_points attack_x, attack_y = attack_points # Выбрали точку, где располагается предполагаемый враг attack_field = board_obj.board[attack_x][attack_y] # Если есть чужая фигура на этой точке if (not attack_field.isfree() and attack_field.figure_obj.color != d["user_color"]): self.results_list.append(True) else: if self.info: f = UtilClass.getfail_coords print( "\033[91m[Ошибка]\033[0m Противников между координатами {} и {} нет. Используйте тихий ход для перемещения без боя" .format(f(d["from"]), f(d["to"]))) self.results_list.append(False)
def figure_detector(self): """Определение, стоит ли на исходной клетке фигура и если стоит, то своя ли""" board_obj = self.board_obj d = self.command_dict # Проверка на то, существует ли ячейка, с которой мы хотим переставить фигуру target_x = d["from"]["x"] target_y = UtilClass.char2xint(d["from"]["y"]) if not board_obj.detect_element(target_x, target_y): if self.info: print( "\033[91m[Ошибка]\033[0m Выбранной шашки по координатам {} не существует." .format(UtilClass.getfail_coords(d["from"]))) self.results_list.append(False) return # Если есть фигура и ее цвет тот, за который мы играем selected_field = board_obj.board[target_x][target_y] if (not selected_field.isfree() and selected_field.figure_obj.color == d["user_color"]): self.results_list.append(True) elif selected_field.isfree(): if self.info: print( "\033[91m[Ошибка]\033[0m Выбранная клетка {} пуста".format( UtilClass.getfail_coords(d["from"]))) self.results_list.append(False) else: if self.info: print( "\033[91m[Ошибка]\033[0m Фигура на клетке {} не вашего цвета." .format(UtilClass.getfail_coords(d["from"]))) self.results_list.append(False)
def command_parser(self, cmd): """ Осуществление парсинга и фильтрации команды, которую ввел пользователь Если все хорошо - вызывается проверка на уровне """ movement_type_dict = {":": "war", "-": "peace"} # Разделитель строки на 2 части spliter = "" detect_flag = False for key in movement_type_dict.keys(): if key in cmd: detect_flag = True spliter = key break if not detect_flag: return {} command_dict = { "from": {}, "to": {}, "mode": movement_type_dict[spliter], "user_color": self.user_color, } # Разделяем введенную команду на 2 части part1, part2 = cmd.split(spliter) if UtilClass.checkxy_value(part1) and UtilClass.checkxy_value(part2): command_dict["from"]["x"] = int(part1[1]) - 1 command_dict["from"]["y"] = part1[0] command_dict["to"]["x"] = int(part2[1]) - 1 command_dict["to"]["y"] = part2[0] return command_dict return {}
def fieldtype_detector(self): """ Проверка на все, что связано с ячейкой. - Проверка на существование ячейки - Занятость ячейки - Цвет ячейки """ # Понятное дело, что мы ячейку на существование проверили на предыдущем шаге в diagonal_detector, но МАЛО ЛИ d = self.command_dict board_obj = self.board_obj x = d["to"]["x"] y = UtilClass.char2xint(d["to"]["y"]) if not board_obj.detect_element(x, y): self.results_list.append(False) return selected_field = board_obj.board[x][y] if selected_field.color == "black" and selected_field.isfree(): self.results_list.append(True) elif not selected_field.isfree(): if self.info: print( "\033[91m[Ошибка]\033[0m Вы пытаетесь поставить шашку на занятую клетку {}" .format(UtilClass.getfail_coords(d["to"]))) self.results_list.append(False) else: if self.info: print( "\033[91m[Ошибка]\033[0m Вы пытаетесь поставить шашку на клетку белого цвета {}" .format(UtilClass.getfail_coords(d["to"]))) self.results_list.append(False)
def user_mode(self): """ Осуществление хода пользователем """ d = self.result_dict board = self.board_obj.board mode = d["mode"] f1 = [d["from"]["x"], UtilClass.char2xint(d["from"]["y"])] f2 = [d["to"]["x"], UtilClass.char2xint(d["to"]["y"])] x1, y1 = f1 x2, y2 = f2 field_from = board[x1][y1] field_to = board[x2][y2] # Получаем объект фигуры с ячейки и выставлем для него обновленные координаты figure_obj = field_from.figure_obj figure_obj.coord_x, figure_obj.coord_y = f2 # Присваиваем фигуру обновленной ячейке field_to.field_reserve(figure_obj) # Освобождаем из старой field_from.field_free() # Если мы кого-то бъём, то удаляем фигуру с той ячейки if mode == "war": attack_x, attack_y = d["enemy"]["x"], d["enemy"]["y"] board[attack_x][attack_y].field_free() self.board_obj.board = board
def diagonal_detector(self): """Проверка на осуществление перехода по диагонали""" # Возможные пути, куда может пойти шашка (их всего 4) board_obj = self.board_obj d = self.command_dict target_x = d["from"]["x"] target_y = UtilClass.char2xint(d["from"]["y"]) # Возможные клетки, куда можно пойти и которые есть на доске # Т.к. использование "коротких" перемещений при атаке просто невозможно if d["mode"] == "war": allowedfields_list = [ [target_x - 2, target_y + 2], [target_x - 2, target_y - 2], ] # При тихом ходе возмодны только короткие перемещения else: allowedfields_list = [ [target_x - 1, target_y + 1], [target_x - 1, target_y - 1], ] validated_points = [ e for e in allowedfields_list if board_obj.detect_element(*e) ] if [d["to"]["x"], UtilClass.char2xint(d["to"]["y"])] in validated_points: self.results_list.append(True) else: self.results_list.append(False)
def figuremanual_generator(self): """Ручная расстановка 6 фигур по полю""" format_dict = {"white": "белого", "black": "чёрного"} for color in ("white", "black"): print("\033[93m*Выставляем шашки {} цвета*\033[0m".format( format_dict[color])) for i in range(6): boolean_flag = True while boolean_flag: print(self) coord_input = input( "Введите координаты расположения шашки №{} -> ".format( i + 1)) if UtilClass.checkxy_value(coord_input): coord_x = int(coord_input[1]) - 1 coord_y = coord_input[0] result = self.boardfigure_setter( color, coord_x, coord_y) if result: print("Успешная постановка шашки на координаты {}". format(coord_input)) boolean_flag = False else: print( "\033[91m[Ошибка]\033[0m Некорретный ввод данных, пример координат: h2" )
def boardfigure_setter(self, color, search_x, search_y): """ Поиск координат фигуры и ее постановка Возврат True - фигура поставлена Возврат False - фигура с координатами не найдена """ x = search_x y = UtilClass.char2xint(search_y) board = self.board if board[x][y].isfree() and board[x][y].color == "black": board[x][y].field_reserve(FigureClass(color, x, y)) self.board = board return True if not board[x][y].isfree(): print( "\033[91m[Ошибка]\033[0m Клетка с координатами {}{} уже занята" .format(search_y, search_x + 1)) if board[x][y].color == "white": print( "\033[91m[Ошибка]\033[0m Цвет клетки с координатами {}{} белый" .format(search_y, search_x + 1)) return False
def board_generator(self): """Создание чистого игрового поля без фигур""" board = np.array([]) for x in np.arange(8): for y in np.arange(8): field_obj = FieldClass(UtilClass.xint2char(x), y) board = np.append(field_obj, board) self.board = np.array(board.reshape(8, 8))
def color_generator(self): """Генератор цвета ячейки на основе ее координат""" x = UtilClass.char2xint(self.coord_x) y = self.coord_y if (x % 2 == 0 and y % 2 == 0) or (y % 2 == 1 and x % 2 == 1): color = "black" else: color = "white" self.color = color
def diagonal_detector(self): """Проверка на осуществление перехода по диагонали""" # Возможные пути, куда может пойти шашка (их всего 4) board_obj = self.board_obj d = self.command_dict target_x = d["from"]["x"] target_y = UtilClass.char2xint(d["from"]["y"]) # Возможные клетки, куда можно пойти и которые есть на доске # Т.к. использование "коротких" перемещений при атаке просто невозможно if d["mode"] == "war": allowedfields_list = [ [target_x + 2, target_y + 2], [target_x + 2, target_y - 2], ] # При тихом ходе возможны только короткие перемещения else: allowedfields_list = [ [target_x + 1, target_y + 1], [target_x + 1, target_y - 1], ] validated_points = [ e for e in allowedfields_list if board_obj.detect_element(*e) ] if [d["to"]["x"], UtilClass.char2xint(d["to"]["y"])] in validated_points: self.results_list.append(True) else: if self.info: print( "\033[91m[Ошибка]\033[0m Шашки могут ходить только по диагонали, ход с боем - длинное перемещение, тихий ход - короткое перемещение." ) # TODO Предложение о возможных ходах для фишки при некорректном ходе # print("Возможные команды для корректного кода с клетки {}:") self.results_list.append(False)
def computer_mode(self): """ Осуществление хода компьютера - Выбираются координаты ячейки из сформированного словаря - Берется объект фигуры, меняются координаты фигуры на обновлённые - Осуществляется привязка к новой ячейке фигуры - Из старой ячейки освобождается объект фигуры - Если осуществилась атака, то удаляем фигуру врага из ячейки enemy """ d = self.result_dict board = self.board_obj.board mode = d["mode"] f1 = [d["from"]["x"], UtilClass.char2xint(d["from"]["y"])] f2 = [d["to"]["x"], UtilClass.char2xint(d["to"]["y"])] x1, y1 = f1 x2, y2 = f2 field_from = board[x1][y1] field_to = board[x2][y2] figure_obj = field_from.figure_obj figure_obj.coord_x, figure_obj.coord_y = f2 # Присваиваем фигуру обновленной ячейке field_to.field_reserve(figure_obj) # Освобождаем из старой field_from.field_free() # Если мы кого-то бъём, то удаляем фигуру с той ячейки if mode == "war": attack_x, attack_y = d["enemy"]["x"], d["enemy"]["y"] board[attack_x][attack_y].field_free() self.board_obj.board = board
def detect_element(self, search_x, search_y): """ Определяем, есть ли элемент с такими координатами на доске Это необходимо для того, чтоб не выехать за массив """ if search_x not in range(0, 8) or search_y not in range(0, 8): return False search_x = UtilClass.xint2char(search_x) board = self.board for x in np.arange(board.shape[0]): for y in np.arange(board.shape[1]): if board[x][y].coord_x == search_x and board[x][ y].coord_y == search_y: return True return False
def gameprocess(self): """Управляющая логика работы игры""" userstepcolor_dict = {"black": 1, "white": 0} usercolor_dict = {"black": "Черный", "white": "Белый"} user_color = self.user_color userstep = userstepcolor_dict[user_color] # Номер итерации i = 0 won_color = "" print("\033[93m*Игра началась*\033[0m") journal = JournalWriterClass() while True: # Проверяем на окончание игры obj = GameOverClass(self.board_obj, user_color) if obj.result: won_color = obj.won_color print("Выиграл цвет: {}".format(usercolor_dict[obj.won_color])) break # Ходит пользователь if i % 2 == userstep: print("Ход №{}. Ходит пользователь..".format(i + 1)) cmd = input("Введите команду -> ") result_dict = self.command_parser(cmd) # Если нормально прошло фильтрацию if result_dict != {}: self.result_dict = result_dict # Проверка на все критерии obj = UserAnalyserClass(result_dict, self.board_obj, True) # Если все хорошо, то осуществлем ход if obj.boolean_result: self.result_dict = obj.command_dict # Пользователь ходит self.user_mode() journal.add_result(obj.command_dict) i += 1 else: print("\033[91m[Ошибка]\033[0m Некорректный ход") else: print( "\033[91m[Ошибка]\033[0m Некорректный ввод данных. Пример: 'c3:e5' - перемещение с боем, 'c3-b4' - тихое перемещение" ) # Компьютер ходит else: print("Ход №{}. Ходит компьютер..".format(i + 1)) time.sleep(3) computergame_obj = ComputerGameClass(self.board_obj, user_color) d = computergame_obj.result_dict print("{} -> {}".format( UtilClass.getfail_coords(d["from"]), UtilClass.getfail_coords(d["to"]), )) # Если тупиковый ход со стороны компьютера if not computergame_obj.result: won_color = user_color print( "\033[91m[ИНФО]\033[0m У компьютера тупиковая ситуация" ) print("Выиграл цвет: {}".format( usercolor_dict[user_color])) break journal.add_result(d) i += 1 # Вывод доски print(self.board_obj) # Добавление окончания journal.winlose_add(won_color) print(journal)
def deadlock_detector(self): """ Определение тупиковой ситуации для пользователя Использует логику, аналогичную рандомному ходу компьютера """ board_obj = self.board_obj board = board_obj.board uc = self.user_color reverse_uc = "black" if uc == "white" else "white" all_d = np.array([]) myfields_arr = np.array([]) # Ищем все фигуры пользователя for i in np.arange(board.shape[0]): for j in np.arange(board.shape[1]): if not board[i][j].isfree( ) and board[i][j].figure_obj.color == uc: myfields_arr = np.append(myfields_arr, board[i][j]) # Для каждой шашки формируем возможные новые координаты: for field in myfields_arr: x, y = field.figure_obj.coord_x, field.figure_obj.coord_y y_char = UtilClass.xint2char(y) # Возможные короткие шаги # [x+1,y-1] if board_obj.detect_element(y - 1, x + 1): new_y, new_x = UtilClass.xint2char(y - 1), x + 1 all_d = np.append( all_d, { "from": { "x": x, "y": y_char }, "to": { "x": new_x, "y": new_y }, "mode": "peace", "user_color": uc, }, ) # [x+1,y+1] if board_obj.detect_element(y + 1, x + 1): new_y, new_x = UtilClass.xint2char(y + 1), x + 1 all_d = np.append( all_d, { "from": { "x": x, "y": y_char }, "to": { "x": new_x, "y": new_y }, "mode": "peace", "user_color": uc, }, ) # Длинные шаги # [x+2,y+2] if board_obj.detect_element(y + 2, x + 2): new_y, new_x = UtilClass.xint2char(y + 2), x + 2 all_d = np.append( all_d, { "from": { "x": x, "y": y_char }, "to": { "x": new_x, "y": new_y }, "mode": "war", "user_color": uc, }, ) # [x+2,y-2] if board_obj.detect_element(y - 2, x + 2): new_y, new_x = UtilClass.xint2char(y - 2), x + 2 all_d = np.append( all_d, { "from": { "x": x, "y": y_char }, "to": { "x": new_x, "y": new_y }, "mode": "war", "user_color": uc, }, ) # Перебираем все возможные ходы пользователя for d in all_d: obj = UserAnalyserClass(d, self.board_obj) if obj.boolean_result: break else: self.result = True self.won_color = reverse_uc print("\033[91m[ИНФО]\033[0m У пользователя тупиковая ситуация")
def processing(self): uc = self.user_color # Цвет, за который ходит компьютер reverse_uc = "black" if uc == "white" else "white" myfields_arr = np.array([]) all_d = [] board = self.board_obj.board for i in np.arange(board.shape[0]): for j in np.arange(board.shape[1]): if (not board[i][j].isfree() and board[i][j].figure_obj.color == reverse_uc): myfields_arr = np.append(myfields_arr, board[i][j]) # Для каждой шашки формируем возможные новые координаты, перемешиваем это и закидываем в ComputerAnalyserClass for field in myfields_arr: x, y = field.figure_obj.coord_x, field.figure_obj.coord_y y_char = UtilClass.xint2char(y) # Возможные короткие шаги # [x-1,y-1] if self.board_obj.detect_element(y - 1, x - 1): new_y, new_x = UtilClass.xint2char(y - 1), x - 1 all_d.append({ "from": { "x": x, "y": y_char }, "to": { "x": new_x, "y": new_y }, "mode": "peace", "user_color": reverse_uc, }) # [x-1,y+1] if self.board_obj.detect_element(y + 1, x - 1): new_y, new_x = UtilClass.xint2char(y + 1), x - 1 all_d.append({ "from": { "x": x, "y": y_char }, "to": { "x": new_x, "y": new_y }, "mode": "peace", "user_color": reverse_uc, }) # Длинные шаги # [x-2,y+2] if self.board_obj.detect_element(y + 2, x - 2): new_y, new_x = UtilClass.xint2char(y + 2), x - 2 all_d.append({ "from": { "x": x, "y": y_char }, "to": { "x": new_x, "y": new_y }, "mode": "war", "user_color": reverse_uc, }) # [x-2,y-2] if self.board_obj.detect_element(y - 2, x - 2): new_y, new_x = UtilClass.xint2char(y - 2), x - 2 all_d.append({ "from": { "x": x, "y": y_char }, "to": { "x": new_x, "y": new_y }, "mode": "war", "user_color": reverse_uc, }) random.shuffle(all_d) all_d.sort(key=lambda x: x["mode"], reverse=True) for d in all_d: obj = ComputerAnalyserClass(d, self.board_obj) if obj.boolean_result: self.result_dict = obj.command_dict self.computer_mode() break else: self.result = False