1.11 (#492)
* Shade estimated territory (#488) * prune branch, icons * Tsumego frame (#506) * straighten quotes * Bump pillow from 9.0.0 to 9.0.1 (#511) * Bump pillow from 8.3.2 to 9.0.0 (#500) * Add option to display higher precision point loss values (#514) * fix mac build (#516) * drop 3.6 support * new katago Co-authored-by: Miles Crawford <miles@milescrawford.com> Co-authored-by: kaorahi <38910552+kaorahi@users.noreply.github.com> Co-authored-by: Hiraoka <khi@users.osdn.me> Co-authored-by: Zironic <Tony-Liou@users.noreply.github.com> Co-authored-by: pdeblanc <peter@spaceandgames.com> Co-authored-by: Dontbtme <66470440+Dontbtme@users.noreply.github.com>
This commit is contained in:
51 files changed
+2016
-271
No files matched your search
+66
-43
@@ -33,7 +33,7 @@ from katrain.core.game import Move
|
||||
from katrain.core.lang import i18n
|
||||
from katrain.core.utils import evaluation_class, format_visits, var_to_grid, json_truncate_arrays
|
||||
from katrain.gui.kivyutils import draw_circle, draw_text, cached_texture
|
||||
from katrain.gui.popups import I18NPopup, ReAnalyzeGamePopup, GameReportPopup
|
||||
from katrain.gui.popups import I18NPopup, ReAnalyzeGamePopup, GameReportPopup, TsumegoFramePopup
|
||||
from katrain.gui.theme import Theme
|
||||
|
||||
|
||||
@@ -269,7 +269,9 @@ class BadukPanWidget(Widget):
|
||||
grid_spaces_margin_y = [0.75, 0.75] # bottom, top
|
||||
x_grid_spaces = board_size_x - 1 + sum(grid_spaces_margin_x)
|
||||
y_grid_spaces = board_size_y - 1 + sum(grid_spaces_margin_y)
|
||||
self.grid_size = min(self.width / x_grid_spaces, self.height / y_grid_spaces)
|
||||
# grid size is rounded to an integer to avoid rounding errors that
|
||||
# produce tiny gaps between shaded grid squares
|
||||
self.grid_size = math.floor(min(self.width / x_grid_spaces, self.height / y_grid_spaces) + 0.1)
|
||||
board_width_with_margins = x_grid_spaces * self.grid_size
|
||||
board_height_with_margins = y_grid_spaces * self.grid_size
|
||||
extra_px_margin_x = (self.width - board_width_with_margins) / 2
|
||||
@@ -348,8 +350,49 @@ class BadukPanWidget(Widget):
|
||||
|
||||
with self.canvas:
|
||||
self.canvas.clear()
|
||||
# stones
|
||||
current_node = katrain.game.current_node
|
||||
|
||||
# ownership - allow one move out of date for smooth animation,
|
||||
# drawn first so the board is shaded underneath all other elements.
|
||||
ownership = current_node.ownership or (current_node.parent and current_node.parent.ownership)
|
||||
if katrain.analysis_controls.ownership.active and ownership:
|
||||
if (
|
||||
current_node.children
|
||||
and katrain.controls.status_state[1] == STATUS_TEACHING
|
||||
and current_node.children[-1].auto_undo
|
||||
and current_node.children[-1].ownership
|
||||
): # loss
|
||||
loss_grid = var_to_grid(
|
||||
[a - b for a, b in zip(current_node.children[-1].ownership, ownership)],
|
||||
(board_size_x, board_size_y),
|
||||
)
|
||||
|
||||
for y in range(board_size_y - 1, -1, -1):
|
||||
for x in range(board_size_x):
|
||||
loss = max(0, (-1 if current_node.children[-1].move.player == "B" else 1) * loss_grid[y][x])
|
||||
if loss > 0:
|
||||
Color(*Theme.EVAL_COLORS[self.trainer_config["theme"]][1][:3], loss)
|
||||
Rectangle(
|
||||
pos=(
|
||||
self.gridpos_x[x] - self.grid_size / 2,
|
||||
self.gridpos_y[y] - self.grid_size / 2,
|
||||
),
|
||||
size=(self.grid_size, self.grid_size),
|
||||
)
|
||||
else:
|
||||
ownership_grid = var_to_grid(ownership, (board_size_x, board_size_y))
|
||||
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"
|
||||
Color(
|
||||
*Theme.STONE_COLORS[ix_owner][:3], abs(ownership_grid[y][x]) * Theme.OWNERSHIP_MAX_ALPHA
|
||||
)
|
||||
Rectangle(
|
||||
pos=(self.gridpos_x[x] - self.grid_size / 2, self.gridpos_y[y] - self.grid_size / 2),
|
||||
size=(self.grid_size, self.grid_size),
|
||||
)
|
||||
|
||||
# stones
|
||||
all_dots_off = not katrain.analysis_controls.eval.active
|
||||
has_stone = {}
|
||||
drawn_stone = {}
|
||||
@@ -399,40 +442,6 @@ class BadukPanWidget(Widget):
|
||||
self.draw_stone(2, y, "W", evalcol=evalcol, evalscale=y / (board_size_y - 1))
|
||||
self.draw_stone(3, y, "W", innercol=Theme.STONE_COLORS["B"], evalcol=evalcol)
|
||||
|
||||
# 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:
|
||||
rsz = self.grid_size * 0.2
|
||||
if (
|
||||
current_node.children
|
||||
and katrain.controls.status_state[1] == STATUS_TEACHING
|
||||
and current_node.children[-1].auto_undo
|
||||
and current_node.children[-1].ownership
|
||||
): # loss
|
||||
loss_grid = var_to_grid(
|
||||
[a - b for a, b in zip(current_node.children[-1].ownership, ownership)],
|
||||
(board_size_x, board_size_y),
|
||||
)
|
||||
|
||||
for y in range(board_size_y - 1, -1, -1):
|
||||
for x in range(board_size_x):
|
||||
loss = max(0, (-1 if current_node.children[-1].move.player == "B" else 1) * loss_grid[y][x])
|
||||
if loss > 0:
|
||||
Color(*Theme.EVAL_COLORS[self.trainer_config["theme"]][1][:3], loss)
|
||||
Rectangle(
|
||||
pos=(self.gridpos_x[x] - rsz / 2, self.gridpos_y[y] - rsz / 2), size=(rsz, rsz)
|
||||
)
|
||||
else:
|
||||
ownership_grid = var_to_grid(ownership, (board_size_x, board_size_y))
|
||||
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(*Theme.STONE_COLORS[ix_owner][:3], 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
|
||||
@@ -517,6 +526,16 @@ class BadukPanWidget(Widget):
|
||||
width=width,
|
||||
)
|
||||
|
||||
def format_loss(self, x: float) -> str:
|
||||
if self.trainer_config.get("extra_precision"):
|
||||
if abs(x) < 0.005:
|
||||
return "0.0"
|
||||
if 0 < x <= 0.995:
|
||||
return "+" + f"{x:.2f}"[1:]
|
||||
elif -0.995 <= x < 0:
|
||||
return "-" + f"{x:.2f}"[2:]
|
||||
return f"{x:+.1f}"
|
||||
|
||||
def draw_hover_contents(self, *_args):
|
||||
ghost_alpha = Theme.GHOST_ALPHA
|
||||
katrain = self.katrain
|
||||
@@ -609,9 +628,7 @@ class BadukPanWidget(Widget):
|
||||
+ "}[/size]"
|
||||
)
|
||||
|
||||
keys[TOP_MOVE_DELTA_SCORE] = (
|
||||
"0.0" if -0.05 < move_dict["pointsLost"] < 0.05 else f"{-move_dict['pointsLost']:+.1f}"
|
||||
)
|
||||
keys[TOP_MOVE_DELTA_SCORE] = self.format_loss(-move_dict["pointsLost"])
|
||||
# def fmt_maybe_missing(arg,sign,digits=1):
|
||||
# return str(round(sign*arg,digits)) if arg is not None else "N/A"
|
||||
|
||||
@@ -620,9 +637,7 @@ class BadukPanWidget(Widget):
|
||||
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]]),
|
||||
@@ -798,6 +813,14 @@ class AnalysisDropDown(DropDown):
|
||||
report_popup.content.popup = report_popup
|
||||
report_popup.open()
|
||||
|
||||
def open_tsumego_frame_popup(self, *_args):
|
||||
analysis_popup = I18NPopup(
|
||||
title_key="analysis:tsumegoframe", size=[dp(500), dp(350)], content=TsumegoFramePopup()
|
||||
)
|
||||
analysis_popup.content.popup = analysis_popup
|
||||
analysis_popup.content.katrain = MDApp.get_running_app().gui
|
||||
analysis_popup.open()
|
||||
|
||||
|
||||
class AnalysisControls(MDBoxLayout):
|
||||
dropdown = ObjectProperty(None)
|
||||
|
||||
@@ -399,7 +399,12 @@ class PlayerSetupBlock(MDBoxLayout):
|
||||
self.players[bw].update_widget(**params)
|
||||
|
||||
def update_player_info(self, bw, player_info): # update sub widget based on gui state change
|
||||
self.players[bw].update_widget(player_type=player_info.player_type, player_subtype=player_info.player_subtype)
|
||||
Clock.schedule_once(
|
||||
lambda _dt: self.players[bw].update_widget(
|
||||
player_type=player_info.player_type, player_subtype=player_info.player_subtype
|
||||
),
|
||||
-1,
|
||||
)
|
||||
|
||||
|
||||
class PlayerInfo(MDBoxLayout, BackgroundMixin):
|
||||
|
||||
+22
-14
@@ -479,22 +479,22 @@ class BaseConfigPopup(QuickConfigGui):
|
||||
|
||||
KATAGOS = {
|
||||
"win": {
|
||||
"OpenCL v1.10.0": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-opencl-windows-x64.zip",
|
||||
"Eigen AVX2 (Modern CPUs) v1.10.0": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-eigenavx2-windows-x64.zip",
|
||||
"Eigen (CPU, Non-optimized) v1.10.0": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-eigen-windows-x64.zip",
|
||||
"OpenCL v1.10.0 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-opencl-windows-x64+bs29.zip",
|
||||
"OpenCL v1.11.0": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-opencl-windows-x64.zip",
|
||||
"Eigen AVX2 (Modern CPUs) v1.11.0": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-eigenavx2-windows-x64.zip",
|
||||
"Eigen (CPU, Non-optimized) v1.11.0": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-eigen-windows-x64.zip",
|
||||
"OpenCL v1.11.0 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-opencl-windows-x64+bs29.zip",
|
||||
},
|
||||
"linux": {
|
||||
"OpenCL v1.10.0": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-opencl-linux-x64.zip",
|
||||
"Eigen AVX2 (Modern CPUs) v1.10.0": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-eigenavx2-linux-x64.zip",
|
||||
"Eigen (CPU, Non-optimized) v1.10.0": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-eigen-linux-x64.zip",
|
||||
"OpenCL v1.10.0 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-opencl-linux-x64+bs29.zip",
|
||||
"OpenCL v1.11.0": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-opencl-linux-x64.zip",
|
||||
"Eigen AVX2 (Modern CPUs) v1.11.0": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-eigenavx2-linux-x64.zip",
|
||||
"Eigen (CPU, Non-optimized) v1.11.0": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-eigen-linux-x64.zip",
|
||||
"OpenCL v1.11.0 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-opencl-linux-x64+bs29.zip",
|
||||
},
|
||||
"just-descriptions": {
|
||||
"CUDA v1.10.0 (Windows)": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-cuda11.2-windows-x64.zip",
|
||||
"CUDA v1.10.0 (Linux)": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-cuda11.1-linux-x64.zip",
|
||||
"Cuda/TensorRT v1.10.0 (Windows)": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-trt8.2-cuda11.2-windows-x64.zip",
|
||||
"Cuda/TensorRT v1.10.0 (Linux)": "https://github.com/lightvector/KataGo/releases/download/v1.10.0/katago-v1.10.0-trt8.2-cuda11.1-linux-x64.zip",
|
||||
"CUDA v1.11.0 (Windows)": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-cuda11.2-windows-x64.zip",
|
||||
"CUDA v1.11.0 (Linux)": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-cuda11.1-linux-x64.zip",
|
||||
"Cuda/TensorRT v1.11.0 (Windows)": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-trt8.2-cuda11.2-windows-x64.zip",
|
||||
"Cuda/TensorRT v1.11.0 (Linux)": "https://github.com/lightvector/KataGo/releases/download/v1.11.0/katago-v1.11.0-trt8.2-cuda11.1-linux-x64.zip",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -810,7 +810,7 @@ class LoadSGFPopup(BaseConfigPopup):
|
||||
(os.path.abspath(app.gui.config("general/sgf_save")), "Last Save Dir"),
|
||||
]
|
||||
self.filesel.path = os.path.abspath(os.path.expanduser(app.gui.config("general/sgf_load")))
|
||||
self.filesel.select_string = i18n._("Load File")
|
||||
self.filesel.select_string = "Load File"
|
||||
|
||||
def on_submit(self):
|
||||
self.filesel.button_clicked()
|
||||
@@ -832,7 +832,7 @@ class SaveSGFPopup(BoxLayout):
|
||||
|
||||
self.filesel.ids.list_view.bind(path=set_suggested)
|
||||
self.filesel.path = os.path.abspath(save_path)
|
||||
self.filesel.select_string = i18n._("Save File")
|
||||
self.filesel.select_string = "Save File"
|
||||
|
||||
def on_submit(self):
|
||||
self.filesel.button_clicked()
|
||||
@@ -846,6 +846,14 @@ class ReAnalyzeGamePopup(BoxLayout):
|
||||
self.button.trigger_action(duration=0)
|
||||
|
||||
|
||||
class TsumegoFramePopup(BoxLayout):
|
||||
katrain = ObjectProperty(None)
|
||||
popup = ObjectProperty(None)
|
||||
|
||||
def on_submit(self):
|
||||
self.button.trigger_action(duration=0)
|
||||
|
||||
|
||||
class GameReportPopup(BoxLayout):
|
||||
def __init__(self, katrain, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@@ -119,6 +119,7 @@ class Theme:
|
||||
|
||||
GHOST_ALPHA = 0.6
|
||||
POLICY_ALPHA = 0.5
|
||||
OWNERSHIP_MAX_ALPHA = 0.7 # max ownership brightness
|
||||
|
||||
HINTS_LO_ALPHA = 0.6
|
||||
HINTS_ALPHA = 0.8
|
||||
@@ -162,6 +163,7 @@ class Theme:
|
||||
KEY_AI_POPUP = "f7"
|
||||
KEY_CONFIG_POPUP = "f8"
|
||||
KEY_CONTRIBUTE_POPUP = "f9"
|
||||
KEY_TSUMEGO_FRAME = "f10"
|
||||
|
||||
KEY_NEW_GAME = "n"
|
||||
KEY_SAVE_GAME = "s"
|
||||
@@ -204,3 +206,6 @@ class Theme:
|
||||
KEY_PAUSE_TIMER = ["pause", "break", "f15"]
|
||||
KEY_TOGGLE_COORDINATES = "k"
|
||||
KEY_ZEN = ["`", "~", "f12"]
|
||||
|
||||
KEY_PAUSE_CONTRIBUTE = KEY_PAUSE_TIMER
|
||||
KEY_STOP_CONTRIBUTING = KEY_STOP_ANALYSIS
|
||||
@@ -232,7 +232,7 @@ Builder.load_string(
|
||||
padding_x: 15
|
||||
height: '40dp'
|
||||
size_hint_x: None
|
||||
text: root.select_string
|
||||
text: i18n._(root.select_string)
|
||||
on_release: root.button_clicked()
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -84,6 +84,16 @@ class MoveTreeCanvas(Widget):
|
||||
self.set_game_node(parent)
|
||||
self.is_open = False
|
||||
|
||||
def prune_branch(self):
|
||||
selected_node = self.menu_selected_node
|
||||
if selected_node and selected_node.parent:
|
||||
node = selected_node
|
||||
while node.parent is not None:
|
||||
node.parent.children = [node]
|
||||
node = node.parent
|
||||
self.set_game_node(selected_node)
|
||||
self.is_open = False
|
||||
|
||||
def make_selected_node_main_branch(self):
|
||||
selected_node = self.menu_selected_node or self.scroll_view_widget.current_node
|
||||
if selected_node and selected_node.parent:
|
||||
@@ -229,6 +239,10 @@ class MoveTree(ScrollView, BackgroundMixin):
|
||||
self.move_tree_canvas.delete_selected_node()
|
||||
self.redraw_tree_trigger()
|
||||
|
||||
def prune_branch(self):
|
||||
self.move_tree_canvas.prune_branch()
|
||||
self.redraw_tree_trigger()
|
||||
|
||||
def make_selected_node_main_branch(self):
|
||||
self.move_tree_canvas.make_selected_node_main_branch()
|
||||
self.redraw_tree_trigger()
|
||||
@@ -306,5 +320,12 @@ Builder.load_string(
|
||||
-background_color: Theme.LIGHTER_BACKGROUND_COLOR
|
||||
-height: dp(45)
|
||||
-width_margin: 1.6
|
||||
MoveTreeDropdownItem:
|
||||
text: i18n._("Prune Branch")
|
||||
icon: 'Prune.png'
|
||||
on_action: root.katrain.controls.move_tree.prune_branch()
|
||||
-background_color: Theme.LIGHTER_BACKGROUND_COLOR
|
||||
-height: dp(45)
|
||||
-width_margin: 1.6
|
||||
"""
|
||||
)
|
||||
Reference in new issue
Block a user