def parse_move(self, move_list, line): m = re.match(self.move_regex, line) if m is not None: pos = parse_position(self.board_size, m.group(1)) visits = int(m.group(2)) winrate = self.flip_winrate(str_to_percent(m.group(3))) mc_winrate = self.flip_winrate(str_to_percent(m.group(4))) nn_winrate = self.flip_winrate(str_to_percent(m.group(5))) nn_count = int(m.group(6)) policy_prob = str_to_percent(m.group(7)) pv = [ parse_position(self.board_size, p) for p in m.group(8).split() ] info = { 'pos': pos, 'visits': visits, 'winrate': winrate, 'mc_winrate': mc_winrate, 'nn_winrate': nn_winrate, 'nn_count': nn_count, 'policy_prob': policy_prob, 'pv': pv, 'color': self.whose_turn() } move_list.append(info) m = re.match(self.move_regex_no_vn, line) if m is not None: pos = parse_position(self.board_size, m.group(1)) visits = int(m.group(2)) mc_winrate = self.flip_winrate(str_to_percent(m.group(3))) r_winrate = self.flip_winrate(str_to_percent(m.group(4))) r_count = int(m.group(5)) policy_prob = str_to_percent(m.group(6)) pv = m.group(7) pv = [parse_position(self.board_size, p) for p in pv.split()] info = { 'pos': pos, 'visits': visits, 'winrate': mc_winrate, 'mc_winrate': mc_winrate, 'r_winrate': r_winrate, 'r_count': r_count, 'policy_prob': policy_prob, 'pv': pv, 'color': self.whose_turn() } move_list.append(info) return move_list
def find_path(initial_state: str, target_position: str, iterations=60, debug=False): """ Вычисляет путь из начального состояния в конечное. :param initial_state: трёх-символьное сочетание -- буквенная координата, числовай координата, ориентация. Примеры: 'a3f', 'f2r', 'e4b', 'g1l' :param target_position: двух-символьное сочетание -- буквенная координата, числовай координата. Примеры: 'a3', 'f2', 'e4', 'g1' :param iterations: количество итераций достаточных для вычисления q-таблицы :param debug: если True то распечатается путь на карте и подробный план (с промежуточными состояниями) :return: """ target = parse_position(target_position) vi = ValueIterator(target) # вычислим Q-таблицу for _ in range(iterations): vi.update() # вычислим путь к цели из задонного состояния path = vi.path(parse_state(initial_state)) pretty_path = pformat_path(path, include_state=False) if debug: visualize_plan(path, target) return pretty_path
def parse_best(self, stats, line): m = re.match(self.best_regex, line) if m is not None: stats['best'] = parse_position(self.board_size, m.group(3).split()[0]) stats['winrate'] = self.flip_winrate(str_to_percent(m.group(2))) return stats
def telemetry(sid, data): global recorded_points if data: # steering_angle = float(data["steering_angle"]) # throttle = float(data["throttle"]) x, y, z = parse_position(data["Position"]) recorded_points.append([x, y, z]) if lap_definition is not None: completion = find_completion([x, y, z], lap_definition) sys.stderr.write("\rTrack position: {0:3.2f}%".format(completion * 100)) speed = float(data["speed"]) image = Image.open(BytesIO(base64.b64decode(data["image"]))) try: image = np.asarray(image) image = preprocess_image(image) image = np.array([image]) image = 2.0 * image / 255 - 1 steering_angle = float(model.predict(image, batch_size=1)) global speed_limit if speed > speed_limit: speed_limit = MIN_SPEED # slow down else: speed_limit = MAX_SPEED throttle = 1.0 - steering_angle**2 - (speed / speed_limit)**2 # print('{} {} {}'.format(steering_angle, throttle, speed)) send_control(steering_angle, throttle) except Exception as e: print(e) if args.image_folder != '': timestamp = datetime.utcnow().strftime('%Y_%m_%d_%H_%M_%S_%f')[:-3] image_filename = os.path.join(args.image_folder, timestamp) lycon.save(path='{}.jpg'.format(image_filename), image=image) else: sio.emit('manual', data={}, skip_sid=True)
def telemetry(sid, data): global recorded_points global no_manual_input if data: x, y, z = parse_position(data["Position"]) if no_manual_input: recorded_points.append([x, y, z]) speed = float(data["speed"]) image = Image.open(BytesIO(base64.b64decode(data["image"]))) try: image = preprocess_image(image) image = np.array([np.asarray(image)]) image = 2.0 * image / 255 - 1.0 steering_angle = float(model.predict(image, batch_size=1)) global speed_limit if speed > speed_limit: speed_limit = MIN_SPEED # slow down else: speed_limit = MAX_SPEED throttle = 1.0 - steering_angle**2 - (speed / speed_limit)**2 # print('{} {} {}'.format(steering_angle, throttle, speed)) send_control(steering_angle, throttle) except Exception as e: print(e) if args.image_folder != '': timestamp = datetime.utcnow().strftime('%Y_%m_%d_%H_%M_%S_%f')[:-3] image_filename = os.path.join(args.image_folder, timestamp) lycon.save(path='{}.jpg'.format(image_filename), image=image) else: no_manual_input = False sio.emit('manual', data={}, skip_sid=True)
game.bot.go_to_position() # c_node = game.cursor.node # nnode = Node() # game.cursor.append_node(nnode) for i in range(1): stdout, stderr = game.bot.genmove() # Drain and parse Leela stdout & stderr stats, move_list = game.bot.parse_analysis(stdout, stderr) if stats.get('winrate') and move_list: best_move = convert_position(19, move_list[0]['pos']) print("result={}".format(best_move)) color = game.bot.whose_turn() best_move = parse_position(19, best_move) command = f"play {color} {best_move}" print("index is {},play is {}".format(i, command)) # game.bot.send_command(command) # this_move = game.add_moves_to_bot() game.bot.add_move_to_history(color, best_move) clr = 'W' if color == 'white' else 'B' nnode = Node() nnode.add_property(Property(clr, [best_move])) game.cursor.append_node(nnode) game.cursor.next(len(game.cursor.children) - 1) game.bot.go_to_position() game.save_to_file() game.bot.stop()
def test_parse_position_valid(): assert parse_position(19, 'A19') == 'aa' assert parse_position(19, 'A1') == 'as' assert parse_position(19, 'T19') == 'sa' assert parse_position(19, 'T1') == 'ss' assert parse_position(19, 'K10') == 'jj' assert parse_position(19, 'pass') == '' assert parse_position(13, 'A13') == 'aa' assert parse_position(13, 'A1') == 'am' assert parse_position(13, 'N13') == 'ma' assert parse_position(13, 'N1') == 'mm' assert parse_position(13, 'G7') == 'gg' assert parse_position(13, 'pass') == '' assert parse_position(9, 'A9') == 'aa' assert parse_position(9, 'A1') == 'ai' assert parse_position(9, 'J9') == 'ia' assert parse_position(9, 'J1') == 'ii' assert parse_position(9, 'E5') == 'ee' assert parse_position(9, 'pass') == ''
def parse_finished(self, stats, stdout): m = re.search(self.finished_regex, "".join(stdout)) if m is not None: stats['chosen'] = "resign" if m.group(1) == "resign" else parse_position( self.board_size, m.group(1)) return stats
# преобразуем переход между состояниями в переход между позициями, т.е. убираем ориентацию edge = self._to_positions(transition) # ищем ревард по таблице (по словарю) reward = self._reward.get(edge) if not reward: # если ревард НЕ найден то возвращаем значение по умолчанию reward = Config.edge_default_reward # тут вознаграждается переход в целевую позицию, если она заданна (т.е. не None) if self.target_position and edge[1] == self.target_position: reward += Config.target_transition_reward return reward @staticmethod def _to_positions(transition): s1, s2 = transition # переход между состояниями i1, j1, _o1 = s1 i2, j2, _o2 = s2 p1 = (i1, j1) # ориентация _o1 "выкинута" p2 = (i2, j2) # ориентация _o2 "выкинута" edge = (p1, p2) # переход между позициями return edge if __name__ == '__main__': pprint_map(data={parse_position('e4'): '$'})
def _proc_inline_move(self, move): """Process an inline move, e.g. I5-H5. Returns a tuple of: the new board position, T if a black marble was removed, T if a white marble was removed""" ######### # Check 1 - Are we moving a distance of 1? start, end = move.split('-') start_row, start_col = utils.parse_position(start) end_row, end_col = utils.parse_position(end) direction, distance = utils.get_direction(start_row, start_col, end_row, end_col) #print "Direction is", direction if distance != 1: raise ValueError("Invalid move - can only move a distance of 1") marble = self.turn ######### # Check 2 - Is there a matching marble in the starting position? try: if self._get_marble(start_row, start_col) != marble: raise ValueError("Invalid move - start marble is not yours!") ####### # Check 3 - If we're here, the starting position is not on the board. except IndexError: raise ValueError("Invalid move - start position is off the board") ######### # Check 4 - The end position can't have a marble of the opposite color. try: if self._get_marble(end_row, end_col) == utils.get_opposite_marble(marble): # Clearly illegal. Is this a pac, though? if self._get_marble(start_row, start_col, direction, 2, True) == empty: raise ValueError("Pac - 1 v 1") else: raise ValueError("Invalid move - don't have superior strength to push") ####### # Check 5 - If we're here, the end position is not on the board. except IndexError: raise ValueError("Invalid move - end position is off the board") # For documentation, we'll assume our marble is white if self._get_marble(start_row, start_col, direction, 1) == empty: # We're pushing one white into an empty space - Legal move board = self._set_marble(start_row, start_col, empty) r, c = utils.calc_position_at_distance(start_row, start_col, direction, 1) board = self._set_marble(r, c, marble, board) return board, False else: # Two white marbles in a row. We dealt with black in check 4. if self._get_marble(start_row, start_col, direction, 2) == empty: # We're pushing two whites into an empty space - Legal move board = self._set_marble(start_row, start_col, empty) r, c = utils.calc_position_at_distance(start_row, start_col, direction, 2) board = self._set_marble(r, c, marble, board) return board, False elif self._get_marble(start_row, start_col, direction, 2) == utils.get_opposite_marble(marble): # Two whites against one black. What's in the next space? if self._get_marble(start_row, start_col, direction, 3, True) == empty: # Two whites pushing one black into an empty space - Legal move board = self._set_marble(start_row, start_col, empty) r, c = utils.calc_position_at_distance(start_row, start_col, direction, 2) board = self._set_marble(r, c, marble, board) try: r, c = utils.calc_position_at_distance(start_row, start_col, direction, 3) board = self._set_marble(r, c, utils.get_opposite_marble(marble), board) except IndexError: # We just pushed a black off the edge return board, True return board, False elif self._get_marble(start_row, start_col, direction, 3) == utils.get_opposite_marble(marble): # Two whites against two blacks. Can't do this, but is this a pac or just an invalid move? if self._get_marble(start_row, start_col, direction, 4) == empty: # We're pushing two whites against two blacks followed by an empty space raise ValueError("Pac - 2 v 2") else: # We're pushing two whites against two blacks and some other stuff raise ValueError("Invalid move - blocked by other marbles behind it") else: # Two whites, one black, one white raise ValueError("Invalid move - blocked by one of your marbles behind it") else: # Three white marbles in a row. if self._get_marble(start_row, start_col, direction, 3) == empty: # We're pushing three whites into an empty space - Legal move board = self._set_marble(start_row, start_col, empty) r, c = utils.calc_position_at_distance(start_row, start_col, direction, 3) board = self._set_marble(r, c, marble, board) return board, False elif self._get_marble(start_row, start_col, direction, 3) == utils.get_opposite_marble(marble): # Three whites against one black. What's in the next space? if self._get_marble(start_row, start_col, direction, 4, True) == empty: # Three whites pushing one black into an empty space - Legal move board = self._set_marble(start_row, start_col, empty) r, c = utils.calc_position_at_distance(start_row, start_col, direction, 3) board = self._set_marble(r, c, marble, board) try: r, c = utils.calc_position_at_distance(start_row, start_col, direction, 4) board = self._set_marble(r, c, utils.get_opposite_marble(marble), board) except IndexError: # We just pushed a black off the edge return board, True return board, False elif self._get_marble(start_row, start_col, direction, 4) == utils.get_opposite_marble(marble): # Three whites against two blacks. What's in the next space? if self._get_marble(start_row, start_col, direction, 5, True) == empty: # Three whites pushing two blacks into an empty space - Legal move board = self._set_marble(start_row, start_col, empty) r, c = utils.calc_position_at_distance(start_row, start_col, direction, 3) board = self._set_marble(r, c, marble, board) try: r, c = utils.calc_position_at_distance(start_row, start_col, direction, 5) board = self._set_marble(r, c, utils.get_opposite_marble(marble), board) except IndexError: # We just pushed a black off the edge return board, True return board, False elif self._get_marble(start_row, start_col, direction, 5) == utils.get_opposite_marble(marble): # Three whites against three blacks. Can't do this, but is this a pac or just an invalid move? if self._get_marble(start_row, start_col, direction, 6) == empty: # We're pushing three whites against three blacks followed by an empty space raise ValueError("Pac - 3 v 3") else: # We're pushing three whites against three blacks and some other stuff raise ValueError("Invalid move - blocked by other marbles behind it") else: # Three whites, two blacks, white raise ValueError("Invalid move - blocked by your marble behind it") else: # Three whites, one black, white raise ValueError("Invalid move - blocked by your marble behind it") else: # Four whites raise ValueError("Invalid move - can't push 4 marbles")
def _proc_broadside_move(self, move): """Process an broadside move, e.g. I5-I7-H5""" line_start, line_end, end = move.split('-') line_start_row, line_start_col = utils.parse_position(line_start) line_end_row, line_end_col = utils.parse_position(line_end) end_row, end_col = utils.parse_position(end) ######### # Check 1 - Is the line actually a line and <= 3 in length? line_direction, line_distance = utils.get_direction(line_start_row, line_start_col, line_end_row, line_end_col) if line_distance > 2: raise ValueError("Invalid move - can only move 1, 2, or 3 marbles broadside") if line_distance == 2: # Direction: # NE = 1, E = 2, SE = 3 # SW = 4, W = 5, NW = 6 # Col changes in all cases except for SE and NW if line_direction not in (3, 6): line_mid_col = max(line_start_col, line_end_col) - 1 else: line_mid_col = line_start_col # Row changes in all cases except for E and W if line_direction not in (2, 5): line_mid_row = max(line_start_row, line_end_row) - 1 else: line_mid_row = line_start_row if line_distance == 0: # This is the same as an inline push of 1 marble inline_result, inline_was_pushed = self._proc_inline_move(move[3:8]) return inline_result marble = self.turn ######### # Check 2 - Is there a matching marble in the line start position? try: if self._get_marble(line_start_row, line_start_col) != marble: raise ValueError("Invalid move - line start marble is not yours!") ####### # Check 3 - If we're here, the line start position is not on the board. except IndexError: raise ValueError("Invalid move - line start position is off the board") ######### # Check 4 - Is there a matching marble in the line end position? try: if self._get_marble(line_end_row, line_end_col) != marble: raise ValueError("Invalid move - line end marble is not yours!") ####### # Check 5 - If we're here, the line end position is not on the board. except IndexError: raise ValueError("Invalid move - line end position is off the board") ######### # Check 6 - If the line is of length 3, is there a matching marble in the middle position? try: if line_distance == 2 and self._get_marble(line_mid_row, line_mid_col) != marble: raise ValueError("Invalid move - middle marble is not yours!") ####### # Check 7 - If we're here, the middle position is not on the board... defying the laws of physics, somehow except IndexError: raise ValueError("Invalid move - middle marble position is off the board") move_direction, move_distance = utils.get_direction(line_start_row, line_start_col, end_row, end_col) if move_distance != 1: raise ValueError("Invalid move - can only move a distance of 1") ###### # Check 8 - Is the end position of the first marble empty? try: if self._get_marble(end_row, end_col) != empty: raise ValueError("Invalid move - end position of the first marble is not empty") ###### # Check 9 - If we're here, the end position of the first marble is not on the board. except IndexError: raise ValueError("Invalid move - end position of the first marble is off the board") ###### # Check 10 - Is the end position of the last marble empty? try: if self._get_marble(line_end_row, line_end_col, move_direction, 1) != empty: raise ValueError("Invalid move - end position of the last marble is not empty") ###### # Check 11 - If we're here, the end position of the last marble is not on the board. except IndexError: raise ValueError("Invalid move - end position of the last marble is off the board") if line_distance == 2: ###### # Check 14 - Is the end position of the middle marble empty? try: if self._get_marble(line_mid_row, line_mid_col, move_direction, 1) != empty: raise ValueError("Invalid move - end position of the middle marble is not empty") ###### # Check 15 - If we're here, the end position of the middle marble is not on the board - somehow. except IndexError: raise ValueError("Invalid move - end position of the middle marble is off the board") board = self._set_marble(line_start_row, line_start_col, empty) board = self._set_marble(end_row, end_col, marble, board) board = self._set_marble(line_end_row, line_end_col, empty, board) r, c = utils.calc_position_at_distance(line_end_row, line_end_col, move_direction, 1) board = self._set_marble(r, c, marble, board) if line_distance == 2: board = self._set_marble(line_mid_row, line_mid_col, empty, board) r, c = utils.calc_position_at_distance(line_mid_row, line_mid_col, move_direction, 1) board = self._set_marble(r, c, marble, board) return board