Skip to content

Commit

Permalink
ui improvements, color improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Sander Land committed Apr 22, 2020
1 parent 751c66a commit 2c4c2a2
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 87 deletions.
13 changes: 8 additions & 5 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@
[x Non square boards
[x] remove fast -> in settings?
[x] Polish graph

[] Multi engine (detect all req. analysis in analysis[engine] fn)
[] Graph is awkward when reviewing. Should we store nodes rather than values? & populate on new game.
[x] BoxLayout padding/spacing use instead of fiddling?

[] Score instead of game end
[] Self-play tournaments?
[] List edit settings/object edit settings?
[] README
[] Release notes
[] more teaching / groups in danger?
[] more AI modes (noisy policy? heavy balance? jigo?)
[] split feedback in box vs top moves
[] box to label ? split in status and comment?


[] BoxLayout padding/spacing use instead of fiddling?
wont do
[] Self-play tournaments?
[] Multi engine (detect all req. analysis in analysis[engine] fn)


3 changes: 1 addition & 2 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@
"ghost_alpha": 0.5,
"top_move_x_alpha": 0.3,
"_child_scale": 0.95,
"eval_colors": [[0.537, 0.129, 0.42], [1, 0, 0], [1,0.5,0], [0.88, 0.70, 0.30], [0.67, 0.95, 0.18], [0.117, 0.588, 0]],
"board_color": [0.85, 0.68, 0.40],
"eval_colors": [[0.447, 0.129, 0.42], [0.8, 0, 0], [0.9,0.4,0.1], [0.85, 0.89, 0.30], [0.67, 0.9, 0.18], [0.117, 0.588, 0]],
"line_color": [0,0,0],
"policy_color": [0,0.2,0.8]
},
Expand Down
4 changes: 2 additions & 2 deletions game.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,10 @@ def analyze_extra(self, mode):
elif mode == "sweep":
board_size_x, board_size_y = self.board_size
analyze_moves = [Move(coords=(x, y), player=cn.next_player) for x in range(board_size_x) for y in range(board_size_y) if (x, y) not in stones]
visits = self.engine.config["visits"] * self.config["sweep_visits_frac"]
visits = int(self.engine.config["visits"] * self.config["sweep_visits_frac"] + 0.5)
self.katrain.controls.set_status(f"Refining analysis of entire board to {visits} visits")
priority = -1_000_000_000
else: # mode=='refine':
else: # mode=='equalize':
analyze_moves = [Move.from_gtp(gtp, player=cn.next_player) for gtp, _ in cn.analysis["moves"].items()]
visits = max(d["visits"] for d in cn.analysis["moves"].values())
self.katrain.controls.set_status(f"Equalizing analysis of candidate moves to {visits} visits")
Expand Down
24 changes: 16 additions & 8 deletions game_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,21 @@ def comment(self, sgf=False, eval=False, hints=False):
text += f"Score: {self.format_score(score)}\n"
if self.parent and self.parent.analysis_ready:
previous_top_move = self.parent.candidate_moves[0]
if sgf or hints and previous_top_move["move"] != single_move.gtp(): # TODO: when to include?
text += f"Predicted top move was {previous_top_move['move']} ({self.format_score(previous_top_move['scoreLead'])})\n"
points_lost = self.points_lost
if sgf and points_lost > 0.5:
text += f"Estimated point loss: {points_lost:.1f}\n"
if sgf or hints:
if previous_top_move["move"] != single_move.gtp():
text += f"Predicted top move was {previous_top_move['move']} ({self.format_score(previous_top_move['scoreLead'])}).\n"
points_lost = self.points_lost
if sgf and points_lost > 0.5:
text += f"Estimated point loss: {points_lost:.1f}\n"
else:
text += f"Move was predicted best move.\n"
if sgf or hints:
policy_ranking = self.parent.policy_ranking
policy_ix = [ix + 1 for (m, p), ix in zip(policy_ranking, range(len(policy_ranking))) if m == single_move]
if not policy_ix or policy_ix[0] != 1:
text += f"Top policy move was {policy_ranking[0][0].gtp()}\n"
if policy_ix:
text += f"Your move was #{policy_ix} according to NN policy\n"
text += f"Move was #{policy_ix[0]} according to policy.\n"
if not policy_ix or policy_ix[0] != 1:
text += f"Top policy move was {policy_ranking[0][0].gtp()}.\n"
if self.auto_undo:
text += "Move was automatically undone."
else:
Expand Down Expand Up @@ -113,6 +116,11 @@ def player_sign(player):
def candidate_moves(self) -> List[Dict]:
if not self.analysis_ready:
return []
if not self.analysis["moves"]:
polmoves = self.policy_ranking
top_polmove = polmoves[0][0] if polmoves else Move(None) # if no info at all, pass
return [{**self.analysis["root"], "pointsLost": 0, "order": 0, "move": top_polmove.gtp()}] # single visit -> go by policy/root

