This commit is contained in:
Sander Land committed 2020-07-02 16:12:20 +02:00
1 parent 7530eff4d3
commit bf8400b59b
7 files changed
+46 -38

No files matched your search

+1 -1
View File
@@ -47,7 +47,7 @@ Many thanks to these additional authors:
* "Dontbtme" for detailed feedback and early testing of v1.0+. * "Dontbtme" for detailed feedback and early testing of v1.0+.
* "nowoowoo" for a fix to the parser for SGF files with extra line breaks. * "nowoowoo" for a fix to the parser for SGF files with extra line breaks.
* "nimets123" for the timer sound effects. * "nimets123" for the timer sound effects.
* "JSinSeaward" for stone sounds. * Jordan Seaward for the stone sound effects.
* "fohristiwhirl" for the Gibo format parsing code. * "fohristiwhirl" for the Gibo format parsing code.
## Translators ## Translators
+11 -7
View File
@@ -7,7 +7,7 @@
* [Quick install guide for Linux](#LinuxQuick) * [Quick install guide for Linux](#LinuxQuick)
* [Troubleshooting and installation from sources](#LinuxSources) * [Troubleshooting and installation from sources](#LinuxSources)
## <img src="https://upload.wikimedia.org/wikipedia/commons/5/5f/Windows_logo_-_2012.svg" alt="drawing" width="25"/> Installation for MacOS users ## <img src="https://upload.wikimedia.org/wikipedia/commons/8/8a/Apple_Logo.svg" alt="MacOs" height="35"/> Installation for MacOS users
### <a name="MacQuick"></a>Quick install guide ### <a name="MacQuick"></a>Quick install guide
@@ -25,11 +25,12 @@ These commands install [Homebrew](https://brew.sh), which simplifies installing
### <a name="MacSources"></a>Troubleshooting and Installation from sources ### <a name="MacSources"></a>Troubleshooting and Installation from sources
Installation from sources is essentially the same as for Linux, see [here](#LinuxSources). Installation from sources is essentially the same as for Linux, see [here](#LinuxSources),
note that you will still need to install your own KataGo, using brew or otherwise.
If you encounter SSL errors on downloading model files, you may need to follow [these](https://stackoverflow.com/questions/52805115/certificate-verify-failed-unable-to-get-local-issuer-certificate) instructions to fix your certificates. If you encounter SSL errors on downloading model files, you may need to follow [these](https://stackoverflow.com/questions/52805115/certificate-verify-failed-unable-to-get-local-issuer-certificate) instructions to fix your certificates.
## <img src="https://upload.wikimedia.org/wikipedia/commons/5/5f/Windows_logo_-_2012.svg" alt="drawing" width="25"/> Installation for Windows users ## <img src="https://upload.wikimedia.org/wikipedia/commons/5/5f/Windows_logo_-_2012.svg" alt="Windows" height="35"/> Installation for Windows users
### <a name="WindowsQuick"></a>Quick install guide ### <a name="WindowsQuick"></a>Quick install guide
@@ -42,9 +43,9 @@ Simply download and run, everything is included.
* Make sure you have a python installation, I will assume Anaconda (Python 3.7), available [here](https://www.anaconda.com/products/individual#download-section). * Make sure you have a python installation, I will assume Anaconda (Python 3.7), available [here](https://www.anaconda.com/products/individual#download-section).
* Open 'Anaconda prompt' from the start menu and navigate to where you extracted the zip file using the `cd <folder>` command. * Open 'Anaconda prompt' from the start menu and navigate to where you extracted the zip file using the `cd <folder>` command.
* Execute the command `pip3 install .` * Execute the command `pip3 install .`
* Start the app by running `katrain` in the directory where you downloaded the scripts. * Start the app by running `katrain` in the command prompt.
## Installation for Linux users ## <img src="https://upload.wikimedia.org/wikipedia/commons/a/ab/Linux_Logo_in_Linux_Libertine_Font.svg" alt="Linux" height="35"/> Installation for Linux users
### <a name="LinuxQuick"></a>Quick install guide ### <a name="LinuxQuick"></a>Quick install guide
@@ -74,6 +75,7 @@ A binary for KataGo is included, but if you have compiled your own, press F8 to
You can try to manually install dependencies to resolve some issues relating to missing dependencies, You can try to manually install dependencies to resolve some issues relating to missing dependencies,
e.g. the binary 'wheel' is not provided, KataGo is not starting, or sounds are not working. e.g. the binary 'wheel' is not provided, KataGo is not starting, or sounds are not working.
You can also follow these instructions if you don't want to install KaTrain, and just run it locally.
First install the following packages, which are either required for building Kivy, First install the following packages, which are either required for building Kivy,
or may help resolve missing dependencies for Kivy or KataGo. or may help resolve missing dependencies for Kivy or KataGo.
@@ -93,6 +95,7 @@ In case the sound is not working, or there is no available wheel for your OS or
pip3 uninstall kivy pip3 uninstall kivy
pip3 install --no-binary kivy kivy==2.0.0rc2 pip3 install --no-binary kivy kivy==2.0.0rc2
``` ```
You can now start KaTrain by running `python3 -m katrain`
In case KataGo does not start, an alternative is to go [here](https://github.com/lightvector/KataGo) and compile KataGo yourself. In case KataGo does not start, an alternative is to go [here](https://github.com/lightvector/KataGo) and compile KataGo yourself.
@@ -114,7 +117,8 @@ The above devices were found on a 2019 MacBook Pro with both an on-motherboard g
As you can see it scores about twice as high as the Intel UHD chip and KataGo has selected As you can see it scores about twice as high as the Intel UHD chip and KataGo has selected
it as it's sole device. You can configure KataGo to use *both* the AMD and the Intel devices to get the best performance out of the system. it as it's sole device. You can configure KataGo to use *both* the AMD and the Intel devices to get the best performance out of the system.
* Open the 'analysis_config.cfg' file in the KataGo folder. * Open the 'analysis_config.cfg' file in the `katrain/KataGo` folder in your python packages, or local sources.
If you can't find it, turn on `debug_level=1` in general settings and look for the command that is used to start KataGo.
* Search for `numNNServerThreadsPerModel` (~line 75), uncomment the line by deleting the # and set the value to 2. The line should read `numNNServerThreadsPerModel = 2`. * Search for `numNNServerThreadsPerModel` (~line 75), uncomment the line by deleting the # and set the value to 2. The line should read `numNNServerThreadsPerModel = 2`.
* Search for `openclDeviceToUseThread` (~line 117), uncomment by deleting the # and set the values to the device ID numbers identified in the terminal. * Search for `openclDeviceToUseThread` (~line 117), uncomment by deleting the # and set the values to the device ID numbers identified in the terminal.
From the example above, we would want to use devices 1 and 2, for the Intel and AMD GPU's, but not device 0 (the CPU). In our case, the lines should read: From the example above, we would want to use devices 1 and 2, for the Intel and AMD GPU's, but not device 0 (the CPU). In our case, the lines should read:
@@ -122,7 +126,7 @@ As you can see it scores about twice as high as the Intel UHD chip and KataGo ha
openclDeviceToUseThread0 = 1 openclDeviceToUseThread0 = 1
openclDeviceToUseThread1 = 2 openclDeviceToUseThread1 = 2
``` ```
* Run `python3 -m katrain` and confirm that KataGo is now using both devices, by * Run `katrain` and confirm that KataGo is now using both devices, by
checking the output from the terminal, which should indicate two devices being used. For example: checking the output from the terminal, which should indicate two devices being used. For example:
``` ```
Found 3 device(s) on platform 0 with type CPU or GPU or Accelerator Found 3 device(s) on platform 0 with type CPU or GPU or Accelerator
+1
View File
@@ -199,6 +199,7 @@ class KaTrainGui(Screen, KaTrainBase):
and not (teaching_undo and cn.auto_undo is None) and not (teaching_undo and cn.auto_undo is None)
): # cn mismatch stops this if undo fired. avoid message loop here or fires repeatedly. ): # cn mismatch stops this if undo fired. avoid message loop here or fires repeatedly.
self._do_ai_move(cn) self._do_ai_move(cn)
Clock.schedule_once(self.board_gui.play_stone_sound, 0)
if len(self.engine.queries) == 0 and self.idle_analysis: if len(self.engine.queries) == 0 and self.idle_analysis:
self("analyze-extra", "extra", continuous=True) self("analyze-extra", "extra", continuous=True)
Clock.schedule_once(lambda _dt: self.update_gui(cn, redraw_board=redraw_board), -1) # trigger? Clock.schedule_once(lambda _dt: self.update_gui(cn, redraw_board=redraw_board), -1) # trigger?
+17 -18
View File
@@ -2,30 +2,30 @@ import heapq
import math import math
import random import random
import time import time
from typing import Dict, List, Tuple, Optional from typing import Dict, List, Optional, Tuple
from katrain.core.utils import var_to_grid
from katrain.core.constants import ( from katrain.core.constants import (
OUTPUT_INFO,
OUTPUT_DEBUG,
AI_STRATEGIES_POLICY,
AI_POLICY,
AI_WEIGHTED,
AI_STRATEGIES_PICK,
AI_JIGO,
AI_SCORELOSS,
AI_DEFAULT, AI_DEFAULT,
AI_HANDICAP,
AI_INFLUENCE, AI_INFLUENCE,
AI_JIGO,
AI_LOCAL, AI_LOCAL,
AI_PICK,
AI_POLICY,
AI_RANK,
AI_SCORELOSS,
AI_STRATEGIES_PICK,
AI_STRATEGIES_POLICY,
AI_STRENGTH,
AI_TENUKI, AI_TENUKI,
AI_TERRITORY, AI_TERRITORY,
AI_PICK, AI_WEIGHTED,
AI_RANK, OUTPUT_DEBUG,
AI_HANDICAP,
OUTPUT_ERROR, OUTPUT_ERROR,
AI_STRENGTH, OUTPUT_INFO,
) )
from katrain.core.game import Game, GameNode, Move from katrain.core.game import Game, GameNode, Move
from katrain.core.utils import var_to_grid
def ai_rank_estimation(strategy, settings) -> Tuple[int, bool]: def ai_rank_estimation(strategy, settings) -> Tuple[int, bool]:
@@ -200,7 +200,7 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move,
elif ai_mode in AI_STRATEGIES_PICK: elif ai_mode in AI_STRATEGIES_PICK:
if ai_mode != AI_RANK: if ai_mode != AI_RANK:
n_moves = int(ai_settings["pick_frac"] * len(legal_policy_moves) + ai_settings["pick_n"]) n_moves = max(1, int(ai_settings["pick_frac"] * len(legal_policy_moves) + ai_settings["pick_n"]))
else: else:
orig_calib_avemodrank = 0.063015 + 0.7624 * board_squares / ( orig_calib_avemodrank = 0.063015 + 0.7624 * board_squares / (
10 ** (-0.05737 * ai_settings["kyu_rank"] + 1.9482) 10 ** (-0.05737 * ai_settings["kyu_rank"] + 1.9482)
@@ -222,9 +222,8 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move,
) )
- 0.01093 * ai_settings["kyu_rank"] - 0.01093 * ai_settings["kyu_rank"]
) * orig_calib_avemodrank ) * orig_calib_avemodrank
n_moves = int( n_moves = board_squares * norm_leg_moves / (1.31165 * (modified_calib_avemodrank + 1) - 0.082653)
round(board_squares * norm_leg_moves / (1.31165 * (modified_calib_avemodrank + 1) - 0.082653)) n_moves = max(1, round(n_moves))
)
if ai_mode in [AI_INFLUENCE, AI_TERRITORY, AI_LOCAL, AI_TENUKI]: if ai_mode in [AI_INFLUENCE, AI_TERRITORY, AI_LOCAL, AI_TENUKI]:
if cn.depth > ai_settings["endgame"] * board_squares: if cn.depth > ai_settings["endgame"] * board_squares:
+4 -4
View File
@@ -101,7 +101,7 @@ class KataGoEngine:
self.shutdown(finish=False) self.shutdown(finish=False)
self.start() self.start()
def check_alive(self, os_error='', exception_if_dead=False): def check_alive(self, os_error="", exception_if_dead=False):
ok = self.katago_process and self.katago_process.poll() is None ok = self.katago_process and self.katago_process.poll() is None
if not ok and exception_if_dead: if not ok and exception_if_dead:
if self.katago_process: if self.katago_process:
@@ -140,7 +140,7 @@ class KataGoEngine:
else: else:
self.check_alive(exception_if_dead=True) self.check_alive(exception_if_dead=True)
except Exception as e: except Exception as e:
self.katrain.log(f"Exception in reading stdout {e}" , OUTPUT_DEBUG) self.katrain.log(f"Exception in reading stdout {e}", OUTPUT_DEBUG)
return return
def _analysis_read_thread(self): def _analysis_read_thread(self):
@@ -150,7 +150,7 @@ class KataGoEngine:
if not line: if not line:
self.check_alive(exception_if_dead=True) self.check_alive(exception_if_dead=True)
except OSError as e: except OSError as e:
self.check_alive(os_error=str(e),exception_if_dead=True) self.check_alive(os_error=str(e), exception_if_dead=True)
return return
if b"Uncaught exception" in line: if b"Uncaught exception" in line:
@@ -203,7 +203,7 @@ class KataGoEngine:
self.katago_process.stdin.write((json.dumps(query) + "\n").encode()) self.katago_process.stdin.write((json.dumps(query) + "\n").encode())
self.katago_process.stdin.flush() self.katago_process.stdin.flush()
except OSError as e: except OSError as e:
self.check_alive(os_error=str(e),exception_if_dead=True) self.check_alive(os_error=str(e), exception_if_dead=True)
return # do not raise, since there's nothing to catch it return # do not raise, since there's nothing to catch it
def request_analysis( def request_analysis(
+5 -2
View File
@@ -98,14 +98,17 @@ class BadukPanWidget(Widget):
self.draw_hover_contents() self.draw_hover_contents()
self.last_mouse_pos = pos self.last_mouse_pos = pos
def play_stone_sound(self, *_args):
if self.katrain.config("timer/sound"):
random.choice(self.stones_sounds).play()
def on_touch_up(self, touch): def on_touch_up(self, touch):
if ("button" in touch.profile and touch.button != "left") or not self.gridpos_x: if ("button" in touch.profile and touch.button != "left") or not self.gridpos_x:
return return
katrain = self.katrain katrain = self.katrain
if self.ghost_stone and ("button" not in touch.profile or touch.button == "left"): if self.ghost_stone and ("button" not in touch.profile or touch.button == "left"):
katrain("play", self.ghost_stone) katrain("play", self.ghost_stone)
if self.katrain.config("timer/sound"): self.play_stone_sound()
random.choice(self.stones_sounds).play()
elif not self.ghost_stone: elif not self.ghost_stone:
xd, xp = self._find_closest(touch.x, self.gridpos_x) xd, xp = self._find_closest(touch.x, self.gridpos_x)
yd, yp = self._find_closest(touch.y, self.gridpos_y) yd, yp = self._find_closest(touch.y, self.gridpos_y)
+7 -6
View File
@@ -40,11 +40,11 @@ class Graph(Widget):
def update_value(self, node): def update_value(self, node):
with self._lock: with self._lock:
changed = (self.redraw_on_highlight_change and self.highlighted_index != node.depth) changed = self.redraw_on_highlight_change and self.highlighted_index != node.depth
self.highlighted_index = index = node.depth self.highlighted_index = index = node.depth
self.nodes.extend([None] * max(0, index - (len(self.nodes) - 1))) self.nodes.extend([None] * max(0, index - (len(self.nodes) - 1)))
if self.nodes[index]!=node: if self.nodes[index] != node:
changed=True changed = True
self.nodes[index] = node self.nodes[index] = node
if index > 1 and node.parent: # sometimes there are gaps if index > 1 and node.parent: # sometimes there are gaps
backfill, bfnode = index - 1, node.parent backfill, bfnode = index - 1, node.parent
@@ -215,7 +215,7 @@ class RankGraph(Graph):
) )
else: else:
rank_kyu = -4 rank_kyu = -4
return min(RankGraph.RANK_CAP,1 - rank_kyu) # dan rank return min(RankGraph.RANK_CAP, 1 - rank_kyu) # dan rank
@staticmethod @staticmethod
def calculate_ranks(segment_stats, num_intersec): def calculate_ranks(segment_stats, num_intersec):
@@ -275,7 +275,7 @@ class RankGraph(Graph):
min_rank = math.floor(min(all_ranks)) min_rank = math.floor(min(all_ranks))
max_rank = math.ceil(max(all_ranks)) max_rank = math.ceil(max(all_ranks))
if max_rank==min_rank: if max_rank == min_rank:
min_rank -= 1 min_rank -= 1
if (max_rank - min_rank) % 2 != 0: # make midpoint whole integer if (max_rank - min_rank) % 2 != 0: # make midpoint whole integer
if abs(max_rank - max(all_ranks)) < abs(min(all_ranks) - min_rank) and max_rank < self.RANK_CAP: if abs(max_rank - max(all_ranks)) < abs(min(all_ranks) - min_rank) and max_rank < self.RANK_CAP:
@@ -285,7 +285,7 @@ class RankGraph(Graph):
rank_range = max_rank - min_rank rank_range = max_rank - min_rank
self.ids.mid_marker.text = rank_label((max_rank + min_rank) / 2) self.ids.mid_marker.text = rank_label((max_rank + min_rank) / 2)
self.ids.top_marker.text = rank_label(max_rank) + ("+" if max_rank==self.RANK_CAP else "") self.ids.top_marker.text = rank_label(max_rank) + ("+" if max_rank == self.RANK_CAP else "")
self.ids.bottom_marker.text = rank_label(min_rank) self.ids.bottom_marker.text = rank_label(min_rank)
graph_points = {} graph_points = {}
@@ -303,6 +303,7 @@ class RankGraph(Graph):
self.black_rank_points = [] self.black_rank_points = []
self.white_rank_points = [] self.white_rank_points = []
Builder.load_string( Builder.load_string(
""" """
#:set GRAPH_CENTER_COLOR [0.5,0.5,0.5] #:set GRAPH_CENTER_COLOR [0.5,0.5,0.5]