This commit is contained in:
Sander Land committed 2020-04-18 20:46:14 +02:00
1 parent 717b1de032
commit 8aaa85e73d
6 files changed
+67 -70

No files matched your search

+3 -2
View File
@@ -79,8 +79,9 @@ class KataGoEngine:
else:
self.katrain.log(f"Query result {analysis['id']} discarded -- recent new game?", OUTPUT_DEBUG)
def request_analysis(self, analysis_node: GameNode, callback: Callable, faster: bool = False, visits: int = None, priority: int = 0, ownership: Optional[bool] = None,
refine_move=None):
def request_analysis(
self, analysis_node: GameNode, callback: Callable, faster: bool = False, visits: int = None, priority: int = 0, ownership: Optional[bool] = None, refine_move=None
):
fast = self.katrain.controls.ai_fast.active
query_id = f"QUERY:{str(self.query_counter)}"
self.query_counter += 1
+10 -10
View File
@@ -194,7 +194,7 @@ class Game:
f.write(self.root.sgf())
return f"SGF with analysis written to {file_name}"
def ai_move(self,train_settings):
def ai_move(self, train_settings):
while not self.current_node.analysis_ready:
self.katrain.set_status("Thinking...")
time.sleep(0.05)
@@ -242,23 +242,23 @@ class Game:
stones = {s.coords for s in self.stones}
cn = self.current_node
if not cn.analysis:
self.katrain.controls.set_status("Wait for initial analysis to complete before doing a board-sweep or refinement",self.current_node)
self.katrain.controls.set_status("Wait for initial analysis to complete before doing a board-sweep or refinement", self.current_node)
return
if mode == "extra":
visits = sum([d["visits"] for d in cn.analysis]) + self.engine.config['visits']
visits = sum([d["visits"] for d in cn.analysis]) + self.engine.config["visits"]
self.katrain.controls.set_status(f"Performing additional analysis to {visits} visits")
cn.analyze(self.engine, visits=visits, priority=- 1_000)
cn.analyze(self.engine, visits=visits, priority=-1_000)
return
elif mode == "sweep":
analyze_moves = [Move(coords=(x, y),player=cn.next_player) for x in range(self.board_size) for y in range(self.board_size) if (x, y) not in stones]
visits = self.engine.config['visits_fast']
analyze_moves = [Move(coords=(x, y), player=cn.next_player) for x in range(self.board_size) for y in range(self.board_size) if (x, y) not in stones]
visits = self.engine.config["visits_fast"]
self.katrain.controls.set_status(f"Refining analysis of entire board to {visits} visits")
priority =- 1_000_000_000
priority = -1_000_000_000
else: # mode=='refine':
analyze_moves = [Move.from_gtp(a["move"],player=cn.next_player) for a in cn.analysis]
visits = cn.analysis[0]["visits"] + self.engine.config['visits_fast']
analyze_moves = [Move.from_gtp(a["move"], player=cn.next_player) for a in cn.analysis]
visits = cn.analysis[0]["visits"] + self.engine.config["visits_fast"]
self.katrain.controls.set_status(f"Refining analysis of candidate moves to {visits} visits")
priority = - 1_000
priority = -1_000
for move in analyze_moves:
cn.analyze(self.engine, priority, visits=visits, refine_move=move)
+6 -7
View File
@@ -29,19 +29,18 @@ class GameNode(SGFNode):
# various analysis functions
def analyze(self, engine, priority=0, visits=None, refine_move=None):
engine.request_analysis(self, lambda result: self.set_analysis(result,refine_move), priority=priority,
visits=visits, refine_move=refine_move)
engine.request_analysis(self, lambda result: self.set_analysis(result, refine_move), priority=priority, visits=visits, refine_move=refine_move)
def set_analysis(self, analysis_blob, refine_move):
if refine_move:
gtp = refine_move.gtp()
for d in self.analysis:
if d['move']==gtp:
if d['visits'] < analysis_blob['rootInfo']['visits']:
d.update(analysis_blob['rootInfo'])
if d["move"] == gtp:
if d["visits"] < analysis_blob["rootInfo"]["visits"]:
d.update(analysis_blob["rootInfo"])
return
self.analysis.append({'move':gtp,'order':999,**analysis_blob['rootInfo']})
else: # TODO root info / to dict?
self.analysis.append({"move": gtp, "order": 999, **analysis_blob["rootInfo"]})
else: # TODO root info / to dict?
self.analysis = analysis_blob["moveInfos"] # TODO: fix when rootInfos comes in
self.ownership = analysis_blob["ownership"]
+6 -1
View File
@@ -20,12 +20,17 @@ class Controls(BoxLayout):
self.status = None
self.status_node = None
def set_status(self, msg,at_node=None):
def set_status(self, msg, at_node=None):
self.status = msg
self.status_node = at_node or self.parent.game.current_node
self.info.text = msg
self.update_evaluation()
def select_mode(self, mode):
if mode == "analyze":
self.analyze_tab_button.trigger_action(duration=0)
else:
self.play_tab_button.trigger_action(duration=0)
def show_evaluation_stats(self, node):
if node.analysis_ready:
+33 -44
View File
@@ -1,14 +1,15 @@
#:kivy 1.11.0
#:import ew kivy.uix.effectwidget
# margin left bottom right top
<StyledButton>:
text_color: 0.95,0.95,0.95,1
button_color: 0.21, 0.28, 0.31, 1
button_color_down: (*[c/2 for c in self.button_color[:3]],1)
margin: (2,1)
margin: (1,1,1,1)
bold: False
font_size: self.size[1] * 0.35
radius: 10
radius: (self.size[1]/7,)
# dont set these
disabled_mask: (0.5,0.5,0.5,1) if self.disabled else (1,1,1,1)
color: self.disabled_mask if self.disabled else self.text_color
@@ -19,30 +20,14 @@
Color:
rgba: root.face_color or [0,0,0,0]
RoundedRectangle:
size: self.size[0]-2*self.margin[0],self.size[1]-2*self.margin[1]
size: self.size[0]-self.margin[0]-self.margin[2],self.size[1]-self.margin[1]-self.margin[3]
pos: (self.pos[0]+self.margin[0],self.pos[1]+self.margin[1])
radius: (root.radius or 0,)
radius: root.radius or (0.0,)
<StyledToggleButton@ToggleButton>:
color: 1,1,1,1
button_color: 0.21, 0.28, 0.31, 1
button_color_down: (*[c/2 for c in self.button_color[:3]],1)
margin: (1,1)
<StyledToggleButton@StyledButton+ToggleButtonBehavior>:
bold: True
font_size: self.size[1] * 0.45
radius: self.size[1]/3
# dont set these
disabled_mask: (0.5,0.5,0.5,1) if self.disabled else (1,1,1,1)
background_color: 0,0,0,0
background_normal: ''
face_color: [c*m for c,m in zip(self.button_color if root.state=='normal' else self.button_color_down,self.disabled_mask)]
canvas.before:
Color:
rgba: root.face_color or [0,0,0,0]
RoundedRectangle:
size: self.size[0]-2*self.margin[0],self.size[1]-2*self.margin[1]
pos: (self.pos[0]+self.margin[0],self.pos[1]+self.margin[1])
radius: (root.radius or 0,root.radius or 0,0,0)
radius: (self.size[1]/3,self.size[1]/3,0,0)
<StyledIconButton@StyledButton>
button_color: 0.71, 0.78, 0.81, 1
@@ -283,6 +268,8 @@
<Controls>
orientation: 'vertical'
play_tab_button: play_tab_button
analyze_tab_button: analyze_tab_button
info: info
win_rate: win_rate
points_lost: points_lost
@@ -303,7 +290,7 @@
StyledToggleButton:
text: 'Analyze'
id: analyze_tab_button
state: 'down'
margin: (3,0,1,3)
group: 'tabs'
on_press:
analyze_tab.size_hint[0] = 1
@@ -311,28 +298,30 @@
play_tab.size_hint_x = None
play_tab.width = 0
play_tab.opacity = 0
print(play_tab,play_tab.size_hint,analyze_tab.size_hint)
StyledToggleButton:
text: 'Play'
group: 'tabs'
state: 'down'
id: play_tab_button
margin: (1,0,3,3)
on_press:
play_tab.size_hint[0] = 1
play_tab.opacity = 1
analyze_tab.size_hint_x = None
analyze_tab.width = 0
analyze_tab.opacity = 0
print(play_tab.size_hint,analyze_tab.size_hint)
BoxLayout:
size_hint: 1,0.25
orientation: 'horizontal'
BoxLayout:
size_hint: 1,1
BoxLayout: # ----------- analyze -----------
size_hint: 0,1
id: analyze_tab
opacity: 0
orientation: 'vertical'
GridLayout:
cols: 7
cols: 6
rows: 1
size_hint: 1, 0.25
size_hint: 1, 0.35
Label:
size_hint: 0.01, 1
BoxLayout:
@@ -355,11 +344,6 @@
id: hints
text: 'top move'
on_active: root.parent.update_state()
BWCheckBoxHint:
size_hint: 0.2, 0.5
id: auto_undo
text: 'undo'
on_active: root.parent.update_state()
CheckBoxHint:
size_hint: 0.2, 0.5
id: ownership
@@ -383,18 +367,13 @@
size_hint: 1, 0.15
label: 'Score'
text: '...'
CensorableLabel:
id: points_lost
size_hint: 1, 0.15
label: 'Point loss'
text: '...'
BoxLayout:
BoxLayout: # ----------- play -----------
orientation: 'vertical'
size_hint: 0,1
opacity: 0
size_hint: 1,1
opacity: 1
id: play_tab
GridLayout:
cols: 4
cols: 5
rows: 1
size_hint: 1, 0.1
BoxLayout:
@@ -411,6 +390,11 @@
id: ai_auto
default_active: False
size_hint: 0.25, 1
BWCheckBoxHint:
size_hint: 0.2, 0.5
id: auto_undo
text: 'undo'
on_active: root.parent.update_state()
CheckBoxHint:
size_hint: 0.25, 1
text: 'fast'
@@ -438,6 +422,11 @@
LargeLabel:
text: 'free real estate'
size_hint: 1,0.5
CensorableLabel:
id: points_lost
size_hint: 1, 0.03
label: 'Point loss'
text: '...'
GridLayout:
cols: 2
rows: 1
@@ -449,7 +438,7 @@
default_active: True
StyledButton:
text: 'Pass'
on_press: root.katrain("play",(None,None))
on_press: root.katrain("play",None)
TextInput:
id: info
size_hint: 1, 0.2
+9 -6
View File
@@ -39,7 +39,7 @@ class KaTrainGui(BoxLayout):
def log(self, message, level=OUTPUT_INFO):
if level == OUTPUT_ERROR:
self.controls.set_status(f"ERROR: {message}",self.game.current_node)
self.controls.set_status(f"ERROR: {message}", self.game.current_node)
print(f"ERROR: {message}")
elif self.debug_level >= level:
print(message)
@@ -108,16 +108,19 @@ class KaTrainGui(BoxLayout):
def _do_new_game(self, board_size=None, move_tree=None):
self.game = Game(self, self.engine, self.config("game"), board_size=board_size, move_tree=move_tree)
self.controls.unlock()
self.update_state(redraw_board=True)
self.controls.select_mode("analyze" if move_tree and len(move_tree.nodes_in_tree) > 1 else "play")
self.update_state(redraw_board=True) # TODO: just board here/redraw is in all anyway?
def _do_ai_move(self, node=None):
if node is None or self.game.current_node == node:
self.game.ai_move(self.config('trainer'))
self.game.ai_move(self.config("trainer"))
self.update_state()
def _do_undo(self, n_times=1):
if self.controls.ai_lock.active and self.contols.auto_undo.active(self.game.current_node.player) and self.config("trainer/lock_undos"):
self.controls.set_status(f"Can't undo manually when Automatic Undo and Lock AI are both set. (Change the `lock_undos` setting to false to allow this regardless)",self.game.current_node)
self.controls.set_status(
f"Can't undo manually when Automatic Undo and Lock AI are both set. (Change the `lock_undos` setting to false to allow this regardless)", self.game.current_node
)
return
self.game.undo(n_times)
self.update_state()
@@ -225,8 +228,8 @@ class KaTrainGui(BoxLayout):
self.controls.set_status(f"Failed to imported game from clipboard: {e}")
return
self._do_new_game(move_tree=move_tree)
self('redo',999)
self.log("Imported game from clipboard.",OUTPUT_INFO)
self("redo", 999)
self.log("Imported game from clipboard.", OUTPUT_INFO)
return True