* 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:
authored and GitHub committed 2022-03-24 11:41:20 +01:00
1 parent dcc3b6f344
commit 2ffb79afa2
51 files changed
+2016 -271

No files matched your search

+66 -43
View File
@@ -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)
+6 -1
View File
@@ -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
View File
@@ -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)
+5
View File
@@ -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
+1 -1
View File
@@ -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()
"""
)
+21
View File
@@ -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
"""
)