install
This commit is contained in:
1 parent
7530eff4d3
commit
bf8400b59b
7 files changed
+46
-38
No files matched your search
+1
-1
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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:
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
Reference in new issue
Block a user