below board panel

This commit is contained in:
Sander Land committed 2020-04-19 13:30:48 +02:00
1 parent c4ce996ef5
commit 3f8e15f36c
6 files changed
+60 -43

No files matched your search

-1
View File
@@ -28,7 +28,6 @@
"eval_off_show_last": 3 "eval_off_show_last": 3
}, },
"board_ui": { "board_ui": {
"board_margin": 1.5,
"starpoint_size": 0.1, "starpoint_size": 0.1,
"stone_size": 0.475, "stone_size": 0.475,
"eval_dot_max_size": 0.5, "eval_dot_max_size": 0.5,
+1 -1
View File
@@ -196,7 +196,7 @@ class Game:
def ai_move(self, train_settings): def ai_move(self, train_settings):
while not self.current_node.analysis_ready: while not self.current_node.analysis_ready:
self.katrain.set_status("Thinking...") self.katrain.controls.set_status("Thinking...")
time.sleep(0.05) time.sleep(0.05)
# select move # select move
+1 -1
View File
@@ -1,4 +1,4 @@
from gui.badukpan import BadukPanWidget from gui.badukpan import BadukPanWidget, BadukPanControls
from gui.controls import Controls from gui.controls import Controls
from gui.kivyutils import ( from gui.kivyutils import (
BWCheckBoxHint, BWCheckBoxHint,
+38 -33
View File
@@ -2,6 +2,7 @@ import math
from kivy.graphics.context_instructions import Color from kivy.graphics.context_instructions import Color
from kivy.graphics.vertex_instructions import Ellipse, Line, Rectangle from kivy.graphics.vertex_instructions import Ellipse, Line, Rectangle
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget from kivy.uix.widget import Widget
from constants import OUTPUT_DEBUG from constants import OUTPUT_DEBUG
@@ -15,22 +16,23 @@ class BadukPanWidget(Widget):
self.ui_config = {} self.ui_config = {}
self.trainer_config = {} self.trainer_config = {}
self.ghost_stone = [] self.ghost_stone = []
self.gridpos = [] self.gridpos_x = []
self.gridpos_y = []
self.grid_size = 0 self.grid_size = 0
self.stone_size = 0 self.stone_size = 0
self.last_eval = 0 self.last_eval = 0
# stone placement functions # stone placement functions
def _find_closest(self, pos): def _find_closest(self, pos, gridpos):
return sorted([(abs(p - pos), i) for i, p in enumerate(self.gridpos)])[0] return sorted([(abs(p - pos), i) for i, p in enumerate(gridpos)])[0]
def on_touch_down(self, touch): def on_touch_down(self, touch):
if not self.gridpos: if not self.gridpos_x:
return return
xd, xp = self._find_closest(touch.x) xd, xp = self._find_closest(touch.x,self.gridpos_x)
yd, yp = self._find_closest(touch.y) yd, yp = self._find_closest(touch.y,self.gridpos_y)
prev_ghost = self.ghost_stone prev_ghost = self.ghost_stone
if max(yd, xd) < self.grid_size / 2 and (xp, yp) not in [m.coords for m in self.parent.game.stones]: if max(yd, xd) < self.grid_size / 2 and (xp, yp) not in [m.coords for m in self.katrain.game.stones]:
self.ghost_stone = (xp, yp) self.ghost_stone = (xp, yp)
else: else:
self.ghost_stone = None self.ghost_stone = None
@@ -41,14 +43,14 @@ class BadukPanWidget(Widget):
return self.on_touch_down(touch) return self.on_touch_down(touch)
def on_touch_up(self, touch): def on_touch_up(self, touch):
if not self.gridpos: if not self.gridpos_x:
return return
katrain = self.parent katrain = self.katrain
if self.ghost_stone: if self.ghost_stone:
katrain("play", self.ghost_stone) katrain("play", self.ghost_stone)
else: else:
xd, xp = self._find_closest(touch.x) xd, xp = self._find_closest(touch.x,self.gridpos_x)
yd, yp = self._find_closest(touch.y) yd, yp = self._find_closest(touch.y,self.gridpos_y)
nodes_here = [node for node in katrain.game.current_node.nodes_from_root if node.single_move and node.single_move.coords == (xp, yp)] nodes_here = [node for node in katrain.game.current_node.nodes_from_root if node.single_move and node.single_move.coords == (xp, yp)]
if nodes_here and max(yd, xd) < self.grid_size / 2: # load old comment if nodes_here and max(yd, xd) < self.grid_size / 2: # load old comment
@@ -68,20 +70,20 @@ class BadukPanWidget(Widget):
def draw_stone(self, x, y, col, outline_col=None, innercol=None, evalcol=None, evalscale=1.0, scale=1.0): def draw_stone(self, x, y, col, outline_col=None, innercol=None, evalcol=None, evalscale=1.0, scale=1.0):
stone_size = self.stone_size * scale stone_size = self.stone_size * scale
draw_circle((self.gridpos[x], self.gridpos[y]), stone_size, col) draw_circle((self.gridpos_x[x], self.gridpos_y[y]), stone_size, col)
if outline_col: if outline_col:
Color(*outline_col) Color(*outline_col)
Line(circle=(self.gridpos[x], self.gridpos[y], stone_size), width=0.05 * stone_size) Line(circle=(self.gridpos_x[x], self.gridpos_y[y], stone_size), width=0.05 * stone_size)
if evalcol: if evalcol:
evalsize = self.stone_size * evalscale * self.ui_config["eval_dot_max_size"] evalsize = self.stone_size * evalscale * self.ui_config["eval_dot_max_size"]
draw_circle((self.gridpos[x], self.gridpos[y]), evalsize, evalcol) 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) ] # highlight_col = [ ((1-c)*0.33+e)/1.33 for c,e in zip(col,evalcol) ]
# Color(*highlight_col[:3],0.5) # Color(*highlight_col[:3],0.5)
# Line(circle=(self.gridpos[x], self.gridpos[y], evalsize)) # Line(circle=(self.gridpos[x], self.gridpos[y], evalsize))
if innercol: if innercol:
Color(*innercol) Color(*innercol)
Line(circle=(self.gridpos[x], self.gridpos[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.45 / 0.85), width=0.125 * stone_size) # 1.75
def eval_color(self, points_lost): def eval_color(self, points_lost):
colors = self.ui_config["eval_colors"] colors = self.ui_config["eval_colors"]
@@ -94,39 +96,40 @@ class BadukPanWidget(Widget):
def draw_board(self, *args): def draw_board(self, *args):
if not self.ui_config: if not self.ui_config:
return return
katrain = self.parent katrain = self.katrain
board_size = katrain.game.board_size board_size = katrain.game.board_size
self.canvas.before.clear() self.canvas.before.clear()
with self.canvas.before: with self.canvas.before:
# board # board
sz = min(self.width, self.height) sz = min(self.width, self.height)
Color(*self.ui_config["board_color"]) Color(*self.ui_config["board_color"])
board_rectangle = Rectangle(pos=(0, 0), size=(sz, sz)) board_rectangle = Rectangle(pos=self.pos, size=(sz, sz))
# grid lines # grid lines
margin = self.ui_config["board_margin"] margin = 1.5
self.grid_size = board_rectangle.size[0] / (board_size - 1 + 1.5 * margin) self.grid_size = board_rectangle.size[0] / (board_size - 1 + 1.5 * margin)
self.stone_size = self.grid_size * self.ui_config["stone_size"] self.stone_size = self.grid_size * self.ui_config["stone_size"]
self.gridpos = [math.floor((margin + i) * self.grid_size + 0.5) for i in range(board_size)] self.gridpos_x = [self.pos[0] + math.floor((margin + i) * self.grid_size + 0.5) for i in range(board_size)]
self.gridpos_y = [self.pos[1] + math.floor((margin + i) * self.grid_size + 0.5) for i in range(board_size)]
line_color = self.ui_config["line_color"] line_color = self.ui_config["line_color"]
Color(*line_color) Color(*line_color)
lo, hi = self.gridpos[0], self.gridpos[-1]
for i in range(board_size): for i in range(board_size):
Line(points=[(self.gridpos[i], lo), (self.gridpos[i], hi)]) Line(points=[(self.gridpos_x[i], self.gridpos_y[0]), (self.gridpos_x[i], self.gridpos_y[-1])])
Line(points=[(lo, self.gridpos[i]), (hi, self.gridpos[i])]) Line(points=[( self.gridpos_x[0], self.gridpos_y[i]), ( self.gridpos_x[-1], self.gridpos_y[i])])
# star points # star points
star_point_pos = 3 if board_size <= 11 else 4 star_point_pos = 3 if board_size <= 11 else 4
starpt_size = self.grid_size * self.ui_config["starpoint_size"] starpt_size = self.grid_size * self.ui_config["starpoint_size"]
for x in [star_point_pos - 1, board_size - star_point_pos, int(board_size / 2)]: for x in [star_point_pos - 1, board_size - star_point_pos, int(board_size / 2)]:
for y in [star_point_pos - 1, board_size - star_point_pos, int(board_size / 2)]: for y in [star_point_pos - 1, board_size - star_point_pos, int(board_size / 2)]:
draw_circle((self.gridpos[x], self.gridpos[y]), starpt_size, line_color) draw_circle((self.gridpos_x[x], self.gridpos_y[y]), starpt_size, line_color)
# coordinates # coordinates
Color(0.25, 0.25, 0.25) Color(0.25, 0.25, 0.25)
coord_offset = self.grid_size * margin / 2
for i in range(board_size): for i in range(board_size):
draw_text(pos=(self.gridpos[i], lo / 2), text=Move.GTP_COORD[i], font_size=self.grid_size / 1.5) 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)
draw_text(pos=(lo / 2, self.gridpos[i]), text=str(i + 1), font_size=self.grid_size / 1.5) draw_text(pos=(self.gridpos_x[0] - coord_offset, self.gridpos_y[i]), text=str(i + 1), font_size=self.grid_size / 1.5)
def draw_board_contents(self, *args): def draw_board_contents(self, *args):
if not self.ui_config: if not self.ui_config:
@@ -134,7 +137,7 @@ class BadukPanWidget(Widget):
stone_color = self.ui_config["stones"] stone_color = self.ui_config["stones"]
outline_color = self.ui_config["outline"] outline_color = self.ui_config["outline"]
_ghost_alpha = self.ui_config["_ghost_alpha"] _ghost_alpha = self.ui_config["_ghost_alpha"]
katrain = self.parent katrain = self.katrain
board_size = katrain.game.board_size board_size = katrain.game.board_size
self.canvas.clear() self.canvas.clear()
@@ -171,7 +174,7 @@ class BadukPanWidget(Widget):
ix_owner = "B" if ownership[ix] > 0 else "W" ix_owner = "B" if ownership[ix] > 0 else "W"
if ix_owner != (has_stone.get((x, y), -1)): if ix_owner != (has_stone.get((x, y), -1)):
Color(*stone_color[ix_owner], abs(ownership[ix])) Color(*stone_color[ix_owner], abs(ownership[ix]))
Rectangle(pos=(self.gridpos[x] - rsz / 2, self.gridpos[y] - rsz / 2), size=(rsz, rsz)) Rectangle(pos=(self.gridpos_x[x] - rsz / 2, self.gridpos_y[y] - rsz / 2), size=(rsz, rsz))
ix = ix + 1 ix = ix + 1
policy = current_node.policy policy = current_node.policy
@@ -187,8 +190,7 @@ class BadukPanWidget(Widget):
policy_delta = best_move_policy - policy[ix] policy_delta = best_move_policy - policy[ix]
polcol = self.eval_color(0.1 * policy_delta / avg_policy) polcol = self.eval_color(0.1 * policy_delta / avg_policy)
Color(*polcol) Color(*polcol)
Rectangle(pos=(self.gridpos[x] - rsz / 2, self.gridpos[y] - rsz / 2), size=(rsz, rsz)) Rectangle(pos=(self.gridpos_x[x] - rsz / 2, self.gridpos_y[y] - rsz / 2), size=(rsz, rsz))
else:
ix = ix + 1 ix = ix + 1
policy_delta = best_move_policy - policy[ix] policy_delta = best_move_policy - policy[ix]
katrain.controls.pass_btn.face_color = (*self.eval_color(100*policy_delta),1) katrain.controls.pass_btn.face_color = (*self.eval_color(100*policy_delta),1)
@@ -220,7 +222,6 @@ class BadukPanWidget(Widget):
scale = 0.85 scale = 0.85
self.draw_stone(move.coords[0], move.coords[1], c, scale=scale) self.draw_stone(move.coords[0], move.coords[1], c, scale=scale)
# hover next move ghost stone # hover next move ghost stone
if self.ghost_stone: if self.ghost_stone:
self.draw_stone(*self.ghost_stone, (*stone_color[next_player], _ghost_alpha)) self.draw_stone(*self.ghost_stone, (*stone_color[next_player], _ghost_alpha))
@@ -233,7 +234,11 @@ class BadukPanWidget(Widget):
else: else:
text = "pass" text = "pass"
Color(0.45, 0.05, 0.45, 0.5) Color(0.45, 0.05, 0.45, 0.5)
center = self.gridpos[int(board_size / 2)] center = (self.pos[0] + self.width/2,self.pos[1]+self.height/2)
Ellipse(pos=(center - self.grid_size * 1.5, center - self.grid_size * 1.5), size=(self.grid_size * 3, self.grid_size * 3)) size = min(self.width, self.height) * 0.22
Ellipse(pos=(center[0] - size/2, center[1] - size/2), size=(size,size))
Color(0.15, 0.15, 0.15) Color(0.15, 0.15, 0.15)
draw_text(pos=(center, center), text=text, font_size=self.grid_size * 0.66, halign="center", outline_color=[0.95, 0.95, 0.95]) draw_text(pos=center, text=text, font_size=size*0.25, halign="center", outline_color=[0.95, 0.95, 0.95])
class BadukPanControls(BoxLayout):
pass
+19 -6
View File
@@ -264,8 +264,8 @@
<BadukPanWidget>: <BadukPanWidget>:
size: self.parent.height, self.parent.height size: self.parent.height, self.parent.height
engine: self.parent.controls katrain: self.parent.parent
<Controls> <Controls>
orientation: 'vertical' orientation: 'vertical'
play_tab_button: play_tab_button play_tab_button: play_tab_button
@@ -300,6 +300,7 @@
play_tab.size_hint_x = None play_tab.size_hint_x = None
play_tab.width = 0 play_tab.width = 0
play_tab.opacity = 0 play_tab.opacity = 0
self.state = 'down'
StyledToggleButton: StyledToggleButton:
text: 'Play' text: 'Play'
group: 'tabs' group: 'tabs'
@@ -312,6 +313,7 @@
analyze_tab.size_hint_x = None analyze_tab.size_hint_x = None
analyze_tab.width = 0 analyze_tab.width = 0
analyze_tab.opacity = 0 analyze_tab.opacity = 0
self.state = 'down'
BoxLayout: BoxLayout:
size_hint: 1,0.25 size_hint: 1,0.25
orientation: 'horizontal' orientation: 'horizontal'
@@ -467,21 +469,32 @@
size_hint: 0.25, 1 size_hint: 0.25, 1
on_press: root.katrain('config-popup') on_press: root.katrain('config-popup')
<BadukPanControls>:
StyledIconButton:
icon: 'img/flaticon/go-game.png'
size_hint: 0.25, 1
on_press: root.katrain("new-game-popup")
<KaTrainGui>: <KaTrainGui>:
board_gui: board_gui board_gui: board_gui
controls: controls controls: controls
board_aspect_ratio: 1.1
canvas.before: canvas.before:
Color: Color:
rgba: 0.95, 0.95, 0.95, 1 rgba: 0.95, 0.95, 0.95, 1
Rectangle: Rectangle:
pos: self.pos pos: self.pos
size: root.size size: root.size
BadukPanWidget: BoxLayout:
id: board_gui orientation: 'vertical'
size_hint: 1 - controls.size_hint[0], 1 size_hint: 1 - controls.size_hint[0], 1
BadukPanWidget:
id: board_gui
size_hint: (1,1)
BadukPanControls:
id: board_controls
size_hint: (1,root.board_aspect_ratio-1)
Controls: Controls:
id: controls id: controls
size_hint: max(0.25,(root.width - root.height)/root.width), 1 size_hint: max(0.25,(root.width - root.height/root.board_aspect_ratio)/root.width), 1
+1 -1
View File
@@ -160,7 +160,7 @@ class SGFNode:
def single_move(self) -> Optional[Move]: def single_move(self) -> Optional[Move]:
"""Returns the single move for the node if one exists, or None if no moves (or multiple ones) exist.""" """Returns the single move for the node if one exists, or None if no moves (or multiple ones) exist."""
moves = self.moves moves = self.moves
if len(moves) == 1: if len(moves) == 1: # TODO: and not placements?
return moves[0] return moves[0]
@property @property