diff --git a/CONTRIBUTIONS.md b/CONTRIBUTIONS.md index 0a4492b..cca2da7 100644 --- a/CONTRIBUTIONS.md +++ b/CONTRIBUTIONS.md @@ -46,7 +46,7 @@ Many thanks to these additional authors: * "bale-go" for development and continued work on the 'calibrated rank' AI and rank estimation algorithm. * "Dontbtme" for detailed feedback and early testing of v1.0+. * "nowoowoo" for a fix to the parser for SGF files with extra line breaks. -* "nimets123" for the timer sound effects and stone graphics. +* "nimets123" for the timer sound effects and board/stone graphics. * Jordan Seaward for the stone sound effects. * "fohristiwhirl" for the Gibo format parsing code. diff --git a/README.md b/README.md index 8a8c254..41488b6 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,8 @@ Further technical details and discussion on these AIs can be found on [this](htt ## Analysis +Analysis options in KaTrain allow you to explore variations and request more in-depth analysis from the engine at any point in the game. + Keyboard shortcuts are shown with **[key]**. * **[Tab]**: Switch between analysis and play modes. @@ -123,6 +125,12 @@ Keyboard shortcuts are shown with **[key]**. * **[spacebar]**: Turn continuous analysis on/off. * **[enter]** AI move. Makes the AI move for the current player regardless of current player selection. +### Rank Estimation + +A new feature in v1.3 is the rank estimation panel. This adds an extra graph which uses a statistical model to estimate the playing strength +of both players for every 80 move segment. It can be used for determining which part of your game needs extra attention, +but keep in mind the estimation is based purely on how well moves correspond to the 'shape sense' of KataGo and can be very inaccurate at times. + ## Keyboard and mouse shortcuts In addition to shortcuts mentioned above and those shown in the main menu: @@ -158,7 +166,7 @@ In addition to shortcuts mentioned above and those shown in the main menu: [![GitHub issues](https://img.shields.io/github/issues/sanderland/katrain)](https://github.com/sanderland/katrain/issues) [![Contributors](https://img.shields.io/static/v1?label=contributors&message=16&color=dcb424)](CONTRIBUTIONS.md) [![Liberapay patrons](https://img.shields.io/liberapay/patrons/sanderbaduk)](https://liberapay.com/sanderbaduk/) -[![Github sponsors](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=dcb424&link=https://github.com/sponsors/sanderland/)](https://github.com/sponsors/sanderland) +[![Github sponsors](https://img.shields.io/static/v1?label=Sponsor&message=2&logo=GitHub&color=dcb424&link=https://github.com/sponsors/sanderland/)](https://github.com/sponsors/sanderland) * Ideas, feedback, and contributions to code or translations are all very welcome. * For suggestions and planned improvements, see [open issues](https://github.com/sanderland/katrain/issues) on github to check if the functionality is already planned. diff --git a/katrain/core/ai.py b/katrain/core/ai.py index 3cffc8f..67bd9db 100644 --- a/katrain/core/ai.py +++ b/katrain/core/ai.py @@ -195,9 +195,11 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, if policy_moves[0][0] > override: aimove = top_policy_move ai_thoughts += f"Top policy move has weight > {override:.1%}, so overriding other strategies." - elif policy_moves[0][0]+policy_moves[1][0] > overridetwo: + elif policy_moves[0][0] + policy_moves[1][0] > overridetwo: aimove = top_policy_move - ai_thoughts += f"Top two policy moves have cumulative weight > {overridetwo:.1%}, so overriding other strategies." + ai_thoughts += ( + f"Top two policy moves have cumulative weight > {overridetwo:.1%}, so overriding other strategies." + ) elif ai_mode == AI_WEIGHTED: aimove, ai_thoughts = policy_weighted_move( policy_moves, ai_settings["lower_bound"], ai_settings["weaken_fac"] diff --git a/katrain/core/game_node.py b/katrain/core/game_node.py index 4a51d23..a4f8676 100644 --- a/katrain/core/game_node.py +++ b/katrain/core/game_node.py @@ -230,7 +230,13 @@ class GameNode(SGFNode): polmoves = self.policy_ranking top_polmove = polmoves[0][1] if polmoves else Move(None) # if no info at all, pass return [ - {**self.analysis["root"], "pointsLost": 0, "order": 0, "move": top_polmove.gtp(),"pv":[top_polmove.gtp()]} + { + **self.analysis["root"], + "pointsLost": 0, + "order": 0, + "move": top_polmove.gtp(), + "pv": [top_polmove.gtp()], + } ] # single visit -> go by policy/root root_score = self.analysis["root"]["scoreLead"] diff --git a/katrain/gui/badukpan.py b/katrain/gui/badukpan.py index 4c36c71..07bb3c1 100644 --- a/katrain/gui/badukpan.py +++ b/katrain/gui/badukpan.py @@ -138,7 +138,7 @@ class BadukPanWidget(Widget): def draw_stone(self, x, y, player, alpha=1, innercol=None, evalcol=None, evalscale=1.0, scale=1.0): stone_size = self.stone_size * scale - Color(1,1,1,alpha) + Color(1, 1, 1, alpha) Rectangle( pos=(self.gridpos_x[x] - stone_size, self.gridpos_y[y] - stone_size), size=(2 * stone_size, 2 * stone_size), @@ -148,9 +148,11 @@ class BadukPanWidget(Widget): eval_radius = math.sqrt(evalscale) # scale area by evalscale evalsize = self.stone_size * (EVAL_DOT_MIN_SIZE + eval_radius * (EVAL_DOT_MAX_SIZE - EVAL_DOT_MIN_SIZE)) Color(*evalcol) - Rectangle( pos=(self.gridpos_x[x] - evalsize, self.gridpos_y[y] - evalsize), - size=(2 * evalsize, 2 * evalsize), - source=f"img/dot.png") + Rectangle( + pos=(self.gridpos_x[x] - evalsize, self.gridpos_y[y] - evalsize), + size=(2 * evalsize, 2 * evalsize), + source=f"img/dot.png", + ) if innercol: Color(*innercol) inner_size = stone_size * 0.8 @@ -194,10 +196,11 @@ class BadukPanWidget(Widget): for i in range(board_size_y) ] - Color(*BOARD_COLOR) + Color(1, 0.95, 0.8, 1) # image is a bit too light 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), + source="img/board.png", ) Color(*LINE_COLOR) @@ -452,7 +455,7 @@ class BadukPanWidget(Widget): hide_node = cn while hide_node and hide_node.move and hide_node != node: if not hide_node.move.is_pass: - pos = (self.gridpos_x[hide_node.move.coords[0]],self.gridpos_y[hide_node.move.coords[1]]) + pos = (self.gridpos_x[hide_node.move.coords[0]], self.gridpos_y[hide_node.move.coords[1]]) draw_circle(pos, self.stone_size, [0.85, 0.68, 0.40, 0.8]) hide_node = hide_node.parent for i, gtpmove in enumerate(pv): @@ -473,9 +476,9 @@ class BadukPanWidget(Widget): sizefac = 1 stone_size = self.stone_size * sizefac - Color(1,1,1,1) + Color(1, 1, 1, 1) Rectangle( - pos=(board_coords[0]-stone_size,board_coords[1]-stone_size), + pos=(board_coords[0] - stone_size, board_coords[1] - stone_size), size=(2 * stone_size, 2 * stone_size), source=f"img/{move_player}_stone.png", ) diff --git a/katrain/gui/style.py b/katrain/gui/style.py index 4141077..a4a3222 100644 --- a/katrain/gui/style.py +++ b/katrain/gui/style.py @@ -46,7 +46,7 @@ LINE_COLOR = [0, 0, 0] POLICY_COLOR = [0.9, 0.2, 0.8] STARPOINT_SIZE = 0.1 BOARD_COLOR = [0.85, 0.68, 0.40, 1] -STONE_SIZE = 0.505 # texture edge is transparent +STONE_SIZE = 0.505 # texture edge is transparent VISITS_FRAC_SMALL = 0.1 GHOST_ALPHA = 0.5 diff --git a/katrain/img/board.png b/katrain/img/board.png new file mode 100644 index 0000000..fb4bfd2 Binary files /dev/null and b/katrain/img/board.png differ