rewinds to start and has keyboard controls

This commit is contained in:
Sander Land committed 2020-02-19 19:33:05 +01:00
1 parent 190a893bae
commit 144e7b8331
5 files changed
+68 -18

No files matched your search

+17 -4
View File
@@ -50,6 +50,10 @@ Options
This can be < 0% in case of suicidal moves, or >100% when Kata did not consider the move before, or further analysis shows it to be better than the best one considered.
* Score: How far one player is ahead.
* Keyboard controls
* Arrow up: undo
* Arrow down: redo
Play
----
@@ -70,10 +74,10 @@ Play
* Play with a friend with instant feedback and/or undos for both, or see how many stones stronger you are with one undo. (But please play unranked and be honest to your opponent on what you're doing)
* Analysis
* Copy the SGF into the text box. Note that branches are not supported and will lead to strange results.
* Choose whether or not to turn on `fast` to make the AI weaker but analyze faster.
* Click `Load`
* Alternatively click `Load` when the text box is empty to get a file chooser dialog.
* Click 'Load' when the text box is empty-ish to get a file chooser dialog. Note that branches are not supported and will lead to strange results.
* Select if you want fast analysis or rewinding to the start for reviewing. Note that the 'fast' checkbox still affects speed as well,
this is just an additional lowering of visits.
* Alternatively copy the SGF into the text box and click 'Load'.
* Save game
* Click save to get an sgf with comments saved in the sgfout/ directory (and a short version in the text box).
@@ -94,6 +98,15 @@ The `trainer` block has the following options to tweak:
The cfg file has additional configuration for kata. In particular, it changes the default to being more exploratory and score-based (and therefore nicer as an opponent, but weaker as analysis tool).
FAQ
===
* The program is slow to start!
* The first startup of KataGo can be slow, after that it should be much faster.
* The program is running too slowly!
* Lower the visits count in `config.json` by half or so and try again.
* Can I play on sizes other than 9, 13 or 19?
* Type in `SZ[n]HA[h]` in the text box and hit 'load' for a game on a n by n board with h handicap stones, but note that the default KataGo does not support sizes above 19x19.
Contributing
============
* Feedback and pull requests are both very welcome.
+11 -1
View File
@@ -74,7 +74,9 @@ class Move:
return ""
if eval and not sgf and self.children: # show undos and on previous move as well while playing
text = "".join(f"Auto undid move {m.gtp()} ({-self.temperature_stats[2] * (1-m.evaluation):.1f} pt)\n" for m in self.children if m.auto_undid) + "\n"
text = "".join(f"Auto undid move {m.gtp()} ({-self.temperature_stats[2] * (1-m.evaluation):.1f} pt)\n" for m in self.children if m.auto_undid)
if text:
text += "\n"
else:
text = ""
@@ -270,6 +272,14 @@ class Board:
self.current_move = self.current_move.parent
self._init_chains()
def redo(self):
if self.current_move.children:
self.play(self.current_move.children[-1])
def rewind(self):
self.current_move = self.root
self._init_chains()
def place_handicap_stones(self, n_handicaps):
near = 3 if self.board_size >= 13 else 2
far = self.board_size - 1 - near
+23 -5
View File
@@ -12,8 +12,11 @@ from queue import Queue
from kivy.clock import Clock
from kivy.storage.jsonstore import JsonStore
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.checkbox import CheckBox
from kivy.uix.filechooser import FileChooserListView
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from board import Board, IllegalMoveException, Move
@@ -169,6 +172,11 @@ class EngineControls(GridLayout):
self.info.text = f"Can't undo more than {self.train_settings['num_undo_prompts']} time(s) when locked"
return
self.board.undo()
self.update_evaluation()
def _do_redo(self):
self.board.redo()
self.update_evaluation()
def _do_init(self, board_size, komi=None):
self.board_size = board_size
@@ -182,21 +190,29 @@ class EngineControls(GridLayout):
for el in [self.ai_lock.checkbox, self.hints.black, self.hints.white, self.ai_auto.black, self.ai_auto.white, self.auto_undo.black, self.auto_undo.white, self.ai_move]:
el.disabled = False
def _do_analyze_sgf(self, sgf):
def _do_analyze_sgf(self, sgf, faster=False, rewind=False):
sgfprops = {k: v for k, v in re.findall(r"\b(\w+)\[(.*?)\]", sgf)}
size = int(sgfprops.get("SZ", self.board_size))
sgfmoves = re.findall(r"\b([BW])\[([a-z]{2})\]", sgf)
if not sgfmoves and not sgfprops:
fileselect_popup = Popup(title="Double Click SGF file to analyze", size_hint=(0.8, 0.8))
fc = FileChooserListView(multiselect=False, path=os.path.expanduser("~"), filters=["*.sgf"])
blui = BoxLayout(orientation="horizontal", size_hint=(1, 0.1))
cbfast = CheckBox(color=(0.95, 0.95, 0.95, 1))
cbrewind = CheckBox(color=(0.95, 0.95, 0.95, 1))
for widget in [Label(text="Analyze Extra Fast"), cbfast, Label(text="Rewind to start"), cbrewind]:
blui.add_widget(widget)
bl = BoxLayout(orientation="vertical")
bl.add_widget(fc)
bl.add_widget(blui)
fileselect_popup.add_widget(bl)
def readfile(files, mouse):
fileselect_popup.dismiss()
with open(files[0]) as f:
self.action("analyze-sgf", f.read())
self.action("analyze-sgf", f.read(), cbfast.active, cbrewind.active)
fc = FileChooserListView(multiselect=False, path=os.path.expanduser("~"), filters=["*.sgf"])
fc.on_submit = readfile
fileselect_popup.add_widget(fc)
fileselect_popup.open()
return
self._do_init(size, sgfprops.get("KM"))
@@ -206,7 +222,9 @@ class EngineControls(GridLayout):
if handicap > 0:
self._request_analysis(self.board.current_move)
for move in moves:
self.play(move, faster=(self.ai_fast.active and move != moves[-1]))
self.play(move, faster=faster and move != moves[-1])
if rewind:
self.board.rewind()
# analysis thread
def _analysis_read_thread(self):
+5 -5
View File
@@ -40,13 +40,14 @@
checkbox: checkbox
text: ''
default_active: False
position: (0,0)
CheckBoxHintLabel:
size_hint: 1,0.45
font_size: root.height * 0.2
size_hint: 1,0.45 if root.orientation=='vertical' else (0.8,1)
font_size: root.height * 0.2 if root.orientation=='vertical' else root.height
text: root.text
on_press: if not checkbox.disabled: checkbox._do_press()
CheckBox:
size_hint: 1,0.55
size_hint: 1,0.55 if root.orientation=='vertical' else (0.2,1)
id: checkbox
on_active: root.dispatch('on_active')
active: root.default_active
@@ -224,7 +225,7 @@
id: ai_balance
default_active: False
CheckBoxHint:
size_hint: 0.2, 0.5
size_hint: 0.167, 0.5
text: 'lock\nai'
id: ai_lock
on_active: self.checkbox.disabled = hints.black.disabled = hints.white.disabled = ai_auto.black.disabled = ai_auto.white.disabled = auto_undo.black.disabled = auto_undo.white.disabled = ai_move.disabled = True
@@ -269,7 +270,6 @@
StyledButton:
text: 'Load'
size_hint: 0.5, 1
margin: (0,1)
on_press: root.action("analyze-sgf",info.text)
GridLayout:
size_hint: 1, 0.05
+12 -3
View File
@@ -2,9 +2,8 @@ import math
import signal
from kivy.app import App
from kivy.core.window import Window
from kivy.graphics import *
from kivy.properties import NumericProperty, ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from board import Move
@@ -186,7 +185,17 @@ class BadukPanWidget(Widget):
class KaTrainGui(BoxLayout):
pass
def __init__(self, **kwargs):
super(KaTrainGui, self).__init__(**kwargs)
self._keyboard = Window.request_keyboard(None, self, "")
self._keyboard.bind(on_key_down=self._on_keyboard_down)
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
if keycode[1] == "up":
self.controls.action("undo")
elif keycode[1] == "down":
self.controls.action("redo")
return True
class KaTrainApp(App):