Skip to content

Commit

Permalink
1.10 (#481)
Browse files Browse the repository at this point in the history
* edit katrain/__main__.py

* delay / 0

* edit katrain/core/constants.py

* edit ENGINE.md

* fix bug

* fix bug

* fix scroll variations

* edit katrain/core/sgf_parser.py, edit tests/test_parser.py and 4 other changes

* fix touchscreen

* antimirror

* openssl dir try

* openssl dir try

* fix log

* openssl

* auto version in osx

* edit .github/workflows/osxbuild.yaml

* edit .github/workflows/osxbuild.yaml

* edit katrain/KataGo/katago

* better pondering

* new downloads

* middle click add variation

* change middle click pv

* more tweaks

* black

Co-authored-by: Sander Land <[email protected]>
Co-authored-by: Sander Land <[email protected]>
Co-authored-by: Sander Land <[email protected]>
  • Loading branch information
4 people authored Oct 31, 2021
1 parent f368f1d commit 6005579
Show file tree
Hide file tree
Showing 38 changed files with 263 additions and 100 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/osxbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
python-version: 3.8
- name: Build KataGo
run: |
export OPENSSL_ROOT_DIR=$(brew --prefix openssl)
export OPENSSL_ROOT_DIR=$(brew --prefix openssl@1.1)
export OPENSSL_LIBRARIES="${OPENSSL_ROOT_DIR}/lib"
echo $OPENSSL_ROOT_DIR
ls $OPENSSL_ROOT_DIR
Expand Down Expand Up @@ -48,11 +48,13 @@ jobs:
python -m pip install .
- name: Finalize KaTrain bundle
run: |
export KATRAIN_VERSION=`python -c 'from katrain.core.constants import VERSION;print(VERSION)' `
echo "Setting version to ${KATRAIN_VERSION}"
cd ../kivy-sdk-packager/osx
pushd KaTrain.app/Contents/Resources/
ln -s ./venv/bin/KaTrain yourapp
popd
./fix-bundle-metadata.sh KaTrain.app -n KaTrain -v "1.9.0" -a "Sander Land" -o "org.katrain.KaTrain" -i "../../katrain/katrain/img/icon.ico"
./fix-bundle-metadata.sh KaTrain.app -n KaTrain -v "${KATRAIN_VERSION}" -a "Sander Land" -o "org.katrain.KaTrain" -i "../../katrain/katrain/img/icon.ico"
./cleanup-app.sh KaTrain.app -g 1
./relocate.sh KaTrain.app
- name: Create dmg
Expand Down
11 changes: 7 additions & 4 deletions ENGINE.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,16 @@ Run DebugKaTrain.exe, which is released in the .zip file distributable in releas

### libzip compatibility

The most common KataGo issue relates to different libzip versions in the provided executables.
Although the provided executables should work on the latest versions of Ubuntu, various other versions and distros differ in their libzip version.
The most common KataGo issue relates to different libzip versions in the provided executables,
leading to an "Error 127".
Although the provided executables should work on the latest versions of Ubuntu with libzip installed,
various other versions and distros differ in their libzip version.

* First, try `sudo apt-get install libzip-dev` to
* First, try `****sudo apt-get install libzip-dev****` to get this library on recent systems.
* Next, try installing all packages mentioned [here](INSTALL.md#LinuxTrouble).
* A final alternative is to go [here](https://github.com/lightvector/KataGo) and compile KataGo yourself.

### Getting more information about errors

Check the terminal output around startup time.
* Check the terminal output around startup time.
* Start KataGo by itself using `katrain/KataGo/katago` when running from source and check output.
1 change: 0 additions & 1 deletion katrain/KataGo/analysis_config.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
# Logs------------------------------------------------------------------------------------

# Where to output log?
logFile = "~/.katrain/katago_log.txt"
# logFile = analysis.log # Use this instead of logDir to just specify a single file directly
# logToStderr = true # Echo everything output to log file to stderr as well
# logAllRequests = false # Log all input lines received to the analysis engine.
Expand Down
Binary file modified katrain/KataGo/katago
Binary file not shown.
Binary file modified katrain/KataGo/katago.exe
Binary file not shown.
57 changes: 28 additions & 29 deletions katrain/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from kivy.clock import Clock
from kivy.metrics import dp
from katrain.core.ai import generate_ai_move
from kivy.utils import platform as kivy_platform

from katrain.core.lang import DEFAULT_LANGUAGE, i18n
from katrain.core.constants import (
Expand Down Expand Up @@ -111,7 +112,7 @@ def __init__(self, **kwargs):
self.timer_settings_popup = None
self.contribute_popup = None

self.idle_analysis = False
self.pondering = False
self.animate_contributing = False
self.message_queue = Queue()

Expand Down Expand Up @@ -141,7 +142,7 @@ def log(self, message, level=OUTPUT_INFO):
def handle_animations(self, *_args):
if self.contributing and self.animate_contributing:
self.engine.advance_showing_game()
if (self.contributing and self.animate_contributing) or self.idle_analysis:
if (self.contributing and self.animate_contributing) or self.pondering:
self.board_controls.engine_status_pondering += 5
else:
self.board_controls.engine_status_pondering = -1
Expand All @@ -154,9 +155,9 @@ def toggle_continuous_analysis(self):
if self.contributing:
self.animate_contributing = not self.animate_contributing
else:
if self.idle_analysis:
if self.pondering:
self.controls.set_status("", STATUS_INFO)
self.idle_analysis = not self.idle_analysis
self.pondering = not self.pondering
self.update_state()

def start(self):
Expand Down Expand Up @@ -257,8 +258,11 @@ def _do_update_state(
): # cn mismatch stops this if undo fired. avoid message loop here or fires repeatedly.
self._do_ai_move(cn)
Clock.schedule_once(self.board_gui.play_stone_sound, 0.25)
if self.engine.is_idle() and self.idle_analysis:
self("analyze-extra", "extra", continuous=True)
if self.engine:
if self.pondering:
self.game.analyze_extra("ponder")
else:
self.engine.stop_pondering()
Clock.schedule_once(lambda _dt: self.update_gui(cn, redraw_board=redraw_board), -1) # trigger?

def update_player(self, bw, **kwargs):
Expand Down Expand Up @@ -322,7 +326,7 @@ def __call__(self, message, *args, **kwargs):
self.message_queue.put([self.game.game_id, message, args, kwargs])

def _do_new_game(self, move_tree=None, analyze_fast=False, sgf_filename=None):
self.idle_analysis = False
self.pondering = False
mode = self.play_analyze_mode
if (move_tree is not None and mode == MODE_PLAY) or (move_tree is None and mode == MODE_ANALYZE):
self.play_mode.switch_ui_mode() # for new game, go to play, for loaded, analyze
Expand Down Expand Up @@ -351,7 +355,7 @@ def _do_katago_contribute(self):
self.contributing = self.animate_contributing = True # special mode
if self.play_analyze_mode == MODE_PLAY: # switch to analysis view
self.play_mode.switch_ui_mode()
self.idle_analysis = False
self.pondering = False
self.board_gui.animating_pv = None
for bw, player_info in self.players_info.items():
self.update_player(bw, player_type=PLAYER_AI, player_subtype=AI_DEFAULT)
Expand Down Expand Up @@ -395,10 +399,6 @@ def _do_find_mistake(self, fn="redo"):
self.board_gui.animating_pv = None
getattr(self.game, fn)(9999, stop_on_mistake=self.config("trainer/eval_thresholds")[-4])

def _do_cycle_children(self, *args):
self.board_gui.animating_pv = None
self.game.cycle_children(*args)

def _do_switch_branch(self, *args):
self.board_gui.animating_pv = None
self.controls.move_tree.switch_branch(*args)
Expand Down Expand Up @@ -593,22 +593,21 @@ def load_sgf_from_clipboard(self):
self.log("Imported game from clipboard.", OUTPUT_INFO)

def on_touch_up(self, touch):
if (
self.board_gui.collide_point(*touch.pos)
or self.board_controls.collide_point(*touch.pos)
or self.controls.move_tree.collide_point(*touch.pos)
):
if touch.is_mouse_scrolling:
if self.board_gui.animating_pv is None:
if touch.button == "scrollup":
self("redo")
elif touch.button == "scrolldown":
self("undo")
else:
if touch.button == "scrollup":
self.board_gui.adjust_animate_pv_index(1)
elif touch.button == "scrolldown":
self.board_gui.adjust_animate_pv_index(-1)
if touch.is_mouse_scrolling:
touching_board = self.board_gui.collide_point(*touch.pos) or self.board_controls.collide_point(*touch.pos)
touching_control_nonscroll = self.controls.collide_point(
*touch.pos
) and not self.controls.notes_panel.collide_point(*touch.pos)
if self.board_gui.animating_pv is not None and touching_board:
if touch.button == "scrollup":
self.board_gui.adjust_animate_pv_index(1)
elif touch.button == "scrolldown":
self.board_gui.adjust_animate_pv_index(-1)
elif touching_board or touching_control_nonscroll: # scroll through moves
if touch.button == "scrollup":
self("redo")
elif touch.button == "scrolldown":
self("undo")
return super().on_touch_up(touch)

@property
Expand Down Expand Up @@ -653,7 +652,7 @@ def popup_open(self) -> Popup:

def _on_keyboard_down(self, _keyboard, keycode, _text, modifiers):
self.last_key_down = keycode
ctrl_pressed = "ctrl" in modifiers
ctrl_pressed = "ctrl" in modifiers or ("meta" in modifiers and kivy_platform == "macosx")
shift_pressed = "shift" in modifiers
if self.controls.note.focus:
return # when making notes, don't allow keyboard shortcuts
Expand Down
3 changes: 2 additions & 1 deletion katrain/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"anim_pv_time": 0.5,
"debug_level": 0,
"lang": "en",
"version": "1.9.0",
"version": "1.10.0",
"load_fast_analysis": false,
"load_sgf_rewind": true
},
Expand Down Expand Up @@ -93,6 +93,7 @@
},
"ai": {
"ai:default": {},
"ai:antimirror": {},
"ai:handicap": {
"automatic": true,
"pda": 0
Expand Down
12 changes: 11 additions & 1 deletion katrain/core/ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
AI_INFLUENCE,
AI_INFLUENCE_ELO_GRID,
AI_JIGO,
AI_ANTIMIRROR,
AI_LOCAL,
AI_LOCAL_ELO_GRID,
AI_PICK,
Expand Down Expand Up @@ -264,6 +265,11 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move,
if not handicap_analysis:
game.katrain.log("Error getting handicap-based move", OUTPUT_ERROR)
ai_mode = AI_DEFAULT
elif ai_mode == AI_ANTIMIRROR:
antimirror_analysis = request_ai_analysis(game, cn, {"antiMirror": True})
if not antimirror_analysis:
game.katrain.log("Error getting antimirror move", OUTPUT_ERROR)
ai_mode = AI_DEFAULT

while not cn.analysis_complete:
time.sleep(0.01)
Expand Down Expand Up @@ -388,6 +394,8 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move,
candidate_ai_moves = cn.candidate_moves
if ai_mode == AI_HANDICAP:
candidate_ai_moves = handicap_analysis["moveInfos"]
elif ai_mode == AI_ANTIMIRROR:
candidate_ai_moves = antimirror_analysis["moveInfos"]

top_cand = Move.from_gtp(candidate_ai_moves[0]["move"], player=cn.next_player)
if top_cand.is_pass and ai_mode not in [
Expand Down Expand Up @@ -492,12 +500,14 @@ def is_tenuki(d):
else:
raise (Exception("No moves found - are you using an older KataGo with no per-move ownership info?"))
else:
if ai_mode not in [AI_DEFAULT, AI_HANDICAP]:
if ai_mode not in [AI_DEFAULT, AI_HANDICAP, AI_ANTIMIRROR]:
game.katrain.log(f"Unknown AI mode {ai_mode} or policy missing, using default.", OUTPUT_INFO)
ai_thoughts += f"Strategy {ai_mode} not found or unexpected fallback."
aimove = top_cand
if ai_mode == AI_HANDICAP:
ai_thoughts += f"Handicap strategy found {len(candidate_ai_moves)} moves returned from the engine and chose {aimove.gtp()} as top move. PDA based score {cn.format_score(handicap_analysis['rootInfo']['scoreLead'])} and win rate {cn.format_winrate(handicap_analysis['rootInfo']['winrate'])}"
if ai_mode == AI_ANTIMIRROR:
ai_thoughts += f"AntiMirror strategy found {len(candidate_ai_moves)} moves returned from the engine and chose {aimove.gtp()} as top move. antiMirror based score {cn.format_score(antimirror_analysis['rootInfo']['scoreLead'])} and win rate {cn.format_winrate(antimirror_analysis['rootInfo']['winrate'])}"
else:
ai_thoughts += f"Default strategy found {len(candidate_ai_moves)} moves returned from the engine and chose {aimove.gtp()} as top move"
game.katrain.log(f"AI thoughts: {ai_thoughts}", OUTPUT_DEBUG)
Expand Down
17 changes: 13 additions & 4 deletions katrain/core/base_katrain.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ def __str__(self):
return f"{self.player_type} ({self.player_subtype})"


def parse_version(s):
parts = [int(p) for p in s.split(".")]
while len(parts) < 3:
parts.append(0)
return parts


class KaTrainBase:
USER_CONFIG_FILE = os.path.expanduser(os.path.join(DATA_FOLDER, "config.json"))
PACKAGE_CONFIG_FILE = "katrain/config.json"
Expand Down Expand Up @@ -101,11 +108,13 @@ def _load_config(self, force_package_config):
self.log(f"Copied package config to local file {config_file}", OUTPUT_INFO)
else: # user file exists
try:
version = JsonStore(user_config_file).get("general")["version"]
version_str = JsonStore(user_config_file).get("general")["version"]
version = parse_version(version_str)
except Exception: # noqa E722 broken file etc
version = "0.0.0"
if version < CONFIG_MIN_VERSION:
backup = user_config_file + f".{version}.backup"
version_str = "0.0.0"
version = [0, 0, 0]
if version < parse_version(CONFIG_MIN_VERSION):
backup = f"{user_config_file}.{version_str}.backup"
shutil.copyfile(user_config_file, backup)
shutil.copyfile(package_config_file, user_config_file)
self.log(
Expand Down
15 changes: 9 additions & 6 deletions katrain/core/constants.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PROGRAM_NAME = "KaTrain"
VERSION = "1.9.3"
VERSION = "1.10.0"
HOMEPAGE = "https://github.com/sanderland/katrain"
CONFIG_MIN_VERSION = "1.9.0" # keep config files from this version
CONFIG_MIN_VERSION = "1.10.0" # keep config files from this version
ANALYSIS_FORMAT_VERSION = "1.0"
DATA_FOLDER = "~/.katrain"

Expand Down Expand Up @@ -42,6 +42,7 @@
AI_SCORELOSS = "ai:scoreloss"
AI_WEIGHTED = "ai:p:weighted"
AI_JIGO = "ai:jigo"
AI_ANTIMIRROR = "ai:antimirror"
AI_POLICY = "ai:policy"
AI_PICK = "ai:p:pick"
AI_LOCAL = "ai:p:local"
Expand All @@ -54,7 +55,7 @@

AI_CONFIG_DEFAULT = AI_RANK

AI_STRATEGIES_ENGINE = [AI_DEFAULT, AI_HANDICAP, AI_SCORELOSS, AI_SIMPLE_OWNERSHIP, AI_JIGO] # AI_SETTLE_STONES
AI_STRATEGIES_ENGINE = [AI_DEFAULT, AI_HANDICAP, AI_SCORELOSS, AI_SIMPLE_OWNERSHIP, AI_JIGO, AI_ANTIMIRROR]
AI_STRATEGIES_PICK = [AI_PICK, AI_LOCAL, AI_TENUKI, AI_INFLUENCE, AI_TERRITORY, AI_RANK]
AI_STRATEGIES_POLICY = [AI_WEIGHTED, AI_POLICY] + AI_STRATEGIES_PICK
AI_STRATEGIES = AI_STRATEGIES_ENGINE + AI_STRATEGIES_POLICY
Expand All @@ -63,20 +64,21 @@
AI_RANK,
AI_HANDICAP,
AI_SIMPLE_OWNERSHIP,
# AI_SETTLE_STONES,
AI_SCORELOSS,
AI_POLICY,
AI_WEIGHTED,
AI_JIGO,
AI_ANTIMIRROR,
AI_PICK,
AI_LOCAL,
AI_TENUKI,
AI_TERRITORY,
AI_INFLUENCE,
AI_JIGO,
]

AI_STRENGTH = { # dan ranks, backup if model is missing. TODO: remove some?
AI_DEFAULT: 9,
AI_ANTIMIRROR: 9,
AI_POLICY: 5,
AI_JIGO: float("nan"),
AI_SCORELOSS: -4,
Expand Down Expand Up @@ -260,7 +262,8 @@
# TOP_MOVE_UTILITY,
# TOP_MOVE_UTILITYLCB
]
REPORT_DT = 0.25
REPORT_DT = 1
PONDERING_REPORT_DT = 0.25

SGF_INTERNAL_COMMENTS_MARKER = "\u3164\u200b"
SGF_SEPARATOR_MARKER = "\u3164\u3164"
4 changes: 3 additions & 1 deletion katrain/core/contribute_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,9 @@ def _read_stdout_thread(self):
game_properties["RU"] = json.dumps(analysis["rules"])
game_properties["PB"] = analysis["blackPlayer"]
game_properties["PW"] = analysis["whitePlayer"]
current_game = BaseGame(self.katrain, game_properties=game_properties)
current_game = BaseGame(
self.katrain, game_properties=game_properties, bypass_config=True
)
self.active_games[game_id] = current_game
last_node = current_game.sync_branch(
[Move.from_gtp(coord, pl) for pl, coord in analysis["moves"]]
Expand Down
Loading

0 comments on commit 6005579

Please sign in to comment.