ai selfplay, black 120
This commit is contained in:
1 parent
06cc316326
commit
9c6d521a88
16 files changed
+566
-134
No files matched your search
+91
-21
@@ -96,7 +96,8 @@ class BadukPanWidget(Widget):
|
||||
near_move = [
|
||||
(pv, node)
|
||||
for move, pv, node in self.active_pv_moves
|
||||
if abs(rel_pos[0] - self.gridpos_x[move[0]]) < self.grid_size / 2 and abs(rel_pos[1] - self.gridpos_y[move[1]]) < self.grid_size / 2
|
||||
if abs(rel_pos[0] - self.gridpos_x[move[0]]) < self.grid_size / 2
|
||||
and abs(rel_pos[1] - self.gridpos_y[move[1]]) < self.grid_size / 2
|
||||
]
|
||||
if near_move:
|
||||
self.set_animating_pv(near_move[0][0], near_move[0][1])
|
||||
@@ -120,7 +121,9 @@ class BadukPanWidget(Widget):
|
||||
xd, xp = self._find_closest(touch.x, self.gridpos_x)
|
||||
yd, yp = self._find_closest(touch.y, self.gridpos_y)
|
||||
|
||||
nodes_here = [node for node in katrain.game.current_node.nodes_from_root if node.move and node.move.coords == (xp, yp)]
|
||||
nodes_here = [
|
||||
node for node in katrain.game.current_node.nodes_from_root if node.move and node.move.coords == (xp, yp)
|
||||
]
|
||||
if nodes_here and max(yd, xd) < self.grid_size / 2: # load old comment
|
||||
if touch.is_double_tap: # navigate to move
|
||||
katrain.game.set_current_node(nodes_here[-1])
|
||||
@@ -181,12 +184,19 @@ class BadukPanWidget(Widget):
|
||||
extra_px_margin_y = (self.height - board_height_with_margins) / 2
|
||||
self.stone_size = self.grid_size * STONE_SIZE
|
||||
|
||||
self.gridpos_x = [self.pos[0] + extra_px_margin_x + math.floor((grid_spaces_margin_x[0] + i) * self.grid_size + 0.5) for i in range(board_size_x)]
|
||||
self.gridpos_y = [self.pos[1] + extra_px_margin_y + math.floor((grid_spaces_margin_y[0] + i) * self.grid_size + 0.5) for i in range(board_size_y)]
|
||||
self.gridpos_x = [
|
||||
self.pos[0] + extra_px_margin_x + math.floor((grid_spaces_margin_x[0] + i) * self.grid_size + 0.5)
|
||||
for i in range(board_size_x)
|
||||
]
|
||||
self.gridpos_y = [
|
||||
self.pos[1] + extra_px_margin_y + math.floor((grid_spaces_margin_y[0] + i) * self.grid_size + 0.5)
|
||||
for i in range(board_size_y)
|
||||
]
|
||||
|
||||
Color(*BOARD_COLOR)
|
||||
Rectangle(
|
||||
pos=(self.gridpos_x[0] - self.grid_size * 1.5, self.gridpos_y[0] - self.grid_size * 1.5), size=(self.grid_size * x_grid_spaces, self.grid_size * y_grid_spaces)
|
||||
pos=(self.gridpos_x[0] - self.grid_size * 1.5, self.gridpos_y[0] - self.grid_size * 1.5),
|
||||
size=(self.grid_size * x_grid_spaces, self.grid_size * y_grid_spaces),
|
||||
)
|
||||
|
||||
Color(*LINE_COLOR)
|
||||
@@ -200,7 +210,9 @@ class BadukPanWidget(Widget):
|
||||
star_point_pos = 3 if size <= 11 else 4
|
||||
if size < 7:
|
||||
return []
|
||||
return [star_point_pos - 1, size - star_point_pos] + ([int(size / 2)] if size % 2 == 1 and size > 7 else [])
|
||||
return [star_point_pos - 1, size - star_point_pos] + (
|
||||
[int(size / 2)] if size % 2 == 1 and size > 7 else []
|
||||
)
|
||||
|
||||
starpt_size = self.grid_size * STARPOINT_SIZE
|
||||
for x in star_point_coords(board_size_x):
|
||||
@@ -211,9 +223,19 @@ class BadukPanWidget(Widget):
|
||||
Color(0.25, 0.25, 0.25)
|
||||
coord_offset = self.grid_size * 1.5 / 2
|
||||
for i in range(board_size_x):
|
||||
draw_text(pos=(self.gridpos_x[i], self.gridpos_y[0] - coord_offset), text=Move.GTP_COORD[i], font_size=self.grid_size / 1.5, font_name="Roboto")
|
||||
draw_text(
|
||||
pos=(self.gridpos_x[i], self.gridpos_y[0] - coord_offset),
|
||||
text=Move.GTP_COORD[i],
|
||||
font_size=self.grid_size / 1.5,
|
||||
font_name="Roboto",
|
||||
)
|
||||
for i in range(board_size_y):
|
||||
draw_text(pos=(self.gridpos_x[0] - coord_offset, self.gridpos_y[i]), text=str(i + 1), font_size=self.grid_size / 1.5, font_name="Roboto")
|
||||
draw_text(
|
||||
pos=(self.gridpos_x[0] - coord_offset, self.gridpos_y[i]),
|
||||
text=str(i + 1),
|
||||
font_size=self.grid_size / 1.5,
|
||||
font_name="Roboto",
|
||||
)
|
||||
|
||||
def draw_board_contents(self, *_args):
|
||||
if not (self.katrain and self.katrain.game):
|
||||
@@ -236,7 +258,9 @@ class BadukPanWidget(Widget):
|
||||
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 = {
|
||||
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
|
||||
@@ -259,7 +283,15 @@ class BadukPanWidget(Widget):
|
||||
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)
|
||||
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 ;)
|
||||
@@ -284,8 +316,16 @@ class BadukPanWidget(Widget):
|
||||
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
|
||||
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()
|
||||
@@ -303,7 +343,11 @@ class BadukPanWidget(Widget):
|
||||
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)
|
||||
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
|
||||
@@ -317,7 +361,9 @@ class BadukPanWidget(Widget):
|
||||
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])
|
||||
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()
|
||||
|
||||
@@ -347,9 +393,20 @@ class BadukPanWidget(Widget):
|
||||
evalcol = copy.copy(self.eval_color(points_lost))
|
||||
evalcol[3] = alpha
|
||||
if child_node.analysis_ready:
|
||||
self.active_pv_moves.append((move.coords, [move.gtp()] + child_node.candidate_moves[0]["pv"], current_node))
|
||||
self.active_pv_moves.append(
|
||||
(move.coords, [move.gtp()] + child_node.candidate_moves[0]["pv"], current_node)
|
||||
)
|
||||
scale = CHILD_SCALE
|
||||
self.draw_stone(move.coords[0], move.coords[1], (*stone_color[move.player][:3], alpha), None, None, evalcol, evalscale=scale, scale=scale)
|
||||
self.draw_stone(
|
||||
move.coords[0],
|
||||
move.coords[1],
|
||||
(*stone_color[move.player][:3], alpha),
|
||||
None,
|
||||
None,
|
||||
evalcol,
|
||||
evalscale=scale,
|
||||
scale=scale,
|
||||
)
|
||||
|
||||
# hints or PV
|
||||
if katrain.analysis_controls.hints.active and not game_ended and not lock_ai:
|
||||
@@ -366,7 +423,12 @@ class BadukPanWidget(Widget):
|
||||
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)
|
||||
self.draw_stone(move.coords[0], move.coords[1], [*self.eval_color(move_dict["pointsLost"])[:3], alpha], scale=scale)
|
||||
self.draw_stone(
|
||||
move.coords[0],
|
||||
move.coords[1],
|
||||
[*self.eval_color(move_dict["pointsLost"])[:3], alpha],
|
||||
scale=scale,
|
||||
)
|
||||
|
||||
# hover next move ghost stone
|
||||
if self.ghost_stone:
|
||||
@@ -403,7 +465,9 @@ class BadukPanWidget(Widget):
|
||||
if coords is None: # tee-hee
|
||||
sizefac = katrain.board_controls.pass_btn.size[1] / 2 / self.stone_size
|
||||
board_coords = [
|
||||
katrain.board_controls.pass_btn.pos[0] + katrain.board_controls.pass_btn.size[0] + self.stone_size * sizefac,
|
||||
katrain.board_controls.pass_btn.pos[0]
|
||||
+ katrain.board_controls.pass_btn.size[0]
|
||||
+ self.stone_size * sizefac,
|
||||
katrain.board_controls.pass_btn.pos[1] + katrain.board_controls.pass_btn.size[1] / 2,
|
||||
]
|
||||
else:
|
||||
@@ -414,7 +478,9 @@ class BadukPanWidget(Widget):
|
||||
draw_text(pos=board_coords, text=str(i + 1), font_size=self.grid_size / 1.45, font_name="Roboto")
|
||||
|
||||
def set_animating_pv(self, pv, node):
|
||||
if node is not None and (not self.animating_pv or not (self.animating_pv[0] == pv and self.animating_pv[1] == node)):
|
||||
if node is not None and (
|
||||
not self.animating_pv or not (self.animating_pv[0] == pv and self.animating_pv[1] == node)
|
||||
):
|
||||
self.animating_pv = (pv, node, time.time(), self.last_mouse_pos)
|
||||
|
||||
def show_pv_from_comments(self, pv_str):
|
||||
@@ -441,10 +507,14 @@ class AnalysisControls(MDFloatLayout):
|
||||
|
||||
def build_menu(self, _dt):
|
||||
menu_items = [
|
||||
{"text": i18n._(text) + f" ({shortcut})"} # , "right_content_cls": AnalysisDropdownMenuRightContent(text=shortcut)}
|
||||
{
|
||||
"text": i18n._(text) + f" ({shortcut})"
|
||||
} # , "right_content_cls": AnalysisDropdownMenuRightContent(text=shortcut)}
|
||||
for text, shortcut in zip(self.ANALYSIS_OPTIONS, self.ANALYSIS_SHORTCUTS)
|
||||
]
|
||||
self.analysis_menu = AnalysisDropdownMenu(caller=self.analysis_button, items=menu_items, width_mult=5, use_icon_item=False, callback=self.action)
|
||||
self.analysis_menu = AnalysisDropdownMenu(
|
||||
caller=self.analysis_button, items=menu_items, width_mult=5, use_icon_item=False, callback=self.action
|
||||
)
|
||||
|
||||
def action(self, item):
|
||||
katrain = MDApp.get_running_app().gui
|
||||
|
||||
@@ -56,11 +56,14 @@ class ControlsPanel(BoxLayout):
|
||||
if not game:
|
||||
return
|
||||
current_node, move = game.current_node, game.current_node.move
|
||||
if game.current_node is not self.status_node and not (self.status is not None and self.status_node is None and game.current_node.is_root): # startup errors on root
|
||||
if game.current_node is not self.status_node and not (
|
||||
self.status is not None and self.status_node is None and game.current_node.is_root
|
||||
): # startup errors on root
|
||||
self.status.text = ""
|
||||
self.status_node = None
|
||||
|
||||
last_player_was_ai_playing_human = katrain.last_player_info.ai and katrain.next_player_info.human
|
||||
both_players_are_robots = katrain.last_player_info.ai and katrain.next_player_info.ai
|
||||
|
||||
self.active_comment_node = current_node
|
||||
if katrain.play_analyze_mode == MODE_PLAY and last_player_was_ai_playing_human:
|
||||
@@ -68,11 +71,15 @@ class ControlsPanel(BoxLayout):
|
||||
self.active_comment_node = current_node.children[-1]
|
||||
elif current_node.parent:
|
||||
self.active_comment_node = current_node.parent
|
||||
elif both_players_are_robots and not current_node.analysis_ready and current_node.parent:
|
||||
self.active_comment_node = current_node.parent
|
||||
|
||||
hints = katrain.analysis_controls.hints.active
|
||||
info = ""
|
||||
if current_node.move and not current_node.is_root:
|
||||
info = self.active_comment_node.comment(teach=katrain.players_info[self.active_comment_node.player].being_taught, hints=hints)
|
||||
info = self.active_comment_node.comment(
|
||||
teach=katrain.players_info[self.active_comment_node.player].being_taught, hints=hints
|
||||
)
|
||||
|
||||
if self.active_comment_node.analysis_ready:
|
||||
self.stats.score = self.active_comment_node.format_score() or ""
|
||||
|
||||
@@ -77,7 +77,9 @@ class LeftButtonBehavior(ButtonBehavior): # stops buttons etc activating on rig
|
||||
|
||||
|
||||
# -- resizeable buttons
|
||||
class SizedButton(LeftButtonBehavior, RectangularRippleBehavior, BasePressedButton, BaseFlatButton, BackgroundMixin): # avoid baserectangular for sizing
|
||||
class SizedButton(
|
||||
LeftButtonBehavior, RectangularRippleBehavior, BasePressedButton, BaseFlatButton, BackgroundMixin
|
||||
): # avoid baserectangular for sizing
|
||||
text = StringProperty("")
|
||||
text_color = ListProperty(WHITE)
|
||||
text_size = ListProperty([100, 100])
|
||||
@@ -263,7 +265,10 @@ class PlayerSetup(MDBoxLayout):
|
||||
if self.mode == PLAYER_AI:
|
||||
return {"player_type": self.player_type.selected[1], "player_subtype": self.player_subtype_ai.selected[1]}
|
||||
else:
|
||||
return {"player_type": self.player_type.selected[1], "player_subtype": self.player_subtype_human.selected[1]}
|
||||
return {
|
||||
"player_type": self.player_type.selected[1],
|
||||
"player_subtype": self.player_subtype_human.selected[1],
|
||||
}
|
||||
|
||||
def update_widget(self, player_type, player_subtype):
|
||||
self.player_type.select_key(player_type) # should trigger setup options
|
||||
@@ -373,18 +378,30 @@ class CollapsablePanel(MDBoxLayout):
|
||||
super().__init__(**kwargs)
|
||||
self.orientation = "vertical"
|
||||
self.bind(
|
||||
options=self.build_options, option_colors=self.build_options, options_height=self.build_options, option_active=self.build_options, options_spacing=self.build_options,
|
||||
options=self.build_options,
|
||||
option_colors=self.build_options,
|
||||
options_height=self.build_options,
|
||||
option_active=self.build_options,
|
||||
options_spacing=self.build_options,
|
||||
)
|
||||
self.bind(state=self.build, size_hint_y_open=self.build, height_open=self.build)
|
||||
MDApp.get_running_app().bind(language=lambda *_: Clock.schedule_once(self.build_options, 0))
|
||||
self.build_options()
|
||||
|
||||
def build_options(self, *args, **kwargs):
|
||||
self.header = CollapsablePanelHeader(height=self.options_height, size_hint_y=None, spacing=self.options_spacing, padding=[1, 0, 0, 0])
|
||||
self.header = CollapsablePanelHeader(
|
||||
height=self.options_height, size_hint_y=None, spacing=self.options_spacing, padding=[1, 0, 0, 0]
|
||||
)
|
||||
self.option_buttons = []
|
||||
option_labels = self.option_labels or [i18n._(f"tab:{opt}") for opt in self.options]
|
||||
for ix, (lbl, opt_col, active) in enumerate(zip(option_labels, self.option_colors, self.option_active)):
|
||||
button = CollapsablePanelTab(text=lbl, font_name=i18n.font_name, active_outline_color=opt_col, height=self.options_height, state="down" if active else "normal")
|
||||
button = CollapsablePanelTab(
|
||||
text=lbl,
|
||||
font_name=i18n.font_name,
|
||||
active_outline_color=opt_col,
|
||||
height=self.options_height,
|
||||
state="down" if active else "normal",
|
||||
)
|
||||
self.option_buttons.append(button)
|
||||
button.bind(state=lambda *_args, _ix=ix: self.trigger_select(_ix))
|
||||
self.open_close_button = TransparentIconButton( # << / >> collapse button
|
||||
@@ -405,7 +422,11 @@ class CollapsablePanel(MDBoxLayout):
|
||||
self.header.add_widget(Label()) # spacer
|
||||
self.trigger_select(ix=None)
|
||||
else:
|
||||
self.header.add_widget(Label(text=i18n._(self.closed_label), font_name=i18n.font_name, halign="right", height=self.options_height))
|
||||
self.header.add_widget(
|
||||
Label(
|
||||
text=i18n._(self.closed_label), font_name=i18n.font_name, halign="right", height=self.options_height
|
||||
)
|
||||
)
|
||||
self.header.add_widget(self.open_close_button)
|
||||
|
||||
super().clear_widgets()
|
||||
@@ -474,7 +495,9 @@ def draw_text(pos, text, font_name=None, **kw):
|
||||
label = CoreLabel(text=text, bold=True, font_name=font_name or i18n.font_name, **kw) #
|
||||
label.refresh()
|
||||
Rectangle(
|
||||
texture=label.texture, pos=(pos[0] - label.texture.size[0] / 2, pos[1] - label.texture.size[1] / 2), size=label.texture.size,
|
||||
texture=label.texture,
|
||||
pos=(pos[0] - label.texture.size[0] / 2, pos[1] - label.texture.size[1] / 2),
|
||||
size=label.texture.size,
|
||||
)
|
||||
|
||||
|
||||
|
||||
+31
-8
@@ -12,7 +12,14 @@ from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.selectioncontrol import MDCheckbox
|
||||
from kivymd.uix.textfield import MDTextField
|
||||
|
||||
from katrain.core.constants import OUTPUT_ERROR, OUTPUT_DEBUG, OUTPUT_INFO, AI_DEFAULT, AI_CONFIG_DEFAULT, AI_STRATEGIES_RECOMMENDED_ORDER
|
||||
from katrain.core.constants import (
|
||||
OUTPUT_ERROR,
|
||||
OUTPUT_DEBUG,
|
||||
OUTPUT_INFO,
|
||||
AI_DEFAULT,
|
||||
AI_CONFIG_DEFAULT,
|
||||
AI_STRATEGIES_RECOMMENDED_ORDER,
|
||||
)
|
||||
from katrain.core.engine import KataGoEngine
|
||||
from katrain.core.utils import i18n, find_package_resource
|
||||
from katrain.gui.kivyutils import I18NSpinner, BackgroundMixin
|
||||
@@ -116,11 +123,15 @@ class QuickConfigGui(MDBoxLayout):
|
||||
Clock.schedule_once(lambda _dt: self.set_properties(self))
|
||||
|
||||
def collect_properties(self, widget) -> Dict:
|
||||
if isinstance(widget, (LabelledTextInput, LabelledSpinner, LabelledCheckBox)) and getattr(widget, "input_property", None):
|
||||
if isinstance(widget, (LabelledTextInput, LabelledSpinner, LabelledCheckBox)) and getattr(
|
||||
widget, "input_property", None
|
||||
):
|
||||
try:
|
||||
ret = {widget.input_property: widget.input_value}
|
||||
except Exception as e:
|
||||
raise InputParseError(f"Could not parse value for {widget.input_property} ({widget.__class__}): {e}") # TODO : on widget!
|
||||
raise InputParseError(
|
||||
f"Could not parse value for {widget.input_property} ({widget.__class__}): {e}"
|
||||
) # TODO : on widget!
|
||||
else:
|
||||
ret = {}
|
||||
for c in widget.children:
|
||||
@@ -144,11 +155,16 @@ class QuickConfigGui(MDBoxLayout):
|
||||
else:
|
||||
if keys[-1] not in config:
|
||||
config[keys[-1]] = ""
|
||||
self.katrain.log(f"Configuration setting {repr(key)} was missing, created it, but this likely indicates a broken config file.", OUTPUT_ERROR)
|
||||
self.katrain.log(
|
||||
f"Configuration setting {repr(key)} was missing, created it, but this likely indicates a broken config file.",
|
||||
OUTPUT_ERROR,
|
||||
)
|
||||
return config[keys[-1]], config, keys[-1]
|
||||
|
||||
def set_properties(self, widget):
|
||||
if isinstance(widget, (LabelledTextInput, LabelledSpinner, LabelledCheckBox)) and getattr(widget, "input_property", None):
|
||||
if isinstance(widget, (LabelledTextInput, LabelledSpinner, LabelledCheckBox)) and getattr(
|
||||
widget, "input_property", None
|
||||
):
|
||||
value = self.get_setting(widget.input_property)[0]
|
||||
if isinstance(widget, LabelledCheckBox):
|
||||
widget.active = value is True
|
||||
@@ -228,7 +244,9 @@ class ConfigTeacherPopup(QuickConfigGui):
|
||||
savesgfs = self.katrain.config("trainer/save_feedback")
|
||||
show_dots = self.katrain.config("trainer/show_dots")
|
||||
|
||||
for i, (color, threshold, undo, show_dot, savesgf) in enumerate(zip(EVAL_COLORS, thresholds, undos, show_dots, savesgfs)):
|
||||
for i, (color, threshold, undo, show_dot, savesgf) in enumerate(
|
||||
zip(EVAL_COLORS, thresholds, undos, show_dots, savesgfs)
|
||||
):
|
||||
self.add_option_widgets(
|
||||
[
|
||||
BackgroundMixin(background_color=color, size_hint=[0.9, 0.9]),
|
||||
@@ -264,7 +282,9 @@ class AIPopup(QuickConfigGui):
|
||||
self.help_label.text = i18n._(strategy.replace("ai:", "aihelp:"))
|
||||
for k, v in sorted(mode_settings.items(), key=lambda kv: kv[0]):
|
||||
self.options_grid.add_widget(DescriptionLabel(text=k))
|
||||
self.options_grid.add_widget(wrap_anchor(LabelledFloatInput(text=str(v), input_property=f"ai/{strategy}/{k}")))
|
||||
self.options_grid.add_widget(
|
||||
wrap_anchor(LabelledFloatInput(text=str(v), input_property=f"ai/{strategy}/{k}"))
|
||||
)
|
||||
for _ in range((self.max_options - len(mode_settings)) * 2):
|
||||
self.options_grid.add_widget(Label())
|
||||
|
||||
@@ -299,7 +319,10 @@ class LoadSGFPopup(BoxLayout):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
app = MDApp.get_running_app()
|
||||
self.filesel.favorites = [(os.path.abspath(app.gui.config("general/sgf_load")), "SGF Load Dir"), (os.path.abspath(app.gui.config("general/sgf_save")), "SGF Save Dir")]
|
||||
self.filesel.favorites = [
|
||||
(os.path.abspath(app.gui.config("general/sgf_load")), "SGF Load Dir"),
|
||||
(os.path.abspath(app.gui.config("general/sgf_save")), "SGF Save Dir"),
|
||||
]
|
||||
self.filesel.path = os.path.abspath(os.path.expanduser(app.gui.config("general/sgf_load")))
|
||||
print(os.path.abspath(os.path.expanduser(app.gui.config("general/sgf_load"))))
|
||||
self.filesel.select_string = i18n._("Load File")
|
||||
@@ -58,7 +58,9 @@ if platform == "win":
|
||||
|
||||
|
||||
def last_modified_first(files, filesystem):
|
||||
return sorted(f for f in files if filesystem.is_dir(f)) + sorted([f for f in files if not filesystem.is_dir(f)], key=lambda f: -getmtime(f))
|
||||
return sorted(f for f in files if filesystem.is_dir(f)) + sorted(
|
||||
[f for f in files if not filesystem.is_dir(f)], key=lambda f: -getmtime(f)
|
||||
)
|
||||
|
||||
|
||||
def get_home_directory():
|
||||
|
||||
@@ -50,14 +50,30 @@ class ScoreGraph(BackgroundMixin):
|
||||
|
||||
score_granularity = 5
|
||||
winrate_granularity = 10
|
||||
self.score_scale = max(math.ceil(max(-score_values_range[0], score_values_range[1]) / score_granularity), 1) * score_granularity
|
||||
self.winrate_scale = max(math.ceil(max(-winrate_values_range[0], winrate_values_range[1]) / winrate_granularity), 1) * winrate_granularity
|
||||
self.score_scale = (
|
||||
max(math.ceil(max(-score_values_range[0], score_values_range[1]) / score_granularity), 1)
|
||||
* score_granularity
|
||||
)
|
||||
self.winrate_scale = (
|
||||
max(math.ceil(max(-winrate_values_range[0], winrate_values_range[1]) / winrate_granularity), 1)
|
||||
* winrate_granularity
|
||||
)
|
||||
|
||||
xscale = self.width / max(len(score_values) - 1, 15)
|
||||
available_height = self.height
|
||||
score_line_points = [[self.pos[0] + i * xscale, self.pos[1] + self.height / 2 + available_height / 2 * (val / self.score_scale),] for i, val in enumerate(score_values)]
|
||||
score_line_points = [
|
||||
[
|
||||
self.pos[0] + i * xscale,
|
||||
self.pos[1] + self.height / 2 + available_height / 2 * (val / self.score_scale),
|
||||
]
|
||||
for i, val in enumerate(score_values)
|
||||
]
|
||||
winrate_line_points = [
|
||||
[self.pos[0] + i * xscale, self.pos[1] + self.height / 2 + available_height / 2 * (val / self.winrate_scale),] for i, val in enumerate(winrate_values)
|
||||
[
|
||||
self.pos[0] + i * xscale,
|
||||
self.pos[1] + self.height / 2 + available_height / 2 * (val / self.winrate_scale),
|
||||
]
|
||||
for i, val in enumerate(winrate_values)
|
||||
]
|
||||
self.score_points = sum(score_line_points, [])
|
||||
self.winrate_points = sum(winrate_line_points, [])
|
||||
@@ -67,10 +83,18 @@ class ScoreGraph(BackgroundMixin):
|
||||
score_dot_point = score_line_points[self.highlighted_index]
|
||||
winrate_dot_point = winrate_line_points[self.highlighted_index]
|
||||
if math.isnan(score_dot_point[1]):
|
||||
score_dot_point[1] = self.pos[1] + self.height / 2 + available_height / 2 * ((score_nn_values or [0])[-1] / self.score_scale)
|
||||
score_dot_point[1] = (
|
||||
self.pos[1]
|
||||
+ self.height / 2
|
||||
+ available_height / 2 * ((score_nn_values or [0])[-1] / self.score_scale)
|
||||
)
|
||||
self.score_dot_pos = [c - self.highlight_size / 2 for c in score_dot_point]
|
||||
if math.isnan(winrate_dot_point[1]):
|
||||
winrate_dot_point[1] = self.pos[1] + self.height / 2 + available_height / 2 * ((winrate_nn_values or [0])[-1] / self.winrate_scale)
|
||||
winrate_dot_point[1] = (
|
||||
self.pos[1]
|
||||
+ self.height / 2
|
||||
+ available_height / 2 * ((winrate_nn_values or [0])[-1] / self.winrate_scale)
|
||||
)
|
||||
self.winrate_dot_pos = [c - self.highlight_size / 2 for c in winrate_dot_point]
|
||||
|
||||
def update_value(self, node):
|
||||
|
||||
Reference in new issue
Block a user