def load_design(self, path, filename): hex_canvas = self.ids.hex_grid # with open(os.path.join(path, filename[0])) as in_file: with open(filename[0]) as in_file: in_des = eval(in_file.read()) for helix_pair in in_des: node_from_id, node_to_id = helix_pair node_from = hex_canvas.grid[node_from_id[0]][node_from_id[1]] node_to = hex_canvas.grid[node_to_id[0]][node_to_id[1]] with node_from.canvas: Color(1, 1, 1, 1) Ellipse(pos=(node_from.center[0] - 6, node_from.center[1] - 6), size=(12, 12)) with node_to.canvas: Color(1, 1, 1, 1) Ellipse(pos=(node_to.center[0] - 6, node_to.center[1] - 6), size=(12, 12)) vvh = VVHelix(from_node=node_from, to_node=node_to, vvhelix_id=hex_canvas.vvhelix_id) hex_canvas.scaffold_path.append(vvh) hex_canvas.vvhelix_id += 2 hex_canvas.add_widget(vvh) from pprint import pprint pprint(hex_canvas.scaffold_path) self.dismiss_popup()
def __init__(self, **kwargs): super(GroupScoreBubble, self).__init__(**kwargs) self.x = groupPos[0] self.y = groupPos[1] with self.canvas.before: Ellipse(pos=(self.x, self.y), size=(self.width * .35, self.width * .35)) with self.canvas: Ellipse(pos=(self.x, self.y), size=(self.width * .35, self.width * .35), texture=GroupBubs[1].texture)
def adjust_size(self, *args): (par_x, par_y) = self.parent.size if par_x == 0 or par_y == 0: with self.canvas: self.canvas.clear() return par_scale = par_x / par_y (img_x, img_y) = self.image.texture.size img_scale = img_x / img_y if par_scale > img_scale: (img_x_new, img_y_new) = (img_x, img_x / par_scale) else: (img_x_new, img_y_new) = (img_y * par_scale, img_y) crop_pos_x = (img_x - img_x_new) / 2 crop_pos_y = (img_y - img_y_new) / 2 subtexture = self.image.texture.get_region( crop_pos_x, crop_pos_y, img_x_new, img_y_new ) with self.canvas: self.canvas.clear() Color(1, 1, 1) Ellipse(texture=subtexture, pos=self.pos, size=(par_x, par_y), radius=self.radius)
def on_press(self): with self.canvas: Ellipse(source='assets/buttons/btn_menu_active.png', pos=self.pos, size=self.size) for child in self.parent.children: child.disabled = True self.parent.add_widget(self.window) self.window.background_normal = 'assets/menu/menu_00.png' self.window.background_down = 'assets/menu/menu_00.png' self.window.size_hint = (0.5, 0.5) self.window.pos_hint = {'x': 0.25, 'y': 0.25} self.window.border = (0, 0, 0, 0) self.parent.add_widget(self.show_restart_button) self.show_restart_button.opacity = 0 self.show_restart_button.size_hint = (0.35, 0.07) self.show_restart_button.pos_hint = {'x': 0.35, 'y': 0.48} self.show_restart_button.bind(on_press=self.show_restart) self.parent.add_widget(self.show_end_game_button) self.show_end_game_button.opacity = 0 self.show_end_game_button.size_hint = (0.35, 0.07) self.show_end_game_button.pos_hint = {'x': 0.35, 'y': 0.39} self.show_end_game_button.bind(on_press=self.show_end_game) self.parent.add_widget(self.continue_button) self.continue_button.opacity = 0 self.continue_button.size_hint = (0.35, 0.07) self.continue_button.pos_hint = {'x': 0.35, 'y': 0.3} self.continue_button.bind(on_press=self.continue_game)
def on_enter(self): # Map with Zoom and Coordinates mapview = MapView(zoom=18, lat=cur_lat, lon=cur_lon) # TODO: use ros variables for coordinates # Back to Menu Button def changeScreen(self): sm.transition = SlideTransition(direction='right') sm.current = "MNS" backBtn = Button(text="[b]BACK[/b]", font_size="20sp", pos=(0, 0), size_hint=(.2, .1), background_color=(1, 1, 1, 0.45), markup=True) backBtn.bind(on_press=changeScreen) self.add_widget(mapview) with self.canvas: carSize = 15 Color(1, 0, 0, 1) # set the colour to red self.elliple = Ellipse(pos=self.center, size=(carSize, carSize)) # Add to Map layout self.add_widget(backBtn)
def __init__(self, grid_path: Path, grid_properties: GridProperties): self._grid_properties = grid_properties self._grid_path = grid_path container_instruction_group = InstructionGroup() container_instruction_group.add(Color(1, 0, 0)) points = [grid_properties.to_pixels(*point) for point in grid_path] container_instruction_group.add(Line(points=points)) d = 15 x, y = self._agent_position container_instruction_group.add( Ellipse(pos=(x - d / 2, y - d / 2), size=(d, d)) ) self.instruction_groups = [container_instruction_group] rectangle_diameter = 10 for resource in grid_path.resources: resource_instruction_group = InstructionGroup() resource_instruction_group.add(COLOR_FROM_RESOURCE[resource]) resource_instruction_group.add( Rectangle( pos=(x - rectangle_diameter / 2, y - rectangle_diameter / 2), size=(rectangle_diameter, rectangle_diameter), ) ) self.instruction_groups.append(resource_instruction_group)
def __init__(self, **kwargs): super().__init__(**kwargs) self.ball_size = dp(50) self.vx = dp(10) self.vy = dp(10) with self.canvas: self.ball = Ellipse(pos=(100, 100), size=(self.ball_size, self.ball_size)) Clock.schedule_interval(self.update, 1/60)
def __init__(self, **kwargs): super().__init__(**kwargs) self.ball_size = dp(50) with self.canvas: Color(0, 1, 1, 0.5) self.circle = Ellipse(pos=(self.center_x, self.center_y), size=(self.ball_size, self.ball_size)) self.start()
def __init__(self, **kwargs): super(ScatterTextWidget, self).__init__(**kwargs) with self.canvas.before: Color(0, 1, 0, 1) Rectangle(pos=(0, 100), size=(300, 100)) Ellipse(pos=(0, 400), size=(300, 100)) Line(points=[0, 0, 500, 600, 400, 300], close=True, width=3)
def __init__(self, **kwargs): super(CanvasWidget, self).__init__(**kwargs) # thefuck does this do? with self.canvas: Color(0, 1, 0, 1) Rectangle(pos=(0, 100), size=(300, 100)) Ellipse(pos=(0, 400), size=(300, 100)) Line(points=[0, 0, 500, 600, 400, 300], close=True, width=3)
def __init__(self, **kwargs): super(Test_Loader, self).__init__(**kwargs) self.starting_angle = 0 self.ending_angle = 0 with self.canvas: Color(0, 1, 1, 1) Ellipse(angle_start=0, angle_end=0) Clock.schedule_once(partial(Test_Loader.animator, self))
def draw_feu(self): if self.recepteur.is_connected: with self.feu_reception.canvas: Color(0, 1, 0) else: with self.feu_reception.canvas: Color(1, 0, 0) with self.feu_reception.canvas: Ellipse(pos=(50, 5), size=(20, 20))
def Render(self, matrix, colorTransform, renderingIndex, renderingCount, visible): if not visible or colorTransform.multi.alpha == 0: return # print(matrix) # print("") self.m_color.rgba = (colorTransform.multi.red, colorTransform.multi.green, colorTransform.multi.blue, colorTransform.multi.alpha) self.m_matrix.set(flat=[ matrix.scaleX, -matrix.skew0, 0, 0, # matrix.skew0, -matrix.skew0 -matrix.skew1, matrix.scaleY, 0, 0, # matrix.scaleX, matrix.scaleY 0, 0, 1, 0, matrix.translateX, matrix.translateY, 0, 1 ]) # matrix.translateX, matrix.translateY self.m_inst.matrix = self.m_matrix self.canvas.add(PushMatrix()) self.canvas.add(Color(1, 0, 0, 1)) self.canvas.add(Translate(575, 300)) self.canvas.add(Ellipse(size=(5, 5))) self.canvas.add(self.m_origin_transform) self.canvas.add(Ellipse(size=(5, 5))) self.canvas.add(Scale(1, -1, 1, origin=(0, 0))) self.canvas.add(self.m_inst) self.canvas.add(self.m_color) self.canvas.add(self.m_mesh) self.canvas.add(PopMatrix()) self.canvas.ask_update()
def continue_game_from_end_game(self, button): self.parent.remove_widget(self.continue_button) self.parent.remove_widget(self.new_game_window) self.parent.remove_widget(self.end_game_button) for child in self.parent.children: child.disabled = False with self.canvas: Ellipse(source='assets/buttons/btn_menu_inactive.png', pos=self.pos, size=self.size) print "continue game"
def fill_canvas(self): super(BarDiagramElementsContainer, self).fill_canvas() from kivy.graphics.vertex_instructions import Rectangle, Ellipse self.bars = [] with self.canvas.before: for value in self.values: self.bars.append( (Ellipse(angle_start=-90, angle_end=90, segments=10, size=(1, 1)), Rectangle(size=(1, 1))))
def refresh_layout(self, dt, generate=True): if self.death_box: return u = self.unit if generate is True: # update the board (DEFAULT) if self.generation is None: self.generation = 0 self.generation += 1 App.get_running_app().gen_lbl.text = str(self.generation) self._scope.generation() self.gol_board = self._scope.surroundings # update the display with self.canvas: self.canvas.clear() # Rotate(axis=(0,0,1), angle=135, origin=self.center) life_signs = 0 w = self.board_width for y in range(w): for x in range(w): state = self.gol_board[y][x] life_signs += state if state == LIFE: if self.fd == False: r, g, b, a = self.life_rgba Color(r, g, b, a) else: Color(random.random(), random.random(), random.random(), 1) Ellipse(pos=(y * u, x * u), size=(u, u)) else: r, g, b, a = self.death_rgba Color(r, g, b, a) Ellipse(pos=(y * u, x * u), size=(u, u)) if life_signs == 0: Clock.unschedule(self.refresh_layout)
def draw(self, wid, *largs): nPOS = MIN_HEIGHT lPOS = MIN_HEIGHT mPOS = MIN_HEIGHT nSTEP = MAX_HEIGHT / (nEntered - 1) lSTEP = MAX_HEIGHT / (lEntered - 1) mSTEP = MAX_HEIGHT / (mEntered - 1) with wid.canvas: for x in range(nEntered): Color(random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1), mode='rgb') Ellipse(pos=(100 - CIRCLE_RADIUS, nPOS - CIRCLE_RADIUS), size=(CIRCLE_RADIUS * 2, CIRCLE_RADIUS * 2)) dataList.nSet.append(nPOS) nPOS += nSTEP for x in range(lEntered): Color(random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1), mode='rgb') Ellipse(pos=(400 - CIRCLE_RADIUS, lPOS - CIRCLE_RADIUS), size=(CIRCLE_RADIUS * 2, CIRCLE_RADIUS * 2)) dataList.lSet.append(lPOS) lPOS += lSTEP for x in range(mEntered): Color(random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1), mode='rgb') Ellipse(pos=(700 - CIRCLE_RADIUS, mPOS - CIRCLE_RADIUS), size=(CIRCLE_RADIUS * 2, CIRCLE_RADIUS * 2)) dataList.mSet.append(mPOS) mPOS += mSTEP draw_lines(wid)
def update(self, dt): self.time += dt if not self.line: self.draw() if self.time >= self.start_time and not self.truck: with self.canvas: Color(1., 0, 1.) self.truck = Ellipse(pos=[x - 5 for x in self.start.pos], size=(10, 10)) self.line.points = self.transform_data(self.lat, self.lon) self.start.pos = self.transform_points(self.start_pos) self.goal.pos = self.transform_points(self.end_pos) self.calculate_speed() if self.truck: self.truck.pos = self.transform_points(self.calculate_truck_pos()) pass
def lay_canvas_instructions(self): with self.canvas.after: StencilPush() RoundedRectangle(size=self.size, pos=self.pos, radius=[self._radius]) StencilUse() self.col_instruction = Color(rgba=self.ripple_color) self.ellipse = Ellipse( size=(self.ripple_rad, self.ripple_rad), pos=( self.ripple_pos[0] - self.ripple_rad / 2.0, self.ripple_pos[1] - self.ripple_rad / 2.0, ), ) StencilUnUse() RoundedRectangle(size=self.size, pos=self.pos, radius=[self._radius]) StencilPop() self.bind(ripple_color=self._set_color, ripple_rad=self._set_ellipse)
def _create_needle(self, *args): if self._needle_widget == self._needle_widget_safe: self._needle_widget_safe.canvas.clear() with self._needle_widget_safe.canvas: Color(*self.needle_color) Line(points=(*self._needle_widget_safe.center, self._needle_widget_safe.center_x, self._needle_widget_safe.center_y + self.circle_radius)) Line(points=(*self._needle_widget_safe.center, self._needle_widget_safe.center_x, self._needle_widget_safe.center_y + self.circle_radius - 20), width=1.5) Ellipse(pos=(self._needle_widget_safe.center_x - 5, self._needle_widget_safe.center_y - 5), size=(10, 10))
def calculate_speed(self): for change in self.speed_history: if self.time < change.end_time: self.speed = change.speed if change.platooning != self.following and self.truck in self.canvas.children: self.following = change.platooning != -1 self.canvas.children.remove(self.truck) with self.canvas: if self.following: Color(0, 0.6, 1.0) else: Color(1., 0, 1.) self.truck = Ellipse(pos=self.truck.pos, size=(10, 10)) # self.following = change.platooning # if self.truck: # self.canvas.clear() break
def set_progress_round(self, interval: Union[int, float]) -> NoReturn: with self.canvas.after: self._instance_progress_inner_circle_color = Color(rgba=(0, 0, 0, 0)) self._instance_progress_inner_circle_ellipse = Ellipse( size=self.get_progress_round_size(), pos=self.get_progress_round_pos(), ) self.bind( pos=self.update_progress_inner_circle_ellipse, size=self.update_progress_inner_circle_ellipse, ) # FIXME: Radius value is not displayed. self._instance_overlay_color = Color(rgba=(0, 0, 0, 0)) self._instance_overlay_rounded_rec = RoundedRectangle( size=self.size, pos=self.pos, radius=self.instance_item.radius if hasattr( self.instance_item, "radius") else [ 0, ], ) self.bind( pos=self.update_overlay_rounded_rec, size=self.update_overlay_rounded_rec, ) self._instance_progress_inner_outer_color = Color(rgba=(0, 0, 0, 0)) self._instance_progress_inner_outer_line = SmoothLine( width=dp(4), circle=[ self.center_x, self.center_y, self.progress_round_size * 0.58, 0, 0, ], )
def on_touch_down(self, touch): if self.collide_point(*touch.pos): ln = self.parent.last_node try: if ln: # fill up the connection graph With helices neighbors = ln.get_neighbors()[0] # for -> if self in neighbors: vvh = VVHelix(from_node=ln, to_node=self, vvhelix_id=self.parent.vvhelix_id) self.parent.vvhelix_id += 2 self.parent.add_widget(vvh) # to generate the design - we are interested in the order of the vvhelixes added self.parent.scaffold_path.append(vvh) else: txt = " ".join([ str(self.grid_id), "not a neighbor of", str(ln.grid_id) ]) popup = Popup(title="Not a neighbor.", content=Label(text=txt), size_hint=(None, None), size=(400, 200)) popup.open() return True self.parent.last_node = self with self.canvas.before: Color(1, 1, 1, 1) Ellipse(pos=(self.center[0] - 6, self.center[1] - 6), size=(12, 12)) return True except: print(sys.exc_info()[0]) pass
def _hover_add_background(self): self.background = InstructionGroup() self.background.add(Color(1, 1, 1, 0.1)) self.background.add(Ellipse(pos=self.pos, size=self.size)) self.canvas.before.add(self.background)
def draw_board_contents(self, *_args): if not (self.katrain and self.katrain.game): return stone_color = STONE_COLORS outline_color = OUTLINE_COLORS katrain = self.katrain board_size_x, board_size_y = katrain.game.board_size lock_ai = self.trainer_config[ "lock_ai"] and self.katrain.play_analyze_mode == MODE_PLAY show_n_eval = self.trainer_config["eval_off_show_last"] self.canvas.clear() with self.canvas: # stones current_node = katrain.game.current_node game_ended = katrain.game.ended full_eval_on = katrain.analysis_controls.eval.active has_stone = {} drawn_stone = {} for m in katrain.game.stones: has_stone[m.coords] = m.player show_dots_for = { p: self.trainer_config["eval_show_ai"] or katrain.players_info[p].human for p in Move.PLAYERS } show_dots_for_class = self.trainer_config["show_dots"] nodes = katrain.game.current_node.nodes_from_root realized_points_lost = None katrain.config("trainer/show_dots") for i, node in enumerate(nodes[::-1]): # reverse order! points_lost = node.points_lost evalsize = 1 if points_lost and realized_points_lost: if points_lost <= 0.5 and realized_points_lost <= 1.5: evalsize = 0 else: evalsize = min( 1, max(0, realized_points_lost / points_lost)) for m in node.move_with_placements: if has_stone.get(m.coords) and not drawn_stone.get( m.coords): # skip captures, last only for move_eval_on = show_dots_for.get( m.player) and (i < show_n_eval or full_eval_on) if move_eval_on and points_lost is not None: evalcol = self.eval_color(points_lost, show_dots_for_class) else: evalcol = None inner = stone_color[m.opponent] if i == 0 else None drawn_stone[m.coords] = m.player self.draw_stone( m.coords[0], m.coords[1], stone_color[m.player], outline_color[m.player], inner, evalcol, evalsize, ) realized_points_lost = node.parent_realized_points_lost if katrain.game.current_node.is_root and katrain.debug_level >= 3: # secret ;) for y in range(0, board_size_y): evalcol = self.eval_color(16 * y / board_size_y) self.draw_stone(0, y, stone_color["B"], outline_color["B"], None, evalcol, y / (board_size_y - 1)) self.draw_stone(1, y, stone_color["B"], outline_color["B"], stone_color["W"], evalcol, 1) self.draw_stone(2, y, stone_color["W"], outline_color["W"], None, evalcol, y / (board_size_y - 1)) self.draw_stone(3, y, stone_color["W"], outline_color["W"], stone_color["B"], evalcol, 1) self.draw_stone(4, y, [*evalcol[:3], 0.5], scale=0.8) # ownership - allow one move out of date for smooth animation ownership = current_node.ownership or ( current_node.parent and current_node.parent.ownership) if katrain.analysis_controls.ownership.active and ownership and not lock_ai: ownership_grid = var_to_grid(ownership, (board_size_x, board_size_y)) rsz = self.grid_size * 0.2 for y in range(board_size_y - 1, -1, -1): for x in range(board_size_x): ix_owner = "B" if ownership_grid[y][x] > 0 else "W" if ix_owner != (has_stone.get((x, y), -1)): Color(*stone_color[ix_owner], abs(ownership_grid[y][x])) Rectangle(pos=(self.gridpos_x[x] - rsz / 2, self.gridpos_y[y] - rsz / 2), size=(rsz, rsz)) policy = current_node.policy if (not policy and current_node.parent and current_node.parent.policy and katrain.last_player_info.ai and katrain.next_player_info.ai): policy = ( current_node.parent.policy ) # in the case of AI self-play we allow the policy to be one step out of date pass_btn = katrain.board_controls.pass_btn pass_btn.canvas.after.clear() if katrain.analysis_controls.policy.active and policy and not lock_ai: policy_grid = var_to_grid(policy, (board_size_x, board_size_y)) best_move_policy = max(*policy) for y in range(board_size_y - 1, -1, -1): for x in range(board_size_x): if policy_grid[y][x] > 0: polsize = 1.1 * math.sqrt(policy_grid[y][x]) policy_circle_color = ( *POLICY_COLOR, GHOST_ALPHA + TOP_MOVE_ALPHA * (policy_grid[y][x] == best_move_policy), ) self.draw_stone(x, y, policy_circle_color, scale=polsize) polsize = math.sqrt(policy[-1]) with pass_btn.canvas.after: draw_circle( (pass_btn.pos[0] + pass_btn.width / 2, pass_btn.pos[1] + pass_btn.height / 2), polsize * pass_btn.height / 2, POLICY_COLOR, ) # pass circle passed = len(nodes) > 1 and current_node.is_pass if passed: if game_ended: text = katrain.game.manual_score or i18n._( "board-game-end") else: text = i18n._("board-pass") Color(0.45, 0.05, 0.45, 0.7) center = (self.gridpos_x[int(board_size_x / 2)], self.gridpos_y[int(board_size_y / 2)]) size = min(self.width, self.height) * 0.22 Ellipse(pos=(center[0] - size / 2, center[1] - size / 2), size=(size, size)) Color(0.85, 0.85, 0.85) draw_text(pos=center, text=text, font_size=size * 0.25, halign="center", outline_color=[0.95, 0.95, 0.95]) self.draw_hover_contents()
def ellipse(self): return Ellipse(source=type(self).IMAGE, pos=(self.x, self.y), size=self.size)
def draw_hover_contents(self, *_args): ghost_alpha = Theme.GHOST_ALPHA katrain = self.katrain game_ended = katrain.game.end_result current_node = katrain.game.current_node next_player = current_node.next_player board_size_x, board_size_y = katrain.game.board_size if len(self.gridpos_x) < board_size_x or len(self.gridpos_y) < board_size_y: return # race condition with self.canvas.after: self.canvas.after.clear() self.active_pv_moves = [] # hints or PV hint_moves = [] if ( katrain.analysis_controls.hints.active and not katrain.analysis_controls.policy.active and not game_ended ): hint_moves = current_node.candidate_moves elif katrain.controls.status_state[1] == STATUS_TEACHING: # show score hint for teaching undo hint_moves = [ m for m in current_node.candidate_moves for c in current_node.children if c.move and c.auto_undo and c.move.gtp() == m["move"] ] top_move_coords = None child_moves = {c.move.gtp() for c in current_node.children if c.move} if hint_moves: low_visits_threshold = katrain.config("trainer/low_visits", 25) top_moves_show = [ opt for opt in [ katrain.config("trainer/top_moves_show"), katrain.config("trainer/top_moves_show_secondary"), ] if opt in TOP_MOVE_OPTIONS and opt != TOP_MOVE_NOTHING ] for move_dict in hint_moves: move = Move.from_gtp(move_dict["move"]) if move.coords is not None: engine_best_move = move_dict.get("order", 99) == 0 scale = Theme.HINT_SCALE text_on = True alpha = Theme.HINTS_ALPHA if ( move_dict["visits"] < low_visits_threshold and not engine_best_move and not move_dict["move"] in child_moves ): scale = Theme.UNCERTAIN_HINT_SCALE text_on = False alpha = Theme.HINTS_LO_ALPHA if "pv" in move_dict: self.active_pv_moves.append((move.coords, move_dict["pv"], current_node)) else: katrain.log(f"PV missing for move_dict {move_dict}", OUTPUT_DEBUG) evalsize = self.stone_size * scale evalcol = self.eval_color(move_dict["pointsLost"]) if text_on and top_moves_show: # remove grid lines using a board colored circle draw_circle( (self.gridpos_x[move.coords[0]], self.gridpos_y[move.coords[1]]), self.stone_size * scale * 0.98, Theme.APPROX_BOARD_COLOR, ) Color(*evalcol[:3], alpha) Rectangle( pos=(self.gridpos_x[move.coords[0]] - evalsize, self.gridpos_y[move.coords[1]] - evalsize), size=(2 * evalsize, 2 * evalsize), texture=cached_texture(Theme.TOP_MOVE_TEXTURE), ) if text_on and top_moves_show: # TODO: faster if not sized? keys = {"size": self.grid_size / 3, "smallsize": self.grid_size / 3.33} player_sign = current_node.player_sign(next_player) if len(top_moves_show) == 1: fmt = "[size={size:.0f}]{" + top_moves_show[0] + "}[/size]" else: fmt = ( "[size={size:.0f}]{" + top_moves_show[0] + "}[/size]\n[size={smallsize:.0f}]{" + top_moves_show[1] + "}[/size]" ) keys[TOP_MOVE_DELTA_SCORE] = ( "0.0" if -0.05 < move_dict["pointsLost"] < 0.05 else f"{-move_dict['pointsLost']:+.1f}" ) # def fmt_maybe_missing(arg,sign,digits=1): # return str(round(sign*arg,digits)) if arg is not None else "N/A" keys[TOP_MOVE_SCORE] = f"{player_sign * move_dict['scoreLead']:.1f}" winrate = move_dict["winrate"] if player_sign == 1 else 1 - move_dict["winrate"] keys[TOP_MOVE_WINRATE] = f"{winrate*100:.1f}" keys[TOP_MOVE_DELTA_WINRATE] = f"{-move_dict['winrateLost']:+.1%}" keys[TOP_MOVE_VISITS] = format_visits(move_dict["visits"]) # keys[TOP_MOVE_UTILITY] = fmt_maybe_missing( move_dict.get('utility'),player_sign,2) # keys[TOP_MOVE_UTILITYLCB] = fmt_maybe_missing(move_dict.get('utilityLcb'),player_sign,2) # keys[TOP_MOVE_SCORE_STDDEV] =fmt_maybe_missing(move_dict.get('scoreStdev'),1) Color(*Theme.HINT_TEXT_COLOR) draw_text( pos=(self.gridpos_x[move.coords[0]], self.gridpos_y[move.coords[1]]), text=fmt.format(**keys), font_name="Roboto", markup=True, line_height=0.85, halign="center", ) if engine_best_move: top_move_coords = move.coords Color(*Theme.TOP_MOVE_BORDER_COLOR) Line( circle=( self.gridpos_x[move.coords[0]], self.gridpos_y[move.coords[1]], self.stone_size - dp(1.2), ), width=dp(1.2), ) # children of current moves in undo / review if katrain.analysis_controls.show_children.active: for child_node in current_node.children: move = child_node.move if move and move.coords is not None: if child_node.analysis_exists: self.active_pv_moves.append( (move.coords, [move.gtp()] + child_node.candidate_moves[0]["pv"], current_node) ) if move.coords != top_move_coords: # for contrast dashed_width = 18 Color(*Theme.NEXT_MOVE_DASH_CONTRAST_COLORS[child_node.player]) Line( circle=( self.gridpos_x[move.coords[0]], self.gridpos_y[move.coords[1]], self.stone_size - dp(1.2), ), width=dp(1.2), ) else: dashed_width = 10 Color(*Theme.STONE_COLORS[child_node.player]) for s in range(0, 360, 30): Line( circle=( self.gridpos_x[move.coords[0]], self.gridpos_y[move.coords[1]], self.stone_size - dp(1.2), s, s + dashed_width, ), width=dp(1.2), ) if self.selecting_region_of_interest and len(self.region_of_interest) == 4: x1, x2, y1, y2 = self.region_of_interest self.draw_roi_box([min(x1, x2), max(x1, x2), min(y1, y2), max(y1, y2)], width=dp(2)) else: # hover next move ghost stone if self.ghost_stone: self.draw_stone(*self.ghost_stone, next_player, alpha=ghost_alpha) animating_pv = self.animating_pv if animating_pv: pv, node, start_time, _ = animating_pv up_to_move = self.get_animate_pv_index() self.draw_pv(pv, node, up_to_move) if getattr(self.katrain.game, "region_of_interest", None): self.draw_roi_box(self.katrain.game.region_of_interest, width=dp(1.25)) # pass circle if current_node.is_pass or game_ended: if game_ended: text = game_ended katrain.controls.timer.paused = True else: text = i18n._("board-pass") Color(*Theme.PASS_CIRCLE_COLOR) center = (self.gridpos_x[int(board_size_x / 2)], self.gridpos_y[int(board_size_y / 2)]) size = min(self.width, self.height) * 0.227 Ellipse(pos=(center[0] - size / 2, center[1] - size / 2), size=(size, size)) Color(*Theme.PASS_CIRCLE_TEXT_COLOR) draw_text(pos=center, text=text, font_size=size * 0.25, halign="center")
def draw_board_contents(self, *_args): if not self.ui_config: return stone_color = self.ui_config["stones"] outline_color = self.ui_config["outline"] katrain = self.katrain board_size_x, board_size_y = katrain.game.board_size lock_ai = self.trainer_config.get( "lock_ai", False) and katrain.controls.teaching_mode_enabled() show_n_eval = self.trainer_config["eval_off_show_last"] self.canvas.clear() with self.canvas: # stones current_node = katrain.game.current_node game_ended = katrain.game.ended full_eval_on = katrain.controls.eval.active has_stone = {} drawn_stone = {} for m in katrain.game.stones: has_stone[m.coords] = m.player show_dots_for = { p: self.trainer_config["eval_show_ai"] or "ai" not in katrain.controls.player_mode(p) for p in Move.PLAYERS } nodes = katrain.game.current_node.nodes_from_root realized_points_lost = None for i, node in enumerate(nodes[::-1]): # reverse order! points_lost = node.points_lost evalsize = 1 if points_lost and realized_points_lost: if points_lost <= 0.5 and realized_points_lost <= 1.5: evalsize = 0 else: evalsize = min( 1, max(0, realized_points_lost / points_lost)) for m in node.move_with_placements: if has_stone.get(m.coords) and not drawn_stone.get( m.coords): # skip captures, last only for move_eval_on = show_dots_for.get( m.player) and (i < show_n_eval or full_eval_on) if move_eval_on and points_lost is not None: evalcol = self.eval_color(points_lost) else: evalcol = None inner = stone_color[m.opponent] if i == 0 else None drawn_stone[m.coords] = m.player self.draw_stone(m.coords[0], m.coords[1], stone_color[m.player], outline_color[m.player], inner, evalcol, evalsize) realized_points_lost = node.parent_realized_points_lost if katrain.game.current_node.is_root and katrain.config( "debug/level") >= 3: # secret ;) for y in range(0, board_size_y): evalcol = self.eval_color(16 * y / board_size_y) self.draw_stone(0, y, stone_color["B"], outline_color["B"], None, evalcol, y / (board_size_y - 1)) self.draw_stone(1, y, stone_color["B"], outline_color["B"], stone_color["W"], evalcol, 1) self.draw_stone(2, y, stone_color["W"], outline_color["W"], None, evalcol, y / (board_size_y - 1)) self.draw_stone(3, y, stone_color["W"], outline_color["W"], stone_color["B"], evalcol, 1) self.draw_stone(4, y, [*evalcol[:3], 0.5], scale=0.8) # ownership - allow one move out of date for smooth animation ownership = current_node.ownership or ( current_node.parent and current_node.parent.ownership) if katrain.controls.ownership.active and ownership: ownership_grid = var_to_grid(ownership, (board_size_x, board_size_y)) rsz = self.grid_size * 0.2 for y in range(board_size_y - 1, -1, -1): for x in range(board_size_x): ix_owner = "B" if ownership_grid[y][x] > 0 else "W" if ix_owner != (has_stone.get((x, y), -1)): Color(*stone_color[ix_owner], abs(ownership_grid[y][x])) Rectangle(pos=(self.gridpos_x[x] - rsz / 2, self.gridpos_y[y] - rsz / 2), size=(rsz, rsz)) policy = current_node.policy if not policy and current_node.parent and current_node.parent.policy and "ai" in katrain.controls.player_mode( "B") and "ai" in katrain.controls.player_mode("W"): policy = current_node.parent.policy # in the case of AI self-play we allow the policy to be one step out of date pass_btn = katrain.board_controls.pass_btn pass_btn.canvas.after.clear() if katrain.controls.policy.active and policy and not lock_ai: policy_grid = var_to_grid(policy, (board_size_x, board_size_y)) best_move_policy = max(*policy) for y in range(board_size_y - 1, -1, -1): for x in range(board_size_x): if policy_grid[y][x] > 0: polsize = 1.1 * math.sqrt(policy_grid[y][x]) policy_circle_color = ( *self.ui_config["policy_color"], self.ui_config["ghost_alpha"] + self.ui_config["top_move_x_alpha"] * (policy_grid[y][x] == best_move_policy), ) self.draw_stone(x, y, policy_circle_color, scale=polsize) polsize = math.sqrt(policy[-1]) with pass_btn.canvas.after: draw_circle((pass_btn.pos[0] + pass_btn.width / 2, pass_btn.pos[1] + pass_btn.height / 2), polsize * pass_btn.height / 2, self.ui_config["policy_color"]) # pass circle passed = len(nodes) > 1 and current_node.is_pass if passed: if game_ended: text = katrain.game.manual_score or "game\nend" else: text = "pass" Color(0.45, 0.05, 0.45, 0.7) center = (self.gridpos_x[int(board_size_x / 2)], self.gridpos_y[int(board_size_y / 2)]) size = min(self.width, self.height) * 0.22 Ellipse(pos=(center[0] - size / 2, center[1] - size / 2), size=(size, size)) Color(0.85, 0.85, 0.85) draw_text(pos=center, text=text, font_size=size * 0.25, halign="center", outline_color=[0.95, 0.95, 0.95]) self.draw_hover_contents()
def draw_point(self, point, color=(0, 0, 0)): with self.canvas: self.create_color(color) Ellipse(pos=(point.x - 5, point.y - 5), size=(10, 10)) Color(0, 0, 0, 1)
def draw_dot(self, square_to): with self.canvas: Color(112 / 255.0, 128 / 255.0, 144 / 255.0, mode='rgb') Ellipse(pos=((square_to % 8 + 1) * 60 + 22.5, (square_to / 8 + 1) * 60 + 22.5), size=(15, 15))