return sorted(
[{"pointsLost": self.player_sign(self.next_player) * (self.analysis["root"]["scoreLead"] - d["scoreLead"]), **d} for d in self.analysis["moves"].values()],
key=lambda d: (d["order"], d["pointsLost"]),
Expand Down
42 changes: 25 additions & 17 deletions gui/badukpan.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget

from constants import OUTPUT_DEBUG
from constants import OUTPUT_DEBUG, OUTPUT_EXTRA_DEBUG
from gui.kivyutils import draw_circle, draw_text
from game import Move

Expand Down Expand Up @@ -79,9 +79,6 @@ def draw_stone(self, x, y, col, outline_col=None, innercol=None, evalcol=None, e
if evalcol:
evalsize = self.stone_size * evalscale * self.ui_config["eval_dot_max_size"]
draw_circle((self.gridpos_x[x], self.gridpos_y[y]), evalsize, evalcol)
# highlight_col = [ ((1-c)*0.33+e)/1.33 for c,e in zip(col,evalcol) ]
# Color(*highlight_col[:3],0.5)
# Line(circle=(self.gridpos[x], self.gridpos[y], evalsize))

if innercol:
Color(*innercol)
Expand All @@ -103,19 +100,19 @@ def draw_board(self, *args):
max_board_size = max(board_size_x, board_size_y)
self.canvas.before.clear()
with self.canvas.before:
# board
board_px_size = min(self.width, self.height)
self.board_color = self.ui_config["board_color"]
Rectangle(pos=self.pos, size=(self.width, self.height))
# grid lines
margin = 1.5
margin_x = margin + (max_board_size - board_size_x) / 2
margin_y = margin - 0.125 + (max_board_size - board_size_y) / 2

self.grid_size = board_px_size / (max_board_size - 1 + 1.5 * margin)
# set up margins and grid lines
grid_spaces_margin_x = [1.5, 0.75] # left, right
grid_spaces_margin_y = [1.125, 0.75] # bottom, top
x_grid_spaces = board_size_x - 1 + sum(grid_spaces_margin_x)
y_grid_spaces = board_size_y - 1 + sum(grid_spaces_margin_y)
self.grid_size = min(self.width / x_grid_spaces, self.height / y_grid_spaces)
board_width_with_margins = x_grid_spaces * self.grid_size
board_height_with_margins = y_grid_spaces * self.grid_size
extra_px_margin_x = (self.width - board_width_with_margins) / 2
extra_px_margin_y = (self.height - board_height_with_margins) / 2
self.stone_size = self.grid_size * self.ui_config["stone_size"]
self.gridpos_x = [self.pos[0] + math.floor((margin_x + i) * self.grid_size + 0.5) for i in range(board_size_x)] #
self.gridpos_y = [self.pos[1] + math.floor((margin_y + i) * self.grid_size + 0.5) for i in range(board_size_y)]
self.gridpos_x = [self.pos[0] + extra_px_margin_x + math.floor((grid_spaces_margin_x[0] + i) * self.grid_size + 0.5) for i in range(board_size_x)] #
self.gridpos_y = [self.pos[1] + extra_px_margin_y + math.floor((grid_spaces_margin_y[0] + i) * self.grid_size + 0.5) for i in range(board_size_y)]

line_color = self.ui_config["line_color"]
Color(*line_color)
Expand All @@ -138,7 +135,7 @@ def star_point_coords(size):

# coordinates
Color(0.25, 0.25, 0.25)
coord_offset = self.grid_size * margin / 2
coord_offset = self.grid_size * 1.5 / 2
for i in range(board_size_x):
draw_text(pos=(self.gridpos_x[i], self.gridpos_y[0] - coord_offset), text=Move.GTP_COORD[i], font_size=self.grid_size / 1.5)
for i in range(board_size_y):
Expand Down Expand Up @@ -178,6 +175,17 @@ def draw_board_contents(self, *args):
drawn_stone[m.coords] = m.player
self.draw_stone(m.coords[0], m.coords[1], stone_color[m.player], outline_color[m.player], inner, evalcol, evalsize)

if katrain.game.current_node.is_root and katrain.config("debug/level") >= OUTPUT_EXTRA_DEBUG:
for s in range(0, 19):
c = s
evalcol = self.eval_color(s)
evalsize = 1
self.draw_stone(5, c, stone_color["B"], outline_color["B"], None, evalcol, evalsize)
self.draw_stone(6, c, stone_color["B"], outline_color["B"], stone_color["W"], evalcol, evalsize)
self.draw_stone(7, c, stone_color["W"], outline_color["W"], None, evalcol, evalsize)
self.draw_stone(8, c, stone_color["W"], outline_color["W"], stone_color["B"], evalcol, evalsize)
self.draw_stone(9, c, [*evalcol, 0.5], scale=0.8)

# ownership - allow one move out of date for smooth animation
ownership = current_node.ownership or (current_node.parent and current_node.parent.ownership)
if katrain.controls.ownership.active and ownership:
Expand Down
5 changes: 2 additions & 3 deletions gui/controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def __init__(self, **kwargs):

def set_status(self, msg, at_node=None):
self.status = msg
self.status_node = at_node or self.katrain.game and self.parent.game.current_node
self.status_node = at_node or self.katrain.game and self.katrain.game.current_node
self.info.text = msg
self.update_evaluation()

Expand Down Expand Up @@ -74,7 +74,6 @@ def update_evaluation(self):
if current_player_is_human_or_both_robots:
self.show_evaluation_stats(current_node)

if current_node.score:
self.graph.update_value(current_node)
self.graph.update_value(current_node)

self.info.text = info
18 changes: 10 additions & 8 deletions gui/kivyutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@ class DarkLabel(Label):


class StyledButton(Button):
text_color = ListProperty([0.95, 0.95, 0.95, 1]) # TODO defaults as in ..
button_color = ListProperty([0.21, 0.28, 0.31, 1])
button_color_down = ListProperty([0.105, 0.14, 0.155, 1])
margin = ListProperty([1, 1, 1, 1]) # margin left bottom right top
button_color = ListProperty([])
button_color_down = ListProperty([])
radius = ListProperty((0,))


Expand Down Expand Up @@ -183,11 +181,12 @@ def initialize_from_game(self, root):
def on_size(self, *args):
nodes = self.nodes
if nodes:
values = [n.score if n and n.score else 0 for n in nodes]
val_range = min(values or [0]), max(values or [0])
values = [n.score if n and n.score else math.nan for n in nodes]
nn_values = [n.score for n in nodes if n and n.score]
val_range = min(nn_values or [0]), max(nn_values or [0])
scale = math.ceil(max(self.min_scale, max(-val_range[0], val_range[1]) * 1.05))

xscale = self.width * 0.9 / max(len(values), 20)
xscale = self.width * 0.9 / max(len(values) - 1, 15)
available_height = self.height * (1 - 2 * self.marginy)
line_points = [[self.pos[0] + self.marginx * self.width + i * xscale, self.pos[1] + available_height / 2 * (1 + val / scale)] for i, val in enumerate(values)]
self.line_points = sum(line_points, [])
Expand All @@ -196,7 +195,10 @@ def on_size(self, *args):

if self.highlighted_index is not None:
self.highlighted_index = min(self.highlighted_index, len(values) - 1)
self.dot_pos = [c - self.highlight_size / 2 for c in line_points[self.highlighted_index]]
dot_point = line_points[self.highlighted_index]
if math.isnan(dot_point[1]):
dot_point[1] = self.pos[1] + available_height / 2 * (1 + (nn_values or [0])[-1] / scale)
self.dot_pos = [c - self.highlight_size / 2 for c in dot_point]

def update_value(self, node):
index = node.depth
Expand Down
4 changes: 1 addition & 3 deletions gui/popups.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,5 @@ def update_config(self, save_to_file=False):
self.katrain.engine = KataGoEngine(self.katrain, self.config[cat])
self.katrain.game.engine = self.katrain.engine
old_engine.shutdown(finish=True)
engine_restart = True

if engine_restart:
self.katrain.update_state(redraw_board=True)
self.katrain.update_state(redraw_board=True)
Loading

0 comments on commit 2c4c2a2

Please sign in to comment.