From 6ae2ac162a428d58e4668343e2f5e8833a724aa6 Mon Sep 17 00:00:00 2001 From: Sander Land Date: Wed, 22 Apr 2020 23:35:39 +0200 Subject: [PATCH] stuff --- TODO | 3 ++- config.json | 1 + game.py | 11 ++++++++++- gui/badukpan.py | 5 +---- gui/controls.py | 30 +++++++++++------------------- gui/popups.py | 2 +- katrain.kv | 16 +++++++++------- katrain.py | 3 +++ 8 files changed, 38 insertions(+), 33 deletions(-) diff --git a/TODO b/TODO index fddba1f..2d9c13a 100644 --- a/TODO +++ b/TODO @@ -12,10 +12,11 @@ [] more AI modes (noisy policy? heavy balance? jigo?) [] split feedback in box vs top moves [] box to label ? split in status and comment? - +[] limit below board buttons somehow to not be too big wont do [] Self-play tournaments? [] Multi engine (detect all req. analysis in analysis[engine] fn) +[] graph wonky on branch switch -> check in children &c. diff --git a/config.json b/config.json index 7c8fae1..9fd5927 100644 --- a/config.json +++ b/config.json @@ -25,6 +25,7 @@ "balance_randomize_score": 1, "balance_max_lost": 5, "balance_min_visits": 20, + "noise_strength": 0.05, "eval_off_show_last": 3 }, "board_ui": { diff --git a/game.py b/game.py index 15a46e2..0948dc9 100644 --- a/game.py +++ b/game.py @@ -219,6 +219,10 @@ class Game: policy_moves = cn.policy_ranking self.katrain.log(f"Top 5 policy moves are: {policy_moves[:5]}", OUTPUT_DEBUG) aimove = policy_moves[0][0] + elif "noise" in ai_mode and cn.policy: + noise = train_settings["noise_strength"] + policy_moves = [(mv, pol + random.gauss(0, noise)) for mv, pol in cn.policy_ranking] + aimove = max(policy_moves, key=lambda mp: mp[1])[0] elif "balance" in ai_mode and candidate_ai_moves[0]["move"] != "pass": # don't play suicidal to balance score - pass when it's best sign = cn.player_sign(cn.next_player) # TODO check sel_moves = [ # top move, or anything not too bad, or anything that makes you still ahead @@ -233,9 +237,14 @@ class Game: ) ] aimove = Move.from_gtp(random.choice(sel_moves)["move"], player=cn.next_player) # TODO: could be weighted towards worse + elif "jigo" in ai_mode and candidate_ai_moves[0]["move"] != "pass": + sign = cn.player_sign(cn.next_player) # TODO check + jigo_move = min(candidate_ai_moves, key=lambda move: abs(sign * move["scoreLead"] - 0.5)) + print("NP sign",sign,"JIGO MOVE",jigo_move) + aimove = Move.from_gtp(jigo_move["move"], player=cn.next_player) else: if "default" not in ai_mode: - self.katrain.log(f"Unknown AI mode {ai_mode}, using default.", OUTPUT_INFO) + self.katrain.log(f"Unknown AI mode {ai_mode} or policy missing, using default.", OUTPUT_INFO) aimove = Move.from_gtp(candidate_ai_moves[0]["move"], player=cn.next_player) self.play(aimove) diff --git a/gui/badukpan.py b/gui/badukpan.py index c79b7e0..4de661a 100644 --- a/gui/badukpan.py +++ b/gui/badukpan.py @@ -12,8 +12,6 @@ from game import Move class BadukPanWidget(Widget): - board_color = ListProperty([0.85, 0.68, 0.40]) - def __init__(self, **kwargs): super(BadukPanWidget, self).__init__(**kwargs) self.ui_config = {} @@ -60,7 +58,6 @@ class BadukPanWidget(Widget): katrain.log(f"\nAnalysis:\n{nodes_here[-1].analysis}", OUTPUT_DEBUG) katrain.log(f"\nParent Analysis:\n{nodes_here[-1].parent.analysis}", OUTPUT_DEBUG) katrain.controls.info.text = nodes_here[-1].comment(sgf=True) - katrain.controls.show_evaluation_stats(nodes_here[-1]) self.ghost_stone = None self.draw_board_contents() # remove ghost @@ -82,7 +79,7 @@ class BadukPanWidget(Widget): if innercol: Color(*innercol) - Line(circle=(self.gridpos_x[x], self.gridpos_y[y], stone_size * 0.45 / 0.85), width=0.125 * stone_size) # 1.75 + Line(circle=(self.gridpos_x[x], self.gridpos_y[y], stone_size * 0.475 / 0.85), width=0.1 * stone_size) def eval_color(self, points_lost): colors = self.ui_config["eval_colors"] diff --git a/gui/controls.py b/gui/controls.py index b6c637e..1c5b63a 100644 --- a/gui/controls.py +++ b/gui/controls.py @@ -27,23 +27,6 @@ class Controls(BoxLayout): else: self.select_mode("play") - def show_evaluation_stats(self, node): - if node.analysis_ready: - self.score.text = node.format_score().replace("-", "\u2013") - self.win_rate.text = node.format_win_rate() - move = node.single_move - if move: - self.points_lost.label = f"Point loss {move.player}{move.gtp()}" - else: - self.points_lost.label = f"Point loss" - self.points_lost.text = "" - return - - if node.points_lost is not None: - self.points_lost.text = f"{node.points_lost:.1f}" - else: - self.points_lost.text = f"..." - def player_mode(self, player): return self.player_mode_groups[player].value @@ -71,8 +54,17 @@ class Controls(BoxLayout): ) if current_player_is_human_or_both_robots and not current_node.is_root and move: info += current_node.comment(eval=True, hints=self.hints.active) - if current_player_is_human_or_both_robots: - self.show_evaluation_stats(current_node) + + if current_node.analysis_ready: + self.score.text = current_node.format_score() + self.win_rate.text = current_node.format_win_rate() + if move and current_player_is_human_or_both_robots: # don't immediately hide this when an ai moves comes in + self.points_lost.label = f"Point loss {move.player}{move.gtp()}" + points_lost = current_node.points_lost + self.points_lost.text = f"{current_node.points_lost:.1f}" if points_lost else "..." + else: + self.points_lost.label = f"Point loss" + self.points_lost.text = "" self.graph.update_value(current_node) diff --git a/gui/popups.py b/gui/popups.py index 1269952..86b8041 100644 --- a/gui/popups.py +++ b/gui/popups.py @@ -117,7 +117,7 @@ class ConfigPopup(QuickConfigGui): self.info_label = Label() self.apply_button = StyledButton(text="Apply", on_press=lambda _: self.update_config()) self.save_button = StyledButton(text="Apply and Save", on_press=lambda _: self.update_config(save_to_file=True)) - btn_container = BoxLayout(orientation="horizontal", size_hint=(1, 0.1)) + btn_container = BoxLayout(orientation="horizontal", size_hint=(1, 0.1), spacing=1, padding=1) btn_container.add_widget(self.info_label) btn_container.add_widget(self.apply_button) btn_container.add_widget(self.save_button) diff --git a/katrain.kv b/katrain.kv index e0f8722..7b0db97 100644 --- a/katrain.kv +++ b/katrain.kv @@ -2,10 +2,12 @@ #:import ew kivy.uix.effectwidget -#:set AI_MODES ['Default','Balance','Policy'] +#:set AI_MODES ['Default','Balance','Jigo','Policy','P+Noise'] #:set PLAYER_MODES ['Human', 'Teach','AI:'] #:set BUTTON_COLOR [0.23, 0.30, 0.35, 1] #:set ICON_BUTTON_COLOR [0.71, 0.78, 0.81, 1] +#:set BOARD_COLOR [0.85, 0.68, 0.40,1] +#:set GRAPH_DOT_COLOR [0.85, 0.3, 0.3,1] #:set BLACK [0.05,0.05,0.05,1] #:set WHITE [0.95,0.95,0.95,1] #:set GREY [0.5,0.5,0.5,1] @@ -180,7 +182,7 @@ points: root.line_points width: 1.1 Color: - rgba: BUTTON_COLOR + rgba: GRAPH_DOT_COLOR Ellipse: id: dot pos: root.dot_pos @@ -218,8 +220,8 @@ Label: size_hint: 0.05, 1 BoxLayout: - size_hint: 0.15, 1 - padding: self.size[1]/5 + size_hint: 0.2, 1 + padding: [0.325*self.size[1],0.2*self.size[1]] StyledButton: text: 'Pass' font_size: 0.6*self.size[1] @@ -270,10 +272,10 @@ size_hint: 0.1, 1 on_press: root.katrain('redo',999) Label: - size_hint: 0.07, 1 + size_hint: 0.05, 1 BoxLayout: size_hint: 0.2, 1 - padding: self.size[1]/5 + padding: 0.2 * self.size[1] StyledButton: text: 'AI Move' font_size: 0.6*self.size[1] @@ -493,7 +495,7 @@ size_hint: 1,1 canvas.before: Color: - rgb: root.board_gui.board_color if root.board_gui else (0,0,0) + rgb: BOARD_COLOR Rectangle: pos: self.pos size: self.size diff --git a/katrain.py b/katrain.py index 13c3f0a..51e94d3 100644 --- a/katrain.py +++ b/katrain.py @@ -212,6 +212,7 @@ class KaTrainGui(BoxLayout): "right": ("switch-branch", 1), "left": ("switch-branch", -1), } + print(keycode) if keycode[1] in shortcuts.keys(): shortcut = shortcuts[keycode[1]] if isinstance(shortcut, Widget): @@ -220,6 +221,8 @@ class KaTrainGui(BoxLayout): self(*shortcut) elif keycode[1] == "tab": self.controls.switch_mode() + elif keycode[1] == "spacebar": + self("play", None) # pass elif keycode[1] in ["`", "~", "p"]: self.controls_box.hidden = not self.controls_box.hidden elif keycode[1] in ["up", "z"]: