From 671a764c6ace12755216747dee8561a5c106dd6a Mon Sep 17 00:00:00 2001 From: Sander Land Date: Fri, 29 May 2020 13:34:52 +0200 Subject: [PATCH] player info --- dev/profile.py | 6 +- katrain/__main__.py | 37 +++--- katrain/config.json | 42 +++---- katrain/core/ai.py | 3 +- katrain/core/base_katrain.py | 111 ++++++++++++++++++ katrain/core/constants.py | 9 ++ katrain/core/engine.py | 3 +- katrain/core/game.py | 55 +-------- katrain/core/game_node.py | 1 - katrain/core/settings_and_logging.py | 62 ---------- katrain/core/utils.py | 14 --- katrain/fonts/digital-7.ttf | Bin 34360 -> 0 bytes katrain/gui.kv | 10 +- katrain/gui/ai_settings.py | 2 +- katrain/gui/badukpan.py | 12 +- katrain/gui/controlspanel.py | 17 +-- katrain/gui/kivyutils.py | 42 +++++-- katrain/gui/popups.py | 7 +- .../i18n/locales/en/LC_MESSAGES/katrain.mo | Bin 6134 -> 7901 bytes .../i18n/locales/en/LC_MESSAGES/katrain.po | 68 ++++++++++- .../i18n/locales/ko/LC_MESSAGES/katrain.mo | Bin 6145 -> 8072 bytes .../i18n/locales/ko/LC_MESSAGES/katrain.po | 84 +++++++++++++ .../i18n/locales/nl/LC_MESSAGES/katrain.mo | Bin 6077 -> 8004 bytes .../i18n/locales/nl/LC_MESSAGES/katrain.po | 84 +++++++++++++ katrain/popups.kv | 1 - 25 files changed, 457 insertions(+), 213 deletions(-) create mode 100644 katrain/core/base_katrain.py delete mode 100644 katrain/core/settings_and_logging.py delete mode 100644 katrain/fonts/digital-7.ttf diff --git a/dev/profile.py b/dev/profile.py index bd276c9..8f14e85 100644 --- a/dev/profile.py +++ b/dev/profile.py @@ -4,6 +4,10 @@ import yappi from katrain.__main__ import run_app +yappi.set_clock_type("cpu") yappi.start() -run_app() +try: + run_app() +except: + pass yappi.get_func_stats().save("callgrind.out." + datetime.now().isoformat(), "CALLGRIND") diff --git a/katrain/__main__.py b/katrain/__main__.py index 813f687..4c87a22 100644 --- a/katrain/__main__.py +++ b/katrain/__main__.py @@ -23,23 +23,16 @@ from kivy.storage.jsonstore import JsonStore from kivy.uix.popup import Popup from kivy.uix.screenmanager import Screen from kivymd.app import MDApp -from katrain.core.constants import * from katrain.core.ai import ai_move from katrain.core.utils import ( DEFAULT_LANGUAGE, - OUTPUT_DEBUG, - OUTPUT_ERROR, - OUTPUT_EXTRA_DEBUG, - OUTPUT_INFO, - OUTPUT_KATAGO_STDERR, find_package_resource, i18n, - MODE_PLAY, - switch_lang, ) +from katrain.core.constants import OUTPUT_ERROR, OUTPUT_KATAGO_STDERR, OUTPUT_INFO, OUTPUT_DEBUG, OUTPUT_EXTRA_DEBUG, MODE_PLAY from katrain.gui.popups import ConfigTeacherPopup, ConfigTimerPopup, I18NPopup from katrain.gui.ai_settings import ConfigAIPopupContents -from katrain.core.settings_and_logging import KaTrainSettings +from katrain.core.base_katrain import KaTrainBase from katrain.core.engine import KataGoEngine from katrain.core.game import Game, IllegalMoveException, KaTrainSGF from katrain.core.sgf_parser import Move, ParseError @@ -53,15 +46,15 @@ from katrain.gui.style import ENGINE_BUSY_COL, ENGINE_DOWN_COL, ENGINE_READY_COL __version__ = "1.1.0" -class KaTrainGui(Screen, KaTrainSettings): +class KaTrainGui(Screen, KaTrainBase): """Top level class responsible for tying everything together""" zen = BooleanProperty(False) + controls = ObjectProperty(None) def __init__(self, **kwargs): super().__init__(**kwargs) self.engine = None - self.game = None self.new_game_popup = None self.fileselect_popup = None @@ -109,7 +102,7 @@ class KaTrainGui(Screen, KaTrainSettings): def update_state(self, redraw_board=False): # is called after every message and on receiving analyses and config changes # AI and Trainer/auto-undo handlers cn = self.game.current_node - last_player, next_player = self.game.players[cn.player], self.game.players[cn.next_player] + last_player, next_player = self.players_info[cn.player], self.players_info[cn.next_player] if self.play_analyze_mode == MODE_PLAY: teaching_undo = cn.player and last_player.being_taught if teaching_undo and cn.analysis_ready and cn.parent and cn.parent.analysis_ready and not cn.children and not self.game.ended: @@ -120,7 +113,7 @@ class KaTrainGui(Screen, KaTrainSettings): # Handle prisoners and next player display prisoners = self.game.prisoner_count top, bot = [w.__self__ for w in self.board_controls.circles] # no weakref - if self.game.next_player.player == "W": + if self.next_player_info.player == "W": top, bot = bot, top self.controls.players["W"].active = True self.controls.players["B"].active = False @@ -148,6 +141,14 @@ class KaTrainGui(Screen, KaTrainSettings): self.controls.update_evaluation() self.controls.update_timer(1) + def update_player(self, bw, **kwargs): + super().update_player(bw, **kwargs) + if self.controls: + self.controls.update_players() + self.update_state() + for player_setup_block in PlayerSetupBlock.INSTANCES: + player_setup_block.update_players(bw,self.players_info[bw]) + def set_note(self, note): self.game.current_node.note = note @@ -173,14 +174,12 @@ class KaTrainGui(Screen, KaTrainSettings): self.board_gui.animating_pv = None self.engine.on_new_game() # clear queries self.game = Game(self, self.engine, move_tree=move_tree, analyze_fast=analyze_fast) - for bw, player_widget in self.nav_drawer_contents.player_setup.players.items(): - self.game.players[bw].update(**player_widget.player_def) self.controls.graph.initialize_from_game(self.game.root) self.update_state(redraw_board=True) def _do_ai_move(self, node=None): if node is None or self.game.current_node == node: - mode = self.game.next_player.strategy + mode = self.next_player_info.strategy settings = self.config(f"ai/{mode}") if settings: ai_move(self.game, mode, settings) @@ -190,7 +189,7 @@ class KaTrainGui(Screen, KaTrainSettings): def _do_undo(self, n_times=1): if n_times == "smart": n_times = 1 - if self.play_analyze_mode == "play" and self.game.last_player.ai and self.game.next_player.human: + if self.play_analyze_mode == "play" and self.last_player_info.ai and self.next_player_info.human: n_times = 2 self.board_gui.animating_pv = None self.game.undo(n_times) @@ -206,7 +205,7 @@ class KaTrainGui(Screen, KaTrainSettings): def _do_play(self, coords): self.board_gui.animating_pv = None try: - self.game.play(Move(coords, player=self.game.next_player.player)) + self.game.play(Move(coords, player=self.next_player_info.player)) except IllegalMoveException as e: self.controls.set_status(f"Illegal Move: {str(e)}") @@ -377,7 +376,7 @@ class KaTrainApp(MDApp): def on_language(self, _instance, language): self.gui.log(f"Switching language to {language}", OUTPUT_INFO) - switch_lang(language) + i18n.switch_lang(language) def on_start(self): self.gui.start() diff --git a/katrain/config.json b/katrain/config.json index 997a889..f16db5a 100644 --- a/katrain/config.json +++ b/katrain/config.json @@ -60,71 +60,59 @@ "lock_ai": false }, "ai": { - "default": { + "ai:default": { "_help_right": "No settings available for Default KataGo AI, strength is mainly affected by `max_visits` and `model` in the main settings `engine` section.", "_help_left": "" }, - "jigo": { + "ai:jigo": { "target_score": 0.5, "_help_left": "Will try to win by `target_score`, without further restrictions.", "_help_right": "Also affected by engine settings such as `max_visits`." }, - "scoreloss": { + "ai:scoreloss": { "strength": 0.5 }, - "Policy": { + "ai:policy": { "opening_moves": 20 }, - "P:Weighted": { - "_help_right": "pick_override` determines when top move is chosen without randomness, and `lower_bound` determines the lower bound policy value that is allowed.", - "_help_left": "Plays move with probability=policy^(1/weaken_fac),i.e. `weaken_fac` influences how much more likely weaker moves are picked.", + "ai:p:weighted": { "pick_override": 1.0, "lower_bound": 0.001, "weaken_fac": 1.25 }, - "P:Pick": { + "ai:p:pick": { "pick_override": 0.95, "pick_n": 5, - "pick_frac": 0.33, - "_help_left": "Picks `pick_n + pick_frac * ` at random and plays the best one. Change `pick_frac` to make it see more moves.", - "_help_right": "Plays top move if policy value is above `pick_override` to avoid obvious mistakes." + "pick_frac": 0.33 }, - "P:Local": { + "ai:p:local": { "pick_override": 0.95, "stddev": 1.5, "pick_n": 15, - "pick_frac": 0.0, - "_help_left": "Samples `pick_n + pick_frac * ` near the last move and plays the best one.", - "_help_right": "Lower `stddev` makes it prefer closer moves." + "pick_frac": 0.0 }, - "P:Tenuki": { + "ai:p:tenuki": { "pick_override": 0.85, "stddev": 7.5, "pick_n": 5, "pick_frac": 0.5, - "endgame": 0.45, - "_help_left": "Samples `pick_n + pick_frac * ` away from the last move and plays the best one.", - "_help_right": "Increase `stddev` makes it prefer moves further away. Stops tenukiing after the 'endgame' fraction of the board is filled." + "endgame": 0.45 }, - "P:Influence": { + "ai:p:influence": { "pick_override": 0.95, "pick_n": 5, "pick_frac": 0.4, "threshold": 3.5, "line_weight": 10, - "endgame": 0.4, - "_help_left": "Samples `pick_n + pick_frac * ` and plays the best one, biased to above the `threshold` line.", - "_help_right": "Increase `line_weight` to penalize moves near the edge more. Stops strategy after the 'endgame' fraction of the board is filled." + "endgame": 0.4 }, - "P:Territory": { + "ai:p:territory": { "pick_override": 0.95, "pick_n": 5, "pick_frac": 0.4, "threshold": 3.5, "line_weight": 2, - "endgame": 0.4, - "_help_left": "Samples `pick_n + pick_frac * ` and plays the best one, biased to below the `threshold` line.", - "_help_right": "Increase `line_weight` to penalize moves closer to the center more. Stops strategy after the 'endgame' fraction of the board is filled." + "endgame": 0.4 } } } \ No newline at end of file diff --git a/katrain/core/ai.py b/katrain/core/ai.py index 8c160bd..e3234c0 100644 --- a/katrain/core/ai.py +++ b/katrain/core/ai.py @@ -4,7 +4,8 @@ import random import time from typing import Dict, List, Tuple -from katrain.core.utils import OUTPUT_DEBUG, OUTPUT_INFO, var_to_grid +from katrain.core.utils import var_to_grid +from katrain.core.constants import OUTPUT_INFO, OUTPUT_DEBUG from katrain.core.engine import EngineDiedException from katrain.core.game import Game, GameNode, Move diff --git a/katrain/core/base_katrain.py b/katrain/core/base_katrain.py new file mode 100644 index 0000000..45a5d87 --- /dev/null +++ b/katrain/core/base_katrain.py @@ -0,0 +1,111 @@ +from kivy import Config +from kivy.properties import ObjectProperty +from kivy.storage.jsonstore import JsonStore +import os, sys +from katrain.core.constants import * + +from katrain.core.utils import find_package_resource + + +class Player: + def __init__(self, player="B", player_type=PLAYER_HUMAN, player_subtype=PLAYING_NORMAL, periods_used=0): + self.player = player + self.update(player_type, player_subtype) + self.periods_used = periods_used + + def update(self, player_type=PLAYER_HUMAN, player_subtype=PLAYING_NORMAL): + self.player_type = player_type + self.player_subtype = player_subtype + + @property + def ai(self): + return self.player_type == PLAYER_AI + + @property + def human(self): + return self.player_type == PLAYER_HUMAN + + @property + def being_taught(self): + return self.player_type == PLAYER_HUMAN and self.player_subtype == PLAYING_TEACHING + + @property + def strategy(self): + return self.player_subtype if self.ai else AI_DEFAULT + + def __str__(self): + return f"{self.player_type} ({self.player_subtype})" + + +class KaTrainBase: + CONFIG_FILE = "katrain/config.json" + + """Settings, logging, and players functionality, so other classes like bots who need a katrain instance can be used without a GUI""" + + def __init__(self, **kwargs): + self.debug_level = 0 + self.game = None + + self.logger = lambda message, level=OUTPUT_INFO: self.log(message, level) + self.config_file = self._load_config() + self.debug_level = self.config("general/debug_level", OUTPUT_INFO) + + Config.set("kivy", "log_level", "error") + if self.debug_level >= OUTPUT_DEBUG: + Config.set("kivy", "log_enable", 1) + Config.set("kivy", "log_level", "warning") + if self.debug_level >= OUTPUT_EXTRA_DEBUG: + Config.set("kivy", "log_level", "trace") + self.players_info = {"B": Player("B"), "W": Player("W")} + self.reset_players() + + def log(self, message, level=OUTPUT_INFO): + if level == OUTPUT_ERROR: + print(f"ERROR: {message}", file=sys.stderr) + elif self.debug_level >= level: + print(message) + + def _load_config(self): + config_file = os.path.abspath(sys.argv[1] if len(sys.argv) > 1 else find_package_resource(self.CONFIG_FILE)) + try: + self.log(f"Using config file {config_file}", OUTPUT_INFO) + self._config_store = JsonStore(config_file, indent=4) + self._config = dict(self._config_store) + return config_file + except Exception as e: + self.log(f"Failed to load config {config_file}: {e}", OUTPUT_ERROR) + sys.exit(1) + + def save_config(self): + for k, v in self._config.items(): + self._config_store.put(k, **v) + + def config(self, setting, default=None): + try: + if "/" in setting: + cat, key = setting.split("/") + return self._config[cat].get(key, default) + else: + return self._config[setting] + except KeyError: + self.log(f"Missing configuration option {setting}", OUTPUT_ERROR) + + + def update_player(self, bw, **kwargs): + self.players_info[bw].update(**kwargs) + + def reset_players(self): + self.update_player("B") + self.update_player("W") + for v in self.players_info.values(): + v.periods_used = 0 + + + @property + def last_player_info(self) -> Player: + return self.players_info[self.game.current_node.player] + + @property + def next_player_info(self) -> Player: + return self.players_info[self.game.current_node.next_player] + diff --git a/katrain/core/constants.py b/katrain/core/constants.py index d9d91bd..a2c3046 100644 --- a/katrain/core/constants.py +++ b/katrain/core/constants.py @@ -1,8 +1,17 @@ +HOMEPAGE = "https://github.com/sanderland/katrain" + PLAYER_HUMAN, PLAYER_AI = "player:human", "player:ai" PLAYER_TYPES = [PLAYER_HUMAN, PLAYER_AI] PLAYING_NORMAL, PLAYING_TEACHING = "game:normal", "game:teach" GAME_TYPES = [PLAYING_NORMAL, PLAYING_TEACHING] +MODE_PLAY, MODE_ANALYZE = "play", "analyze" + AI_DEFAULT = "default" AI_STRATEGIES = [AI_DEFAULT] +OUTPUT_ERROR = -1 +OUTPUT_KATAGO_STDERR = -0.5 +OUTPUT_INFO = 0 +OUTPUT_DEBUG = 1 +OUTPUT_EXTRA_DEBUG = 2 diff --git a/katrain/core/engine.py b/katrain/core/engine.py index ce2c63c..ffd6b14 100644 --- a/katrain/core/engine.py +++ b/katrain/core/engine.py @@ -6,7 +6,8 @@ import threading import time from typing import Callable, Optional -from katrain.core.utils import OUTPUT_DEBUG, OUTPUT_ERROR, OUTPUT_EXTRA_DEBUG, OUTPUT_KATAGO_STDERR, find_package_resource, i18n +from katrain.core.utils import find_package_resource, i18n +from katrain.core.constants import OUTPUT_ERROR, OUTPUT_KATAGO_STDERR, OUTPUT_DEBUG, OUTPUT_EXTRA_DEBUG from katrain.core.game_node import GameNode diff --git a/katrain/core/game.py b/katrain/core/game.py index 5879921..b761463 100644 --- a/katrain/core/game.py +++ b/katrain/core/game.py @@ -5,11 +5,11 @@ import threading from datetime import datetime from typing import Dict, List, Union, Optional -from katrain.core.utils import var_to_grid, OUTPUT_INFO, OUTPUT_DEBUG, i18n +from katrain.core.utils import var_to_grid, i18n +from katrain.core.constants import OUTPUT_INFO, OUTPUT_DEBUG, HOMEPAGE from katrain.core.engine import KataGoEngine from katrain.core.game_node import GameNode from katrain.core.sgf_parser import SGF, Move -from katrain.core.constants import * class IllegalMoveException(Exception): @@ -20,46 +20,15 @@ class KaTrainSGF(SGF): _NODE_CLASS = GameNode -class Player: - def __init__(self, player="B", player_type=PLAYER_HUMAN, player_subtype=PLAYING_NORMAL, periods_used=0): - self.player = player - self.update(player_type, player_subtype) - self.periods_used = periods_used - - def update(self, player_type, player_subtype): - self.player_type = player_type - self.player_subtype = player_subtype - - @property - def ai(self): - return self.player_type == PLAYER_AI - - @property - def human(self): - return self.player_type == PLAYER_HUMAN - - @property - def being_taught(self): - return self.player_type == PLAYER_HUMAN and self.player_subtype == PLAYING_TEACHING - - @property - def strategy(self): - return self.player_subtype if self.ai else AI_DEFAULT - - def __str__(self): - return f"{self.player_type} ({self.player_subtype})" - - class Game: """Represents a game of go, including an implementation of capture rules.""" - DEFAULT_PROPERTIES = {"GM": 1, "FF": 4, "AP": "KaTrain:https://github.com/sanderland/katrain"} + DEFAULT_PROPERTIES = {"GM": 1, "FF": 4, "AP": f"KaTrain:{HOMEPAGE}"} - def __init__(self, katrain, engine: Union[Dict, KataGoEngine], move_tree: GameNode = None, players: Dict = None, analyze_fast=False): + def __init__(self, katrain, engine: Union[Dict, KataGoEngine], move_tree: GameNode = None, analyze_fast=False): self.katrain = katrain if not isinstance(engine, Dict): engine = {"B": engine, "W": engine} - self.players = players or {"B": Player("B"), "W": Player("W")} self.engines = engine self.game_id = datetime.strftime(datetime.now(), "%Y-%m-%d %H %M %S") @@ -76,8 +45,6 @@ class Game: handicap = katrain.config("game/handicap") if handicap: self.place_handicap_stones(handicap) - self.root.set_property("PW", str(self.players["W"])) - self.root.set_property("PB", str(self.players["B"])) if not self.root.get_property("RU"): self.root.set_property("RU", katrain.config("game/rules")) @@ -85,14 +52,6 @@ class Game: self.set_current_node(self.root) threading.Thread(target=lambda: self.analyze_all_nodes(-1_000_000, analyze_fast=analyze_fast), daemon=True).start() # return faster, but bypass Kivy Clock - @property - def last_player(self) -> Player: - return self.players[self.current_node.player] - - @property - def next_player(self) -> Player: - return self.players[self.current_node.next_player] - def analyze_all_nodes(self, priority=0, analyze_fast=False): for node in self.root.nodes_in_tree: node.analyze(self.engines[node.next_player], priority=priority, analyze_fast=analyze_fast) @@ -287,10 +246,8 @@ class Game: if eval_thresholds is None: eval_thresholds = self.katrain.config("trainer/eval_thresholds") - black, white = self.root.get_property("PB"), self.root.get_property("PW") - black = re.sub(r"['<>:\"/\\|?*]", "", black or "Black") - white = re.sub(r"['<>:\"/\\|?*]", "", white or "White") - game_name = f"katrain_{black} vs {white} {self.game_id}" + player_names = {bw: re.sub(r"['<>:\"/\\|?*]", "", self.root.get_property("P"+bw) or str(self.katrain.players_info[bw])) for bw in "BW" } + game_name = f"katrain_{player_names['B']} vs {player_names['W']} {self.game_id}" file_name = os.path.abspath(os.path.join(path, f"{game_name}.sgf")) os.makedirs(os.path.dirname(file_name), exist_ok=True) diff --git a/katrain/core/game_node.py b/katrain/core/game_node.py index 8da2fcb..85d1a0c 100644 --- a/katrain/core/game_node.py +++ b/katrain/core/game_node.py @@ -142,7 +142,6 @@ class GameNode(SGFNode): else: text += i18n._("Info:best move") + "\n" if previous_top_move.get("pv") and (sgf or hints): - print("PREV", previous_top_move) text += i18n._("Info:PV").format(pv=self.make_pv(single_move.player, previous_top_move["pv"], interactive)) + "\n" if sgf or hints or teach: diff --git a/katrain/core/settings_and_logging.py b/katrain/core/settings_and_logging.py deleted file mode 100644 index 91cff66..0000000 --- a/katrain/core/settings_and_logging.py +++ /dev/null @@ -1,62 +0,0 @@ -from kivy import Config -from kivy.storage.jsonstore import JsonStore -import os, sys -from katrain.core.utils import ( - OUTPUT_ERROR, - OUTPUT_INFO, - OUTPUT_KATAGO_STDERR, - find_package_resource, - OUTPUT_DEBUG, - OUTPUT_EXTRA_DEBUG, -) - - -class KaTrainSettings: - CONFIG_FILE = "katrain/config.json" - - """Settings and logging functionality, so other classes who need a katrain instance can be used without a GUI""" - - def __init__(self, **kwargs): - self.debug_level = 0 - self.logger = lambda message, level=OUTPUT_INFO: self.log(message, level) - self.config_file = self._load_config() - self.debug_level = self.config("general/debug_level", OUTPUT_INFO) - - Config.set("kivy", "log_level", "error") - if self.debug_level >= OUTPUT_DEBUG: - Config.set("kivy", "log_enable", 1) - Config.set("kivy", "log_level", "warning") - - # if self.debug_level >= OUTPUT_EXTRA_DEBUG: - # Config.set("kivy", "log_level", "trace") - - def log(self, message, level=OUTPUT_INFO): - if level == OUTPUT_ERROR: - print(f"ERROR: {message}", file=sys.stderr) - elif self.debug_level >= level: - print(message) - - def _load_config(self): - config_file = os.path.abspath(sys.argv[1] if len(sys.argv) > 1 else find_package_resource(self.CONFIG_FILE)) - try: - self.log(f"Using config file {config_file}", OUTPUT_INFO) - self._config_store = JsonStore(config_file, indent=4) - self._config = dict(self._config_store) - return config_file - except Exception as e: - self.log(f"Failed to load config {config_file}: {e}", OUTPUT_ERROR) - sys.exit(1) - - def save_config(self): - for k, v in self._config.items(): - self._config_store.put(k, **v) - - def config(self, setting, default=None): - try: - if "/" in setting: - cat, key = setting.split("/") - return self._config[cat].get(key, default) - else: - return self._config[setting] - except KeyError: - self.log(f"Missing configuration option {setting}", OUTPUT_ERROR) diff --git a/katrain/core/utils.py b/katrain/core/utils.py index 0203f2e..3d80d7c 100644 --- a/katrain/core/utils.py +++ b/katrain/core/utils.py @@ -5,8 +5,6 @@ from typing import List, Tuple, Callable from kivy.lang import Observable import gettext -from kivymd.uix.textfield import MDTextField - from katrain.gui.style import DEFAULT_FONT try: @@ -14,14 +12,6 @@ try: except: import importlib_resources as pkg_resources -OUTPUT_ERROR = -1 -OUTPUT_KATAGO_STDERR = -0.5 -OUTPUT_INFO = 0 -OUTPUT_DEBUG = 1 -OUTPUT_EXTRA_DEBUG = 2 - -MODE_PLAY, MODE_ANALYZE = "play", "analyze" - def var_to_grid(array_var: List[Number], size: Tuple[int, int]) -> List[List[Number]]: """convert ownership/policy to grid format such that grid[y][x] is for move with coords x,y""" @@ -113,7 +103,3 @@ class Lang(Observable): DEFAULT_LANGUAGE = "en" i18n = Lang(DEFAULT_LANGUAGE) - - -def switch_lang(lang): - i18n.switch_lang(lang) diff --git a/katrain/fonts/digital-7.ttf b/katrain/fonts/digital-7.ttf deleted file mode 100644 index 5dbe6f908239d00a9f88c335df3efb9261ecc3cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34360 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: background_radius: self.height/3.5 -: +: background_color: BOX_BACKGROUND_COLOR : @@ -695,7 +695,7 @@ notebox.size_hint_y = int(args[1]['notes'])*0.66+1e-9 notebox.opacity = int(args[1]['notes']) options_height: root.tab_option_height - BGMDBoxLayout: + BGBoxLayout: background_color: BOX_BACKGROUND_COLOR orientation: 'vertical' ScrollableLabel: @@ -895,9 +895,9 @@ StyledSpinner: id: player_subtype value_refs: [] - on_text: root.set_player() + on_text: root.update_global_player_info() -: +: orientation: 'vertical' size_hint_y: None spacing: 3*CP_SPACING @@ -1023,7 +1023,7 @@ ScreenManager: Screen: name: 'gui' - BGMDBoxLayout: + BGBoxLayout: background_color: BACKGROUND_COLOR MDBoxLayout: orientation: 'vertical' diff --git a/katrain/gui/ai_settings.py b/katrain/gui/ai_settings.py index 56e1fbd..77c73dd 100644 --- a/katrain/gui/ai_settings.py +++ b/katrain/gui/ai_settings.py @@ -4,7 +4,7 @@ from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.gridlayout import MDGridLayout from kivymd.uix.label import MDLabel -from katrain.core.utils import OUTPUT_DEBUG, OUTPUT_ERROR +from katrain.core.constants import OUTPUT_ERROR, OUTPUT_DEBUG from katrain.gui.kivyutils import SizedButton, LightHelpLabel, ScaledLightLabel, StyledSpinner from katrain.gui.popups import QuickConfigGui, ConfigPopup, InputParseError diff --git a/katrain/gui/badukpan.py b/katrain/gui/badukpan.py index 6a1af5e..1f6cb4b 100644 --- a/katrain/gui/badukpan.py +++ b/katrain/gui/badukpan.py @@ -14,7 +14,8 @@ from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.floatlayout import MDFloatLayout from kivymd.uix.menu import MDDropdownMenu, RightContent -from katrain.core.utils import OUTPUT_DEBUG, evaluation_class, i18n, MODE_PLAY +from katrain.core.utils import evaluation_class, i18n +from katrain.core.constants import OUTPUT_DEBUG, MODE_PLAY from katrain.core.game import Move from katrain.gui.kivyutils import draw_circle, draw_text from katrain.core.utils import var_to_grid @@ -50,9 +51,12 @@ class BadukPanWidget(Widget): self.stone_size = 0 self.active_pv_moves = [] self.animating_pv = None - self.redraw_board_contents_trigger = Clock.create_trigger(self.draw_board_contents) self.last_mouse_pos = (0, 0) Window.bind(mouse_pos=self.on_mouse_pos) + + self.redraw_board_contents_trigger = Clock.create_trigger(self.draw_board_contents) + self.redraw_trigger = Clock.create_trigger(self.redraw) + self.bind(size=self.redraw_trigger) Clock.schedule_interval(self.animate_pv, 0.1) # stone placement functions @@ -132,7 +136,7 @@ class BadukPanWidget(Widget): self.draw_hover_contents() # remove ghost # drawing functions - def on_size(self, *_args): + def redraw(self,*_args): self.draw_board() self.draw_board_contents() @@ -276,7 +280,7 @@ class BadukPanWidget(Widget): Rectangle(pos=(self.gridpos_x[x] - rsz / 2, self.gridpos_y[y] - rsz / 2), size=(rsz, rsz)) policy = current_node.policy - if not policy and current_node.parent and current_node.parent.policy and katrain.game.last_player.ai and katrain.game.next_player.ai: + if not policy and current_node.parent and current_node.parent.policy and katrain.last_player_info.ai and katrain.next_player_info.ai: policy = current_node.parent.policy # in the case of AI self-play we allow the policy to be one step out of date pass_btn = katrain.board_controls.pass_btn diff --git a/katrain/gui/controlspanel.py b/katrain/gui/controlspanel.py index 306ba7f..3dad15c 100644 --- a/katrain/gui/controlspanel.py +++ b/katrain/gui/controlspanel.py @@ -7,7 +7,8 @@ from kivy.uix.popup import Popup from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.floatlayout import MDFloatLayout -from katrain.core.utils import MODE_PLAY, MODE_ANALYZE, i18n +from katrain.core.utils import i18n +from katrain.core.constants import MODE_PLAY, MODE_ANALYZE class PlayAnalyzeSelect(MDFloatLayout): @@ -38,9 +39,9 @@ class ControlsPanel(BoxLayout): Clock.schedule_interval(self.update_timer, 0.07) def update_players(self, *_args): - for player, info in self.katrain.game.players.items(): - self.players[player].player_type = i18n._(info.player_type) - self.players[player].player_subtype = i18n._(info.player_subtype) + for bw, player_info in self.katrain.players_info.items(): + self.players[bw].player_type = i18n._(player_info.player_type) + self.players[bw].player_subtype = i18n._(player_info.player_subtype) def set_status(self, msg, at_node=None): self.status_msg = msg @@ -59,11 +60,11 @@ class ControlsPanel(BoxLayout): self.status.text = "" self.status_node = None - last_player_was_ai_playing_human = game.last_player.ai and game.next_player.human + last_player_was_ai_playing_human = katrain.last_player_info.ai and katrain.next_player_info.human self.active_comment_node = current_node if katrain.play_analyze_mode == MODE_PLAY and last_player_was_ai_playing_human: - if game.next_player.being_taught and current_node.children and current_node.children.auto_undo: + if katrain.next_player_info.being_taught and current_node.children and current_node.children.auto_undo: self.active_comment_node = current_node.children[-1] elif current_node.parent: self.active_comment_node = current_node.parent @@ -71,7 +72,7 @@ class ControlsPanel(BoxLayout): hints = katrain.analysis_controls.hints.active info = "" if current_node.move and not current_node.is_root: - info = self.active_comment_node.comment(teach=game.players[self.active_comment_node.player].being_taught, hints=hints) + info = self.active_comment_node.comment(teach=katrain.players_info[self.active_comment_node.player].being_taught, hints=hints) if self.active_comment_node.analysis_ready: self.stats.score = self.active_comment_node.format_score() or "" @@ -96,7 +97,7 @@ class ControlsPanel(BoxLayout): self.last_timer_update = (current_node, now) byo_len = max(1, self.katrain.config("timer/byo_length")) byo_num = max(1, self.katrain.config("timer/byo_periods")) - player = self.katrain.game.next_player + player = self.katrain.next_player_info ai = player.ai if not self.timer.paused and not ai: if last_update_node == current_node and not current_node.children: diff --git a/katrain/gui/kivyutils.py b/katrain/gui/kivyutils.py index 01d0264..07f9506 100644 --- a/katrain/gui/kivyutils.py +++ b/katrain/gui/kivyutils.py @@ -14,6 +14,7 @@ from kivy.properties import ( ObjectProperty, ) from kivy.uix.behaviors import ToggleButtonBehavior, ButtonBehavior +from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button from kivy.uix.checkbox import CheckBox from kivy.uix.filechooser import FileChooserLayout, FileChooserListLayout @@ -170,7 +171,7 @@ class CircleWithText(Widget): min_size = NumericProperty(50) -class BGMDBoxLayout(MDBoxLayout, BackgroundMixin): +class BGBoxLayout(BoxLayout, BackgroundMixin): pass @@ -195,11 +196,17 @@ class StyledSpinner(Spinner): except (ValueError, IndexError): return 0, "", "" + def select_key(self, key): + try: + ix = self.value_refs.index(key) + self.text = self.values[ix] + except: + pass + def i18n_values(self, *_args): if self.value_refs: selected = self.selected[0] self.values = [i18n._(ref) for ref in self.value_refs] - print(self.selected, self.values, self.value_refs) self.text = self.values[selected] self.font_name = i18n.font_name self.update_dropdown_props() @@ -221,6 +228,18 @@ class StyledSpinner(Spinner): item.font_name = self.font_name +class PlayerSetupBlock(MDBoxLayout): + players = ObjectProperty(None) + INSTANCES = [] + + def __init__(self, **kwargs): + super().__init__(**kwargs) + PlayerSetupBlock.INSTANCES.append(self) + + def update_players(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) + + class PlayerSetup(MDBoxLayout): player = OptionProperty("B", options=["B", "W"]) @@ -237,19 +256,20 @@ class PlayerSetup(MDBoxLayout): self.player_subtype_label.text = i18n._("aistrategy") self.player_subtype.value_refs = MDApp.get_running_app().gui.ai_strategies # TODO: self.player_subtype.text = self.player_subtype.values[0] - self.set_player() + self.update_global_player_info() @property - def player_def(self): + def player_type_dump(self): return {"player_type": self.player_type.selected[1], "player_subtype": self.player_subtype.selected[1]} - def set_player(self): + def update_widget(self, player_type, player_subtype): + self.player_type.select_key(player_type) # should trigger setup options + self.player_subtype.select_key(player_subtype) # should trigger setup options + + def update_global_player_info(self): katrain = MDApp.get_running_app().gui - game = katrain and katrain.game - if game: - game.players[self.player].update(**self.player_def) - katrain.controls.update_players() - katrain.update_state() + if katrain.game and katrain.game.current_node: + katrain.update_player(self.player, **self.player_type_dump) class PlayerInfo(MDBoxLayout, BackgroundMixin): @@ -260,7 +280,7 @@ class PlayerInfo(MDBoxLayout, BackgroundMixin): active = BooleanProperty(True) -class Timer(BGMDBoxLayout): +class Timer(BGBoxLayout): state = ListProperty([30, 5, 1]) diff --git a/katrain/gui/popups.py b/katrain/gui/popups.py index e006044..7618eaf 100644 --- a/katrain/gui/popups.py +++ b/katrain/gui/popups.py @@ -12,7 +12,7 @@ from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.selectioncontrol import MDCheckbox from kivymd.uix.textfield import MDTextField -from katrain.core.utils import OUTPUT_DEBUG, OUTPUT_ERROR +from katrain.core.constants import OUTPUT_ERROR, OUTPUT_DEBUG from katrain.core.engine import KataGoEngine from katrain.core.game import Game, GameNode from katrain.gui.kivyutils import StyledSpinner @@ -163,7 +163,7 @@ class ConfigTimerPopup(QuickConfigGui): def update_config(self, save_to_file=True): super().update_config(save_to_file=save_to_file) - for p in self.katrain.game.players.values(): + for p in self.katrain.players_info.values(): p.periods_used = 0 self.katrain.controls.timer.paused = True self.katrain.game.current_node.time_used = 0 @@ -183,6 +183,9 @@ class NewGamePopup(QuickConfigGui): self.katrain.engine.restart() self.katrain("new-game") + # for bw, player_widget in self.nav_drawer_contents.player_setup.players.items(): + # self.players[bw].update(**player_widget.player_def) + class ConfigPopup(QuickConfigGui): def __init__(self, katrain, popup: Popup, config: Dict, ignore_cats: Tuple = (), **kwargs): diff --git a/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo index df122724f1af04d814d4bc5c35d0e20cf0417ac7..bf632aacd49c6a089420339d0ea0ba56a5dcb19c 100644 GIT binary patch delta 3545 zcmb`{Ylt1?9mnx!bxl%D*5;x%n&_k0B$~MC<&E8RgSP~uVz#C#25ruqGtb#G-PxJb znK`>Xu`m*Br4}W!hJuY3D3zkN(5`(Uy~GOQ3mZ~IYLOZcePKjF6mM<4e19{~#-tD_ zZNlb!=6UA1{Qu8o-dq3DXnAnS;2y)jl>aOEfA5JZ8MAQyXD;S(5#=x8Io^x$9LnFq zCHOu3BHoVtnLYdr;r)0jK8AY#2k(A7*_hHC z8!E6SF2e$qz>iTmJd9t!N05oki+}OO5Ew+--nBt-~7rq*oRu8{iui!qB|Ik zJfD}EcsXjKHK=wQeErqFemkoDBx>9e`7^uuQU9Nz>dYhjD5KvY$(pB74W2~}{32@U zUPop6HfoDLMs3MyRI0odtCiq~SLRyOcsF^QsFj%T<^CzG{~#5+sF;U$peDQso`4G5{}?19K-M9G(L)N;Xd3;w7Pybvut~@f!f-SP=O6Hs9c0J zEzRjXDC0G#iAGT?aSalKxyc)$2I`}h^fugyKfxPt9)rkR@M(M;|Aae<`UU(3C-g~N ze1Xj zDzH%;z|Gz(Q4?H+8fPnNg|7GI2C82h6=-@k8>S9Fq(T|piJS1JIP;x_SIq97*B&TG zLe~y@abbdJRQ%c3I9`gL*I zMdO{qg;gnyqgGX)x6;hTX`WL(^WOZ6Za!+7j*GiTOy!GyI$t_G<>B&Y)B38psb|hy zaNg{$1=|M)vngc~+G+V|O}bZJDsn|pC=^CEM}>@ODEfs!@M?PNOTa@&l8 zoOyyKC0lfyZ4{l%<()JR8?ElDeL^tBDO+EM4-utjRS zE(zjjr}Hx;F375`E*w`~=E`9*NxQj13JN#gw?Vsbb)(fT3CDv;x7xO|pjAX^V$*g# za~fo!jdI(L;@E}5W~@r1p)J~x*tNELP%nF-{btgeY%(N$V>izFR@rWBSjAcDY!K-* z1J+r^0a>ZZv9h&e^$Mijx>?k=-D+#>RKQ79SoIRt;V=>>BXrez1XF1g+O#ElDSj8S3UVvvn9+jM1+){PxAsM7_mjqdp=Hd+CA3U5okC5I2=k!SHgFHh)Li%C8& zxt;E~grMiHUv68SG^a`dr@gs5LCbtybuk+3mCJTC(_X@d?1+IlQWx0jrLA5beUFO{ W_e+;KR+Dh{sU>3rv!lzNIPp`=rVbte delta 1745 zcmZwGT}V_x7{>82*G$dt{8$Y$6FWuh8&{$m6{rzou-*3iP>Ef`Rd^p&z$B`Mj~IlXQS;|91pQYm8IGZ>ZxU%J z^Gwu(F8e@{^#Cd{H|jYLlDX+XRn~3q510C~1wjM|BEWR9t__Zv`w+mPbSc~ph{s2v<2TfqS8!8b#|bRObGQemF#|V|O%j%)5;%=|S-oBw=`;p0 z8^_Uw^QZ)}xoA8ev#=4JIDpYOiu}wZ7wzCXOvA6(f-#)e9lU^J=%N~Z9Y1jpy}xOk zp)o)iWf;qT$_9La8(+SkX_n3?`s09KjQwc<%UQVa&C)s{F>L{{MM^k`$XUb8DRoL-k zsQ1sb+Z$chepKc|s08k!7JP_1@u}?x@Qo>fFw_o2qZUX&9Z4E$UM?z5zU>#H3f`x2 zegB7O=q0N~Vw+avXL`6O&`r$2QPhH;a2d{G0M4Nj_-^})m_gq^ZmEzgRAMgF*6%_k zR)%GMG%9FFH)?@ORNz|FmN(jdD{7(_m1r00`75Z3u44g?#QA~)hyD6;gEsa}1Ua`g zx*MupRnO*`nt+id&l=WsK(*T4;yp%x}(?o`QAE9{Q4H7 ZoRNE%o+_>MoUBeR_B1v5)+Ijj{{s-Luaf`( diff --git a/katrain/i18n/locales/en/LC_MESSAGES/katrain.po b/katrain/i18n/locales/en/LC_MESSAGES/katrain.po index 746e53a..09c403a 100644 --- a/katrain/i18n/locales/en/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/en/LC_MESSAGES/katrain.po @@ -311,7 +311,7 @@ msgstr "" msgid "Engine died unexpectedly" msgstr "" "Engine died unexpectedly without sending output, possibly due to out of " -"memory: {e}" +"memory: {error}" #. AI names, help etc msgid "strength:kyu" @@ -320,7 +320,7 @@ msgstr "k" msgid "strength:dan" msgstr "d" -msgid "ainame:default" +msgid "ai:default" msgstr "KataGo" msgid "aihelp:default" @@ -328,7 +328,7 @@ msgstr "" "Full strength KataGo AI. Strength is mainly affected by `max_visits` and " "`model` in the general settings `engine` section." -msgid "ainame:jigo" +msgid "ai:jigo" msgstr "KataJigo" msgid "aihelp:jigo" @@ -336,7 +336,7 @@ msgstr "" "Will try to win by a set amount of points (default 0.5), without further " "restrictions." -msgid "ainame:jigo" +msgid "ai:jigo" msgstr "KataJigo" msgid "aihelp:jigo" @@ -344,7 +344,7 @@ msgstr "" "Will try to win by a set amount of points (default 0.5), without further " "restrictions." -msgid "ainame:scoreloss" +msgid "ai:scoreloss" msgstr "Score Loss" msgid "aihelp:scoreloss" @@ -352,7 +352,7 @@ msgstr "" "Plays moves that lead to more points lost with lower probability. Likely to " "play more varied/weaker with higher visits settings." -msgid "ainame:policy" +msgid "ai:policy" msgstr "Policy" msgid "aihelp:policy" @@ -360,3 +360,59 @@ msgstr "" "Plays the top move from the policy network, without any reading. Strength is" " mainly affected by `model` in engine settings. The opening moves setting " "affects how many moves in the opening are more random." + +msgid "ai:p:weighted" +msgstr "Policy Weighted" + +msgid "aihelp:p:weighted" +msgstr "" +"Plays moves according to policy probability, with `weaken_fac` influencing " +"how much more likely weaker moves are played. A high negative value plays " +"like the `Policy` AI.`pick_override` determines when top move is chosen " +"without randomness, and `lower_bound` determines the lower bound policy " +"value that is allowed." + +msgid "ai:p:pick" +msgstr "Blinded Policy" + +msgid "aihelp:p:pick" +msgstr "" +"Picks `pick_n + pick_frac * ` at random and plays the" +" best one. For `pick_frac=1` plays like the `Policy` AI. Plays top move if " +"policy value is above `pick_override` to avoid obvious mistakes." + +msgid "ai:p:local" +msgstr "Local Response Style" + +msgid "aihelp:p:local" +msgstr "" +"Picks `pick_n + pick_frac * ` weighted towards the " +"last move and plays the best one. Plays top move if policy value is above " +"`pick_override` to avoid obvious mistakes." + +msgid "ai:p:tenuki" +msgstr "Tenuki Style" + +msgid "aihelp:p:tenuki" +msgstr "" +"Picks `pick_n + pick_frac * ` weighted away from the " +"last move and plays the best one. Plays top move if policy value is above " +"`pick_override` to avoid obvious mistakes." + +msgid "ai:p:influence" +msgstr "Influential Style" + +msgid "aihelp:p:influence" +msgstr "" +"Picks moves biased above the `threshold` line and plays the best " +"one.Increase `line_weight` to penalize moves near the edge more. Stops " +"strategy after the 'endgame' fraction of the board is filled." + +msgid "ai:p:territory" +msgstr "Respond Locally" + +msgid "aihelp:p:territory" +msgstr "" +"Picks moves biased below the `threshold` line and plays the best " +"one.Increase `line_weight` to penalize moves near the center more. Stops " +"strategy after the 'endgame' fraction of the board is filled." diff --git a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.mo index eead6a6e926f876fb922064162b72e4061012671..8c6c1e5aa1e578a754f3338ae53da653847fd4a7 100644 GIT binary patch delta 3572 zcmbu9dx#y?9mkKatT9HDXf$c6IaYDCu2F*|xQ+2`Ocj$DAJDGuoqO-Od&ixfxy;Pn zbpv&}NI_dDnji|=S|L~pp^DK!e1jS*SSsQRA1!DIiej|=LyTJb`OciHB$_tWPe9qU+#XIOgX!K{>V_ z9tk%>1+Wz=hF9Tq_y)v~*$%O3c0%d;cq4wS8<@b8|15o>)hSK{AEciD&7^L76sJXmQq%$B{GV`F; zkAqTtI#epph5XDV3@X``P$e4m^C`&B+{qxl8=)M(A4>1zGpN5lw)us>`GvRPfyj5j zY48Im!~cYeaDTibS!S;1LMVq%W>92HynF?e!8MSd8D`M=2+D48DEXJiHzUx&-$N8L(-#K}GzMpT7a6Xb04}&%FE)tjXX}42aALo@YQATn?pw1yn}X6kad{WvB&} z>J&=x6qKU%P+fix9EA@-)zY$A*K#pj3onJM;63mpxDy@==aD`+uoUW+oD2J5aV;OG z@$oA-2p@*3<;Py$hZh6Pm%{n531#p`h;DNSR0i*ZC&I_z4e(v~Cpd(cPr_-W>lnBV z-VV1zN?Vw9M^v6oK}Gayh;4H>lz~l98FlCu@355 z-U8*wZ=np`<=6iRb#4oko+thMd8qv_dHFw}0(<`$@~`IEg+QLpqE%(6A1;PVpdt_9 z{;=bjdHFaz2>CCdy8R}oKsG@+_K2Tv^L!anY4eWf_G2&c4-En-`T#2RpFkP@0!rZl z3#%@l4V8g@KOcY>F+YFd=D}&3_A3UPt`&5n+yvp^_2Eb&b_T<^6?I+QaMd(Q8bMTj zcEZMJ^_9E0I~w-B(=^PJbh4UGxNxMMyJk5{qOeiQvqqA-D9JL!Z5MT9dc#M3^M`gb zSFUshdnWzVoAtA=On){1+PoL_T-f~YzCTPaE)DWvMPh`XD#(>pe0dl|c5OZxIdg@} zI!WBLmnqa}(wrZKanm*J>dO5q%V77ix7uT`=|%0&tW~@y%(4x?oBeV@;xapyjJwR% z!yrRNsm_+BIASS+jX! zJ1!2QaGmoOVi%<4QP&)iEOo^qyiYor&GIzJ-N>X3TDhw>^}Dz^5{$Wi+e(8*9wxC( zT9xG_NSijyY%7c+*IZ;)e>03aMV%;j*ZxZw1z~=VI2taNw~FMu1yX!_BsF!`aBNSp z<%i<8Keo%_?pPgjWFc}RG)Y;vu33w((T{LOS&AJzQR|4J}y&7Cpd!B9c2-}$U%|pspR1H-%(nl!VGc9J2I!%4SyC)k+{lzmd;MR4hGJ?X~0Xr-dXm8P<%v}nu4-Mc++ RbHCK`kC<=mDtUWs+)QOsr>!W6uY$#@q%IEIP%5|i+~tUc{bq%OW4%>PgDuEE{fH10%e$>8uHa}+buTcBHqT>EQALlzCX(~WE z>Y%l#%8QUauFTe}QGxd&$-5R*!pBh^>p*qrqKyY^{UIvuGgM&_RNPM((9N_h%-KQ| zyJML5A+O0Lp$^VKRhWxxbtPscD&bmGW&3Tu6?I^{t#_iH??Ih=!$<#>@ogsb;8RrK z2rA$QRE5*1isxcD>F<3_lsgU>M+C$R%PystqF;uBm?HJLb#y%Iux3Ch2P_3Rr{VJk~szf}fgVIpzt5MGtq2g?{@ix@{oi^Wq zDy$jP_4{w*hL1bXMS=QoGY+9DpTcPTX3p6BEXFcFkNNl$)q!=Csl>LR#ua8QMlo(Q zo3KU|9pXlTT2QS&hB~+%72qsVyz55o@3Zj$Rx=*KaCTzVaL{ukD%|AF8UF0O;temP LMuxxpdt(0roy(Dg diff --git a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po index ad0e281..5352582 100644 --- a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po @@ -398,3 +398,87 @@ msgstr "k" #. TODO msgid "strength:dan" msgstr "d" + +#. TODO +msgid "aihelp:p:weighted" +msgstr "" +"Plays moves according to policy probability, with `weaken_fac` influencing " +"how much more likely weaker moves are played. A high negative value plays " +"like the `Policy` AI.`pick_override` determines when top move is chosen " +"without randomness, and `lower_bound` determines the lower bound policy " +"value that is allowed." + +#. TODO +msgid "aihelp:p:pick" +msgstr "" +"Picks `pick_n + pick_frac * ` at random and plays the" +" best one. For `pick_frac=1` plays like the `Policy` AI. Plays top move if " +"policy value is above `pick_override` to avoid obvious mistakes." + +#. TODO +msgid "ai:p:influence" +msgstr "Influential Style" + +#. TODO +msgid "ai:p:local" +msgstr "Respond Locally" + +#. TODO +msgid "aihelp:p:tenuki" +msgstr "" +"Picks `pick_n + pick_frac * ` weighted away from the " +"last move and plays the best one. Plays top move if policy value is above " +"`pick_override` to avoid obvious mistakes." + +#. TODO +msgid "ai:scoreloss" +msgstr "Score Loss" + +#. TODO +msgid "aihelp:p:influence" +msgstr "" +"Picks moves biased above the `threshold` line and plays the best " +"one.Increase `line_weight` to penalize moves near the edge more. Stops " +"strategy after the 'endgame' fraction of the board is filled." + +#. TODO +msgid "ai:default" +msgstr "KataGo" + +#. TODO +msgid "ai:p:tenuki" +msgstr "Tenuki Style" + +#. TODO +msgid "ai:p:pick" +msgstr "Blinded Policy" + +#. TODO +msgid "ai:p:weighted" +msgstr "Policy Weighted" + +#. TODO +msgid "ai:policy" +msgstr "Policy" + +#. TODO +msgid "ai:jigo" +msgstr "KataJigo" + +#. TODO +msgid "aihelp:p:local" +msgstr "" +"Picks moves biased below the `threshold` line and plays the best " +"one.Increase `line_weight` to penalize moves near the center more. Stops " +"strategy after the 'endgame' fraction of the board is filled." + +#. TODO +msgid "aihelp:p:territory" +msgstr "" +"Picks moves biased below the `threshold` line and plays the best " +"one.Increase `line_weight` to penalize moves near the center more. Stops " +"strategy after the 'endgame' fraction of the board is filled." + +#. TODO +msgid "ai:p:territory" +msgstr "Respond Locally" diff --git a/katrain/i18n/locales/nl/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/nl/LC_MESSAGES/katrain.mo index 9de209e986aa98e832850832a9d0a2a28bf18259..189c2aead1e17a51c36175260979529863ac5359 100644 GIT binary patch delta 3572 zcmbu9dyEy;9mkKTP=s2bVxcM?TT`@>RcK4>qO_uwM~$#uwT-X6bMHNO@3^xw*O}Q} zmOmUx|EQ#ishTDRUm+!E8;mw<+K`mC0mZb@m>7HnAOC2GMq7f`XiXq~zBA`)c(t@_ z?#}0&-#O>^K4<&IPcJRroOQ~t4Sy;BXY;@HWX+7ZY|0m$$?$UKbKq*vHawU4dN>Pi zf-~S#ke_*m&*|`a_!am%)cX6L2jFSO6z23VRSM?9FSB6*JQMc9>97w<(XDVc9QN~{ zLpgRYJOgfq3Sb*l3@^i}a1X?gc^hKW?1R$xaVam1nanP2oXKYzJPT^Wd?<$&Lw@Ee zK62<*ql!z62_jKZN|u3O*{?bxYImw$l= z;5l$RX?qa91}SY})}pPf1yn?LL2R3iPzHVnm4R(uzRUAvsNUEMmCAp>b?_5-1I$R* zGw|>5S@yqoP+`L_#6u#5$2t6$JZ+ZSDsZlxC+W(Ka{~6 zp-Sc;)iAe1)wY1&fE%C!*$TD)Pf&q83sG%$!&$oj`xxlpBnopLoDOxM2P!k)hq?{R z{Cv5euYs!l^-!6Mp&Ypr%CWn>d?S>;tzP~|&z(^HXI@|+z5(UPdr*cyf>*+WP^DN# z0p&;^R3tY*8EQbSCs60^fYS2|KfecR|3)u=6w)5%_ves*HO~$NdO%)z_Dzl3t^0Z66IX3s72R#Xu^hCqrQhf39i zpZ^)^;L}i!J`a_FxBUDa_#@^A=S}oZ-g;8e+jOm9B+5+?_TCl_CSs>Ij9bx&iyN+* zMoA-xs$nN=3{|7t#Un#ucbukSo}}Z|bj*c=?c6oXSrUbfQl2%E)I~{_A#S^4D+bb7lc{nVTFv(HU`KL5hJ7j<2jI5_3usl|_jJXoF>VU>bhS;d!!L1g>$ z@yMBNid?hDtT{4_Iz=5Tch~+y7zJUTKpYJh%UebA{{>PUJ(8L_ zYaq54*>a%x?YHe^@yKu;b7UcMgEUE5x1}{3tMkXGQ_7r|6Fv@Nq^^_^kX7Aslj9j<3s(-DJh_ z+?EsWvLl+TEUyA7sAPi|p&7=5<%O-v+)0yqP!FRpA75a{!n|#3V~#q;1FfJ@v)zYS zhuYk-;gLqWyaYTGLoOP(fZTsZHdAm@(*w!O{hZhRpa1{dxxU)}yf`|Op3r0X zYv8+uZ(yBz#)Q`YcN5Jr`dL_O4Pzet4ot^en1(~>!U;^l_n3-PcK)~ZFFM9VO$w_O zARCi0fSDM?jaY{YbPBzA-u63DiCxDGyo)N}8LEcQ=*DlT`+r~(&ZG8O!8GU--P#ZR&;x{27OluP7uYq<3_?RnP z^eAqi0{5W;Jw^S<#_i6CA?={DN(`jQ25;YRoA5sU`er?Q2)suU_3suK1My7Axy+!EW$BdeH5s~7EzBN!MB!32FB6P zvF2fwD)Q4%paRrU1#EvGs)914C{u-6f5P_9U?u&CZ!qZUkLy0^_78q{_qe+kJ+Z-s I?1PE_0Cvic=Kufz diff --git a/katrain/i18n/locales/nl/LC_MESSAGES/katrain.po b/katrain/i18n/locales/nl/LC_MESSAGES/katrain.po index c747d4c..0487226 100644 --- a/katrain/i18n/locales/nl/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/nl/LC_MESSAGES/katrain.po @@ -430,3 +430,87 @@ msgstr "k" #. TODO msgid "strength:dan" msgstr "d" + +#. TODO +msgid "aihelp:p:weighted" +msgstr "" +"Plays moves according to policy probability, with `weaken_fac` influencing " +"how much more likely weaker moves are played. A high negative value plays " +"like the `Policy` AI.`pick_override` determines when top move is chosen " +"without randomness, and `lower_bound` determines the lower bound policy " +"value that is allowed." + +#. TODO +msgid "aihelp:p:pick" +msgstr "" +"Picks `pick_n + pick_frac * ` at random and plays the" +" best one. For `pick_frac=1` plays like the `Policy` AI. Plays top move if " +"policy value is above `pick_override` to avoid obvious mistakes." + +#. TODO +msgid "ai:p:influence" +msgstr "Influential Style" + +#. TODO +msgid "ai:p:local" +msgstr "Respond Locally" + +#. TODO +msgid "aihelp:p:tenuki" +msgstr "" +"Picks `pick_n + pick_frac * ` weighted away from the " +"last move and plays the best one. Plays top move if policy value is above " +"`pick_override` to avoid obvious mistakes." + +#. TODO +msgid "ai:scoreloss" +msgstr "Score Loss" + +#. TODO +msgid "aihelp:p:influence" +msgstr "" +"Picks moves biased above the `threshold` line and plays the best " +"one.Increase `line_weight` to penalize moves near the edge more. Stops " +"strategy after the 'endgame' fraction of the board is filled." + +#. TODO +msgid "ai:default" +msgstr "KataGo" + +#. TODO +msgid "ai:p:tenuki" +msgstr "Tenuki Style" + +#. TODO +msgid "ai:p:pick" +msgstr "Blinded Policy" + +#. TODO +msgid "ai:p:weighted" +msgstr "Policy Weighted" + +#. TODO +msgid "ai:policy" +msgstr "Policy" + +#. TODO +msgid "ai:jigo" +msgstr "KataJigo" + +#. TODO +msgid "aihelp:p:local" +msgstr "" +"Picks moves biased below the `threshold` line and plays the best " +"one.Increase `line_weight` to penalize moves near the center more. Stops " +"strategy after the 'endgame' fraction of the board is filled." + +#. TODO +msgid "aihelp:p:territory" +msgstr "" +"Picks moves biased below the `threshold` line and plays the best " +"one.Increase `line_weight` to penalize moves near the center more. Stops " +"strategy after the 'endgame' fraction of the board is filled." + +#. TODO +msgid "ai:p:territory" +msgstr "Respond Locally" diff --git a/katrain/popups.kv b/katrain/popups.kv index 6f68b76..ce7dbcf 100644 --- a/katrain/popups.kv +++ b/katrain/popups.kv @@ -31,7 +31,6 @@ : font_size: INPUT_FONT_SIZE - on_text: print(self.size,self.font_size) : color: WHITE