tsumego solver 5000 is go
This commit is contained in:
1 parent
da42fc4e0f
commit
0ade2524ce
27 files changed
+252
-83
No files matched your search
@@ -5,7 +5,7 @@ For on related licenses for these binaries and libraries see https://github.com/
|
|||||||
|
|
||||||
2. Icons from www.flaticon.com, used with permission with the following attributions:
|
2. Icons from www.flaticon.com, used with permission with the following attributions:
|
||||||
- Equalize icon and Thrash Icon: derived from work by bqlqn from www.flaticon.com
|
- Equalize icon and Thrash Icon: derived from work by bqlqn from www.flaticon.com
|
||||||
- Local search icon: derived from work by Pixel Perfect from www.flaticon.com
|
- Local search icon, Insert icon: derived from work by Pixel Perfect from www.flaticon.com
|
||||||
- Other Menu icons and Flag icons: derived from work by Freepik from www.flaticon.com
|
- Other Menu icons and Flag icons: derived from work by Freepik from www.flaticon.com
|
||||||
|
|
||||||
3. The True Type Font DIGITAL-7 version 1.02 by Sizenko Alexander, which is free for non-commercial use.
|
3. The True Type Font DIGITAL-7 version 1.02 by Sizenko Alexander, which is free for non-commercial use.
|
||||||
|
|||||||
@@ -101,12 +101,13 @@ for lang in locales:
|
|||||||
print("Fixed", pofile[lang], "and converted ->", mofile)
|
print("Fixed", pofile[lang], "and converted ->", mofile)
|
||||||
|
|
||||||
|
|
||||||
for file in glob.glob("katrain/**/*.py") + glob.glob("katrain/**/*.kv"):
|
for file in glob.glob("**/*.py") + glob.glob("**/*.kv"):
|
||||||
with open(file, "r") as f:
|
with open(file, "r") as f:
|
||||||
for i, line in enumerate(f.readlines()):
|
for i, line in enumerate(f.readlines()):
|
||||||
matches = [m.strip() for m in re.findall(r"i18n._\((.*?)\)", line)]
|
matches = [m.strip() for m in re.findall(r"i18n._\((.*?)\)", line)]
|
||||||
for msgid in matches:
|
for msgid in matches:
|
||||||
if msgid[0] in ['"', "'"] and msgid.strip("\"'") not in strings_to_langs: # not code
|
stripped_msgid = msgid.strip("\"'")
|
||||||
|
if stripped_msgid and msgid[0] in ['"', "'"] and stripped_msgid not in strings_to_langs: # not code
|
||||||
print(f"Missing {msgid} used in code at \t{file}:{i} \t'{line.strip()}'")
|
print(f"Missing {msgid} used in code at \t{file}:{i} \t'{line.strip()}'")
|
||||||
errors += 1
|
errors += 1
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -324,6 +324,10 @@ class KaTrainGui(Screen, KaTrainBase):
|
|||||||
def _do_analyze_extra(self, mode, **kwargs):
|
def _do_analyze_extra(self, mode, **kwargs):
|
||||||
self.game.analyze_extra(mode, **kwargs)
|
self.game.analyze_extra(mode, **kwargs)
|
||||||
|
|
||||||
|
def _do_select_box(self):
|
||||||
|
self.controls.set_status(i18n._("analysis:region:start"), STATUS_INFO)
|
||||||
|
self.board_gui.selecting_region_of_interest = True
|
||||||
|
|
||||||
def _do_new_game_popup(self):
|
def _do_new_game_popup(self):
|
||||||
self.controls.timer.paused = True
|
self.controls.timer.paused = True
|
||||||
if not self.new_game_popup:
|
if not self.new_game_popup:
|
||||||
@@ -489,7 +493,7 @@ class KaTrainGui(Screen, KaTrainBase):
|
|||||||
"s": ("analyze-extra", "equalize"),
|
"s": ("analyze-extra", "equalize"),
|
||||||
"d": ("analyze-extra", "sweep"),
|
"d": ("analyze-extra", "sweep"),
|
||||||
"f": ("analyze-extra", "alternative"),
|
"f": ("analyze-extra", "alternative"),
|
||||||
"g": ("analyze-extra", "local"),
|
"g": ("select-box",),
|
||||||
"i": ("insert-mode",),
|
"i": ("insert-mode",),
|
||||||
"p": ("play", None),
|
"p": ("play", None),
|
||||||
"n": ("next-mistake",),
|
"n": ("next-mistake",),
|
||||||
|
|||||||
+9
-10
@@ -6,7 +6,7 @@ import subprocess
|
|||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
from typing import Callable, Dict, Optional
|
from typing import Callable, Dict, Optional, List
|
||||||
|
|
||||||
from kivy.utils import platform
|
from kivy.utils import platform
|
||||||
|
|
||||||
@@ -112,6 +112,7 @@ class KataGoEngine:
|
|||||||
self.terminate_query(query_id)
|
self.terminate_query(query_id)
|
||||||
self.queries = {}
|
self.queries = {}
|
||||||
|
|
||||||
|
|
||||||
def restart(self):
|
def restart(self):
|
||||||
self.queries = {}
|
self.queries = {}
|
||||||
self.shutdown(finish=False)
|
self.shutdown(finish=False)
|
||||||
@@ -249,7 +250,7 @@ class KataGoEngine:
|
|||||||
analyze_fast: bool = False,
|
analyze_fast: bool = False,
|
||||||
time_limit=True,
|
time_limit=True,
|
||||||
find_alternatives: bool = False,
|
find_alternatives: bool = False,
|
||||||
find_local: bool = False,
|
region_of_interest: Optional[List] = None,
|
||||||
priority: int = 0,
|
priority: int = 0,
|
||||||
ownership: Optional[bool] = None,
|
ownership: Optional[bool] = None,
|
||||||
next_move: Optional[GameNode] = None,
|
next_move: Optional[GameNode] = None,
|
||||||
@@ -278,22 +279,20 @@ class KataGoEngine:
|
|||||||
"untilDepth": 1,
|
"untilDepth": 1,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
elif find_local:
|
elif region_of_interest:
|
||||||
distance = 5
|
xmin, xmax, ymin, ymax = region_of_interest
|
||||||
last_move = analysis_node.move
|
|
||||||
if last_move is None or last_move.is_pass:
|
|
||||||
return
|
|
||||||
avoid = [
|
avoid = [
|
||||||
{
|
{
|
||||||
"moves": [
|
"moves": [
|
||||||
Move((x, y)).gtp()
|
Move((x, y)).gtp()
|
||||||
for x in range(0, size_x)
|
for x in range(0, size_x)
|
||||||
for y in range(0, size_y)
|
for y in range(0, size_y)
|
||||||
if max(abs(x - last_move.coords[0]), abs(y - last_move.coords[1])) > distance
|
if x < xmin or x > xmax or y < ymin or y > ymax
|
||||||
],
|
],
|
||||||
"player": analysis_node.next_player,
|
"player": player,
|
||||||
"untilDepth": 1,
|
"untilDepth": 10000,
|
||||||
}
|
}
|
||||||
|
for player in "BW"
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
avoid = []
|
avoid = []
|
||||||
|
|||||||
+19
-6
@@ -62,6 +62,8 @@ class Game:
|
|||||||
self.insert_mode = False
|
self.insert_mode = False
|
||||||
self.insert_after = None
|
self.insert_after = None
|
||||||
|
|
||||||
|
self.region_of_interest = None
|
||||||
|
|
||||||
if move_tree:
|
if move_tree:
|
||||||
self.root = move_tree
|
self.root = move_tree
|
||||||
self.komi = self.root.komi
|
self.komi = self.root.komi
|
||||||
@@ -233,7 +235,11 @@ class Game:
|
|||||||
played_node = self.current_node.play(move)
|
played_node = self.current_node.play(move)
|
||||||
self.current_node = played_node
|
self.current_node = played_node
|
||||||
if analyze:
|
if analyze:
|
||||||
played_node.analyze(self.engines[played_node.next_player])
|
if self.region_of_interest:
|
||||||
|
played_node.analyze(self.engines[played_node.next_player],analyze_fast=True)
|
||||||
|
played_node.analyze(self.engines[played_node.next_player],region_of_interest=self.region_of_interest)
|
||||||
|
else:
|
||||||
|
played_node.analyze(self.engines[played_node.next_player])
|
||||||
return played_node
|
return played_node
|
||||||
|
|
||||||
def set_current_node(self, node):
|
def set_current_node(self, node):
|
||||||
@@ -410,6 +416,17 @@ class Game:
|
|||||||
f.write(sgf)
|
f.write(sgf)
|
||||||
return i18n._("sgf written").format(file_name=filename)
|
return i18n._("sgf written").format(file_name=filename)
|
||||||
|
|
||||||
|
def set_region_of_interest(self,region_of_interest):
|
||||||
|
x1, x2, y1, y2 =region_of_interest
|
||||||
|
xmin, xmax = min(x1, x2), max(x1, x2)
|
||||||
|
ymin, ymax = min(y1, y2), max(y1, y2)
|
||||||
|
if not (xmin==xmax and ymin==ymax):
|
||||||
|
self.region_of_interest = [xmin,xmax,ymin,ymax]
|
||||||
|
else:
|
||||||
|
self.region_of_interest = None
|
||||||
|
self.katrain.controls.set_status("",OUTPUT_INFO)
|
||||||
|
|
||||||
|
|
||||||
def analyze_extra(self, mode, **kwargs):
|
def analyze_extra(self, mode, **kwargs):
|
||||||
stones = {s.coords for s in self.stones}
|
stones = {s.coords for s in self.stones}
|
||||||
cn = self.current_node
|
cn = self.current_node
|
||||||
@@ -426,7 +443,7 @@ class Game:
|
|||||||
visits = cn.analysis_visits_requested + engine.config["max_visits"]
|
visits = cn.analysis_visits_requested + engine.config["max_visits"]
|
||||||
self.katrain.controls.set_status(i18n._("extra analysis").format(visits=visits), STATUS_ANALYSIS)
|
self.katrain.controls.set_status(i18n._("extra analysis").format(visits=visits), STATUS_ANALYSIS)
|
||||||
self.katrain.controls.set_status(i18n._("extra analysis").format(visits=visits), STATUS_ANALYSIS)
|
self.katrain.controls.set_status(i18n._("extra analysis").format(visits=visits), STATUS_ANALYSIS)
|
||||||
cn.analyze(engine, visits=visits, priority=-1_000, time_limit=False)
|
cn.analyze(engine, visits=visits, priority=-1_000, region_of_interest=self.region_of_interest, time_limit=False)
|
||||||
return
|
return
|
||||||
if mode == "game":
|
if mode == "game":
|
||||||
nodes = self.root.nodes_in_tree
|
nodes = self.root.nodes_in_tree
|
||||||
@@ -467,10 +484,6 @@ class Game:
|
|||||||
visits = engine.config["fast_visits"]
|
visits = engine.config["fast_visits"]
|
||||||
self.katrain.controls.set_status(i18n._("sweep analysis").format(visits=visits), STATUS_ANALYSIS)
|
self.katrain.controls.set_status(i18n._("sweep analysis").format(visits=visits), STATUS_ANALYSIS)
|
||||||
priority = -1_000_000_000
|
priority = -1_000_000_000
|
||||||
elif mode == "local": # also do a quick update on current candidates so it doesn't look too weird
|
|
||||||
self.katrain.controls.set_status(i18n._("local analysis"), STATUS_ANALYSIS)
|
|
||||||
cn.analyze(engine, priority=-500, time_limit=False, find_local="local")
|
|
||||||
return
|
|
||||||
elif mode in ["equalize", "alternative", "local"]:
|
elif mode in ["equalize", "alternative", "local"]:
|
||||||
if not cn.analysis_complete and mode != "local":
|
if not cn.analysis_complete and mode != "local":
|
||||||
self.katrain.controls.set_status(i18n._("wait-before-equalize"), STATUS_INFO, self.current_node)
|
self.katrain.controls.set_status(i18n._("wait-before-equalize"), STATUS_INFO, self.current_node)
|
||||||
|
|||||||
@@ -145,13 +145,14 @@ class GameNode(SGFNode):
|
|||||||
refine_move=None,
|
refine_move=None,
|
||||||
analyze_fast=False,
|
analyze_fast=False,
|
||||||
find_alternatives=False,
|
find_alternatives=False,
|
||||||
find_local=False,
|
region_of_interest = None,
|
||||||
report_every=0.25,
|
report_every=0.25,
|
||||||
):
|
):
|
||||||
|
additional_moves = bool(find_alternatives or region_of_interest)
|
||||||
engine.request_analysis(
|
engine.request_analysis(
|
||||||
self,
|
self,
|
||||||
callback=lambda result, partial_result: self.set_analysis(
|
callback=lambda result, partial_result: self.set_analysis(
|
||||||
result, refine_move, find_alternatives or find_local, partial_result
|
result, refine_move, additional_moves, partial_result
|
||||||
),
|
),
|
||||||
priority=priority,
|
priority=priority,
|
||||||
visits=visits,
|
visits=visits,
|
||||||
@@ -159,7 +160,7 @@ class GameNode(SGFNode):
|
|||||||
time_limit=time_limit,
|
time_limit=time_limit,
|
||||||
next_move=refine_move,
|
next_move=refine_move,
|
||||||
find_alternatives=find_alternatives,
|
find_alternatives=find_alternatives,
|
||||||
find_local=find_local,
|
region_of_interest=region_of_interest,
|
||||||
report_every=report_every,
|
report_every=report_every,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -751,13 +751,13 @@
|
|||||||
shortcut: 'f'
|
shortcut: 'f'
|
||||||
on_action: root.katrain("analyze-extra", "alternative")
|
on_action: root.katrain("analyze-extra", "alternative")
|
||||||
AnalysisMenuItem:
|
AnalysisMenuItem:
|
||||||
text: i18n._("analysis:local")
|
text: i18n._("analysis:region")
|
||||||
icon: 'img/local.png'
|
icon: 'img/local.png'
|
||||||
shortcut: 'g'
|
shortcut: 'g'
|
||||||
on_action: root.katrain("analyze-extra", "local")
|
on_action: root.katrain("select-box",)
|
||||||
AnalysisMenuItem:
|
AnalysisMenuItem:
|
||||||
text: i18n._("analysis:insert")
|
text: i18n._("analysis:insert")
|
||||||
icon: 'img/local.png'
|
icon: 'img/insert.png'
|
||||||
shortcut: 'i'
|
shortcut: 'i'
|
||||||
on_action: root.katrain("insert-mode")
|
on_action: root.katrain("insert-mode")
|
||||||
AnalysisMenuItem:
|
AnalysisMenuItem:
|
||||||
|
|||||||
+70
-19
@@ -48,6 +48,9 @@ class BadukPanWidget(Widget):
|
|||||||
self.gridpos_y = []
|
self.gridpos_y = []
|
||||||
self.grid_size = 0
|
self.grid_size = 0
|
||||||
self.stone_size = 0
|
self.stone_size = 0
|
||||||
|
self.selecting_region_of_interest = False
|
||||||
|
self.region_of_interest = []
|
||||||
|
|
||||||
self.active_pv_moves = []
|
self.active_pv_moves = []
|
||||||
self.animating_pv = None
|
self.animating_pv = None
|
||||||
self.last_mouse_pos = (0, 0)
|
self.last_mouse_pos = (0, 0)
|
||||||
@@ -57,6 +60,12 @@ class BadukPanWidget(Widget):
|
|||||||
self.bind(size=self.redraw_trigger, pos=self.redraw_trigger)
|
self.bind(size=self.redraw_trigger, pos=self.redraw_trigger)
|
||||||
Clock.schedule_interval(self.animate_pv, 0.1)
|
Clock.schedule_interval(self.animate_pv, 0.1)
|
||||||
|
|
||||||
|
def play_stone_sound(self, *_args):
|
||||||
|
if self.katrain.config("timer/sound"):
|
||||||
|
sound = random.choice(self.stones_sounds)
|
||||||
|
if sound:
|
||||||
|
sound.play()
|
||||||
|
|
||||||
# stone placement functions
|
# stone placement functions
|
||||||
def _find_closest(self, pos, gridpos):
|
def _find_closest(self, pos, gridpos):
|
||||||
return sorted([(abs(p - pos), i) for i, p in enumerate(gridpos)])[0]
|
return sorted([(abs(p - pos), i) for i, p in enumerate(gridpos)])[0]
|
||||||
@@ -74,23 +83,42 @@ class BadukPanWidget(Widget):
|
|||||||
if prev_ghost != self.ghost_stone:
|
if prev_ghost != self.ghost_stone:
|
||||||
self.draw_hover_contents()
|
self.draw_hover_contents()
|
||||||
|
|
||||||
|
def update_box_selection(self, touch, second_point=True):
|
||||||
|
if not self.gridpos_x:
|
||||||
|
return
|
||||||
|
_, xp = self._find_closest(touch.x, self.gridpos_x)
|
||||||
|
_, yp = self._find_closest(touch.y, self.gridpos_y)
|
||||||
|
if second_point and len(self.region_of_interest) == 4:
|
||||||
|
self.region_of_interest[1] = xp
|
||||||
|
self.region_of_interest[3] = yp
|
||||||
|
else:
|
||||||
|
self.region_of_interest = [xp, xp, yp, yp]
|
||||||
|
self.draw_hover_contents()
|
||||||
|
|
||||||
def on_touch_down(self, touch):
|
def on_touch_down(self, touch):
|
||||||
self.set_animating_pv(None, None) # any click kills PV from label/move
|
self.set_animating_pv(None, None) # any click kills PV from label/move
|
||||||
if "button" in touch.profile and touch.button != "left":
|
if "button" in touch.profile and touch.button != "left":
|
||||||
return
|
return
|
||||||
self.check_next_move_ghost(touch)
|
if self.selecting_region_of_interest:
|
||||||
|
self.update_box_selection(touch, second_point=False)
|
||||||
|
else:
|
||||||
|
self.check_next_move_ghost(touch)
|
||||||
|
|
||||||
def on_touch_move(self, touch):
|
def on_touch_move(self, touch):
|
||||||
if "button" in touch.profile and touch.button != "left":
|
if "button" in touch.profile and touch.button != "left":
|
||||||
return
|
return
|
||||||
return self.check_next_move_ghost(touch)
|
if self.selecting_region_of_interest:
|
||||||
|
return self.update_box_selection(touch)
|
||||||
|
else:
|
||||||
|
return self.check_next_move_ghost(touch)
|
||||||
|
|
||||||
def on_mouse_pos(self, *args): # https://gist.github.com/opqopq/15c707dc4cffc2b6455f
|
def on_mouse_pos(self, *args): # https://gist.github.com/opqopq/15c707dc4cffc2b6455f
|
||||||
if self.get_root_window(): # don't proceed if I'm not displayed <=> If have no parent
|
if self.get_root_window(): # don't proceed if I'm not displayed <=> If have no parent
|
||||||
pos = args[1]
|
pos = args[1]
|
||||||
rel_pos = self.to_widget(*pos) # compensate for relative layout
|
rel_pos = self.to_widget(*pos) # compensate for relative layout
|
||||||
inside = self.collide_point(*rel_pos)
|
inside = self.collide_point(*rel_pos)
|
||||||
if inside and self.active_pv_moves:
|
|
||||||
|
if inside and self.active_pv_moves and not self.selecting_region_of_interest:
|
||||||
near_move = [
|
near_move = [
|
||||||
(pv, node)
|
(pv, node)
|
||||||
for move, pv, node in self.active_pv_moves
|
for move, pv, node in self.active_pv_moves
|
||||||
@@ -109,17 +137,17 @@ class BadukPanWidget(Widget):
|
|||||||
self.set_animating_pv(None, None) # any click kills PV from label/move
|
self.set_animating_pv(None, None) # any click kills PV from label/move
|
||||||
self.last_mouse_pos = pos
|
self.last_mouse_pos = pos
|
||||||
|
|
||||||
def play_stone_sound(self, *_args):
|
|
||||||
if self.katrain.config("timer/sound"):
|
|
||||||
sound = random.choice(self.stones_sounds)
|
|
||||||
if sound:
|
|
||||||
sound.play()
|
|
||||||
|
|
||||||
def on_touch_up(self, touch):
|
def on_touch_up(self, touch):
|
||||||
if ("button" in touch.profile and touch.button != "left") or not self.gridpos_x:
|
if ("button" in touch.profile and touch.button != "left") or not self.gridpos_x:
|
||||||
return
|
return
|
||||||
katrain = self.katrain
|
katrain = self.katrain
|
||||||
if self.ghost_stone and ("button" not in touch.profile or touch.button == "left"):
|
if self.selecting_region_of_interest:
|
||||||
|
if len(self.region_of_interest) == 4:
|
||||||
|
self.katrain.game.set_region_of_interest(self.region_of_interest)
|
||||||
|
self.region_of_interest = []
|
||||||
|
self.selecting_region_of_interest = False
|
||||||
|
|
||||||
|
elif self.ghost_stone and ("button" not in touch.profile or touch.button == "left"):
|
||||||
game = self.katrain and self.katrain.game
|
game = self.katrain and self.katrain.game
|
||||||
current_node = game and self.katrain.game.current_node
|
current_node = game and self.katrain.game.current_node
|
||||||
if (
|
if (
|
||||||
@@ -429,6 +457,20 @@ class BadukPanWidget(Widget):
|
|||||||
|
|
||||||
self.draw_hover_contents()
|
self.draw_hover_contents()
|
||||||
|
|
||||||
|
def draw_roi_box(self,region_of_interest,width=2):
|
||||||
|
xmin, xmax, ymin, ymax = region_of_interest
|
||||||
|
Color(*LIGHTER_BACKGROUND_COLOR)
|
||||||
|
Line(
|
||||||
|
rectangle=(
|
||||||
|
self.gridpos_x[xmin] - self.grid_size/6,
|
||||||
|
self.gridpos_y[ymin] - self.grid_size/6,
|
||||||
|
(xmax - xmin + 1/3) * self.grid_size,
|
||||||
|
(ymax - ymin + 1/3) * self.grid_size,
|
||||||
|
),
|
||||||
|
dash_length=10,dash_offset=10,
|
||||||
|
width=width,
|
||||||
|
)
|
||||||
|
|
||||||
def draw_hover_contents(self, *_args):
|
def draw_hover_contents(self, *_args):
|
||||||
ghost_alpha = POLICY_ALPHA
|
ghost_alpha = POLICY_ALPHA
|
||||||
katrain = self.katrain
|
katrain = self.katrain
|
||||||
@@ -442,6 +484,7 @@ class BadukPanWidget(Widget):
|
|||||||
|
|
||||||
with self.canvas.after:
|
with self.canvas.after:
|
||||||
self.canvas.after.clear()
|
self.canvas.after.clear()
|
||||||
|
|
||||||
self.active_pv_moves = []
|
self.active_pv_moves = []
|
||||||
# hints or PV
|
# hints or PV
|
||||||
hint_moves = []
|
hint_moves = []
|
||||||
@@ -582,16 +625,24 @@ class BadukPanWidget(Widget):
|
|||||||
width=dp(1.2),
|
width=dp(1.2),
|
||||||
)
|
)
|
||||||
|
|
||||||
# hover next move ghost stone
|
if self.selecting_region_of_interest and len(self.region_of_interest) == 4:
|
||||||
if self.ghost_stone:
|
x1, x2, y1, y2 = self.region_of_interest
|
||||||
self.draw_stone(*self.ghost_stone, next_player, alpha=ghost_alpha)
|
self.draw_roi_box([min(x1, x2), max(x1, x2), min(y1, y2), max(y1, y2)],width=2)
|
||||||
|
else:
|
||||||
|
# hover next move ghost stone
|
||||||
|
if self.ghost_stone:
|
||||||
|
self.draw_stone(*self.ghost_stone, next_player, alpha=ghost_alpha)
|
||||||
|
|
||||||
|
animating_pv = self.animating_pv
|
||||||
|
if animating_pv:
|
||||||
|
pv, node, start_time, _ = animating_pv
|
||||||
|
delay = self.katrain.config("general/anim_pv_time", 0.5)
|
||||||
|
up_to_move = (time.time() - start_time) / delay
|
||||||
|
self.draw_pv(pv, node, up_to_move)
|
||||||
|
|
||||||
|
if self.katrain.game.region_of_interest:
|
||||||
|
self.draw_roi_box(self.katrain.game.region_of_interest, width=1) # dashed
|
||||||
|
|
||||||
animating_pv = self.animating_pv
|
|
||||||
if animating_pv:
|
|
||||||
pv, node, start_time, _ = animating_pv
|
|
||||||
delay = self.katrain.config("general/anim_pv_time", 0.5)
|
|
||||||
up_to_move = (time.time() - start_time) / delay
|
|
||||||
self.draw_pv(pv, node, up_to_move)
|
|
||||||
|
|
||||||
def animate_pv(self, _dt):
|
def animate_pv(self, _dt):
|
||||||
if self.animating_pv:
|
if self.animating_pv:
|
||||||
|
|||||||
Binary file not shown.
@@ -657,9 +657,6 @@ msgstr ""
|
|||||||
msgid "ai:simple"
|
msgid "ai:simple"
|
||||||
msgstr "简明风格"
|
msgstr "简明风格"
|
||||||
|
|
||||||
msgid "analysis:local"
|
|
||||||
msgstr "寻找局部走法"
|
|
||||||
|
|
||||||
msgid "local analysis"
|
msgid "local analysis"
|
||||||
msgstr "正在寻找局部走法"
|
msgstr "正在寻找局部走法"
|
||||||
|
|
||||||
@@ -739,3 +736,20 @@ msgstr "Inserting exchange(s) done, copied {num_copied} following moves."
|
|||||||
msgid "finish inserting before navigating"
|
msgid "finish inserting before navigating"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
||||||
|
|
||||||
|
#. TODO - in new game options
|
||||||
|
msgid "player names"
|
||||||
|
msgstr "Player Names"
|
||||||
|
|
||||||
|
#. TODO - Option in dropdown to insert some moves between the current and next
|
||||||
|
msgid "analysis:insert"
|
||||||
|
msgstr "Insert moves"
|
||||||
|
|
||||||
|
#. TODO - Status message
|
||||||
|
msgid "analysis:region:start"
|
||||||
|
msgstr ""
|
||||||
|
"Drag to select the region of interest. Selecting a single point removes it."
|
||||||
|
|
||||||
|
#. TODO - Restrict analysis to a specific region
|
||||||
|
msgid "analysis:region"
|
||||||
|
msgstr "Set region of interest"
|
||||||
Binary file not shown.
@@ -707,9 +707,6 @@ msgstr ""
|
|||||||
msgid "ai:simple"
|
msgid "ai:simple"
|
||||||
msgstr "Einfacher Stil"
|
msgstr "Einfacher Stil"
|
||||||
|
|
||||||
msgid "analysis:local"
|
|
||||||
msgstr "Finde lokale Antworten"
|
|
||||||
|
|
||||||
msgid "local analysis"
|
msgid "local analysis"
|
||||||
msgstr "Suche nach lokalen Antworten"
|
msgstr "Suche nach lokalen Antworten"
|
||||||
|
|
||||||
@@ -791,3 +788,20 @@ msgstr "Inserting exchange(s) done, copied {num_copied} following moves."
|
|||||||
msgid "finish inserting before navigating"
|
msgid "finish inserting before navigating"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
||||||
|
|
||||||
|
#. TODO - in new game options
|
||||||
|
msgid "player names"
|
||||||
|
msgstr "Player Names"
|
||||||
|
|
||||||
|
#. TODO - Option in dropdown to insert some moves between the current and next
|
||||||
|
msgid "analysis:insert"
|
||||||
|
msgstr "Insert moves"
|
||||||
|
|
||||||
|
#. TODO - Status message
|
||||||
|
msgid "analysis:region:start"
|
||||||
|
msgstr ""
|
||||||
|
"Drag to select the region of interest. Selecting a single point removes it."
|
||||||
|
|
||||||
|
#. TODO - Restrict analysis to a specific region
|
||||||
|
msgid "analysis:region"
|
||||||
|
msgstr "Set region of interest"
|
||||||
Binary file not shown.
@@ -109,9 +109,14 @@ msgstr "Deeper full game analysis"
|
|||||||
msgid "analysis:alternatives"
|
msgid "analysis:alternatives"
|
||||||
msgstr "Find alternative moves"
|
msgstr "Find alternative moves"
|
||||||
|
|
||||||
#. Analyze again but allow only nearby moves
|
#. Restrict analysis to a specific region
|
||||||
msgid "analysis:local"
|
msgid "analysis:region"
|
||||||
msgstr "Find local responses"
|
msgstr "Set region of interest"
|
||||||
|
|
||||||
|
#. Status message
|
||||||
|
msgid "analysis:region:start"
|
||||||
|
msgstr ""
|
||||||
|
"Drag to select the region of interest. Selecting a single point removes it."
|
||||||
|
|
||||||
#. Keep improving current position analysis when there is nothing else to do
|
#. Keep improving current position analysis when there is nothing else to do
|
||||||
msgid "analysis:continuous"
|
msgid "analysis:continuous"
|
||||||
@@ -120,6 +125,10 @@ msgstr "Toggle continuous analysis"
|
|||||||
msgid "analysis:aimove"
|
msgid "analysis:aimove"
|
||||||
msgstr "Force AI Move"
|
msgstr "Force AI Move"
|
||||||
|
|
||||||
|
#. Option in dropdown to insert some moves between the current and next
|
||||||
|
msgid "analysis:insert"
|
||||||
|
msgstr "Insert moves"
|
||||||
|
|
||||||
#. status message
|
#. status message
|
||||||
msgid "extra analysis"
|
msgid "extra analysis"
|
||||||
msgstr "Performing additional analysis to {visits} visits"
|
msgstr "Performing additional analysis to {visits} visits"
|
||||||
@@ -343,6 +352,10 @@ msgstr "Update Timer"
|
|||||||
msgid "New Game title"
|
msgid "New Game title"
|
||||||
msgstr "Setup New Game"
|
msgstr "Setup New Game"
|
||||||
|
|
||||||
|
#. in new game options
|
||||||
|
msgid "player names"
|
||||||
|
msgstr "Player Names"
|
||||||
|
|
||||||
msgid "board size"
|
msgid "board size"
|
||||||
msgstr "Board size"
|
msgstr "Board size"
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -713,10 +713,6 @@ msgstr "Plays moves that lead to simplifying the board state."
|
|||||||
msgid "ai:simple"
|
msgid "ai:simple"
|
||||||
msgstr "Simple Style"
|
msgstr "Simple Style"
|
||||||
|
|
||||||
#. TODO - Analyze again but allow only nearby moves
|
|
||||||
msgid "analysis:local"
|
|
||||||
msgstr "Find local responses"
|
|
||||||
|
|
||||||
#. TODO - status message
|
#. TODO - status message
|
||||||
msgid "local analysis"
|
msgid "local analysis"
|
||||||
msgstr "Searching for local responses"
|
msgstr "Searching for local responses"
|
||||||
@@ -799,3 +795,20 @@ msgstr "Inserting exchange(s) done, copied {num_copied} following moves."
|
|||||||
msgid "finish inserting before navigating"
|
msgid "finish inserting before navigating"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
||||||
|
|
||||||
|
#. TODO - in new game options
|
||||||
|
msgid "player names"
|
||||||
|
msgstr "Player Names"
|
||||||
|
|
||||||
|
#. TODO - Option in dropdown to insert some moves between the current and next
|
||||||
|
msgid "analysis:insert"
|
||||||
|
msgstr "Insert moves"
|
||||||
|
|
||||||
|
#. TODO - Status message
|
||||||
|
msgid "analysis:region:start"
|
||||||
|
msgstr ""
|
||||||
|
"Drag to select the region of interest. Selecting a single point removes it."
|
||||||
|
|
||||||
|
#. TODO - Restrict analysis to a specific region
|
||||||
|
msgid "analysis:region"
|
||||||
|
msgstr "Set region of interest"
|
||||||
Binary file not shown.
@@ -743,9 +743,6 @@ msgstr ""
|
|||||||
msgid "ai:simple"
|
msgid "ai:simple"
|
||||||
msgstr "Modéré"
|
msgstr "Modéré"
|
||||||
|
|
||||||
msgid "analysis:local"
|
|
||||||
msgstr "Proposer des coups locaux"
|
|
||||||
|
|
||||||
msgid "local analysis"
|
msgid "local analysis"
|
||||||
msgstr "Recherche de coups locaux."
|
msgstr "Recherche de coups locaux."
|
||||||
|
|
||||||
@@ -825,3 +822,20 @@ msgstr "Inserting exchange(s) done, copied {num_copied} following moves."
|
|||||||
msgid "finish inserting before navigating"
|
msgid "finish inserting before navigating"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
||||||
|
|
||||||
|
#. TODO - in new game options
|
||||||
|
msgid "player names"
|
||||||
|
msgstr "Player Names"
|
||||||
|
|
||||||
|
#. TODO - Option in dropdown to insert some moves between the current and next
|
||||||
|
msgid "analysis:insert"
|
||||||
|
msgstr "Insert moves"
|
||||||
|
|
||||||
|
#. TODO - Status message
|
||||||
|
msgid "analysis:region:start"
|
||||||
|
msgstr ""
|
||||||
|
"Drag to select the region of interest. Selecting a single point removes it."
|
||||||
|
|
||||||
|
#. TODO - Restrict analysis to a specific region
|
||||||
|
msgid "analysis:region"
|
||||||
|
msgstr "Set region of interest"
|
||||||
Binary file not shown.
@@ -698,10 +698,6 @@ msgstr ""
|
|||||||
msgid "ai:simple"
|
msgid "ai:simple"
|
||||||
msgstr "簡明派"
|
msgstr "簡明派"
|
||||||
|
|
||||||
#. Analyze again but allow only nearby moves
|
|
||||||
msgid "analysis:local"
|
|
||||||
msgstr "近辺の応手に絞って分析"
|
|
||||||
|
|
||||||
#. status message
|
#. status message
|
||||||
msgid "local analysis"
|
msgid "local analysis"
|
||||||
msgstr "近辺の応手を分析中"
|
msgstr "近辺の応手を分析中"
|
||||||
@@ -783,3 +779,20 @@ msgstr "Inserting exchange done and copied {num_copied} following moves."
|
|||||||
msgid "finish inserting before navigating"
|
msgid "finish inserting before navigating"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
||||||
|
|
||||||
|
#. TODO - in new game options
|
||||||
|
msgid "player names"
|
||||||
|
msgstr "Player Names"
|
||||||
|
|
||||||
|
#. TODO - Option in dropdown to insert some moves between the current and next
|
||||||
|
msgid "analysis:insert"
|
||||||
|
msgstr "Insert moves"
|
||||||
|
|
||||||
|
#. TODO - Status message
|
||||||
|
msgid "analysis:region:start"
|
||||||
|
msgstr ""
|
||||||
|
"Drag to select the region of interest. Selecting a single point removes it."
|
||||||
|
|
||||||
|
#. TODO - Restrict analysis to a specific region
|
||||||
|
msgid "analysis:region"
|
||||||
|
msgstr "Set region of interest"
|
||||||
Binary file not shown.
@@ -671,9 +671,6 @@ msgstr ""
|
|||||||
msgid "ai:simple"
|
msgid "ai:simple"
|
||||||
msgstr "간명한 기풍"
|
msgstr "간명한 기풍"
|
||||||
|
|
||||||
msgid "analysis:local"
|
|
||||||
msgstr "국지적인 응수 찾기"
|
|
||||||
|
|
||||||
msgid "local analysis"
|
msgid "local analysis"
|
||||||
msgstr "국지적인 응수를 찾고 있습니다"
|
msgstr "국지적인 응수를 찾고 있습니다"
|
||||||
|
|
||||||
@@ -753,3 +750,19 @@ msgstr "Inserting exchange(s) done, copied {num_copied} following moves."
|
|||||||
msgid "finish inserting before navigating"
|
msgid "finish inserting before navigating"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
||||||
|
|
||||||
|
#. TODO - in new game options
|
||||||
|
msgid "player names"
|
||||||
|
msgstr "Player Names"
|
||||||
|
|
||||||
|
#. TODO - Option in dropdown to insert some moves between the current and next
|
||||||
|
msgid "analysis:insert"
|
||||||
|
msgstr "Insert moves"
|
||||||
|
|
||||||
|
#. TODO - Status message
|
||||||
|
msgid "analysis:region:start"
|
||||||
|
msgstr "Drag to select the region of interest."
|
||||||
|
|
||||||
|
#. TODO - Restrict analysis to a specific region
|
||||||
|
msgid "analysis:region"
|
||||||
|
msgstr "Set region of interest"
|
||||||
Binary file not shown.
@@ -706,9 +706,6 @@ msgstr ""
|
|||||||
msgid "ai:simple"
|
msgid "ai:simple"
|
||||||
msgstr "Простой стиль"
|
msgstr "Простой стиль"
|
||||||
|
|
||||||
msgid "analysis:local"
|
|
||||||
msgstr "Найти локальные ответы"
|
|
||||||
|
|
||||||
msgid "local analysis"
|
msgid "local analysis"
|
||||||
msgstr "Поиск локальных ответов"
|
msgstr "Поиск локальных ответов"
|
||||||
|
|
||||||
@@ -788,3 +785,20 @@ msgstr "Inserting exchange(s) done, copied {num_copied} following moves."
|
|||||||
msgid "finish inserting before navigating"
|
msgid "finish inserting before navigating"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
"Navigation is disabled in insert mode, finish insert mode by pressing 'i'. "
|
||||||
|
|
||||||
|
#. TODO - in new game options
|
||||||
|
msgid "player names"
|
||||||
|
msgstr "Player Names"
|
||||||
|
|
||||||
|
#. TODO - Option in dropdown to insert some moves between the current and next
|
||||||
|
msgid "analysis:insert"
|
||||||
|
msgstr "Insert moves"
|
||||||
|
|
||||||
|
#. TODO - Status message
|
||||||
|
msgid "analysis:region:start"
|
||||||
|
msgstr ""
|
||||||
|
"Drag to select the region of interest. Selecting a single point removes it."
|
||||||
|
|
||||||
|
#. TODO - Restrict analysis to a specific region
|
||||||
|
msgid "analysis:region"
|
||||||
|
msgstr "Set region of interest"
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
+4
-12
@@ -310,17 +310,9 @@
|
|||||||
DescriptionLabel:
|
DescriptionLabel:
|
||||||
font_size: DESC_FONT_SIZE * 0.8
|
font_size: DESC_FONT_SIZE * 0.8
|
||||||
text: i18n._("show stats if")
|
text: i18n._("show stats if")
|
||||||
BoxLayout:
|
AnchorLayout:
|
||||||
Label:
|
LabelledIntInput:
|
||||||
text: '>'
|
input_property: "trainer/low_visits"
|
||||||
size_hint: 0.1, 1
|
|
||||||
AnchorLayout:
|
|
||||||
LabelledIntInput:
|
|
||||||
input_property: "trainer/low_visits"
|
|
||||||
Label:
|
|
||||||
size_hint: 0.1, 1
|
|
||||||
text: i18n._('visits')
|
|
||||||
Label:
|
|
||||||
DescriptionLabel:
|
DescriptionLabel:
|
||||||
font_size: DESC_FONT_SIZE * 0.8
|
font_size: DESC_FONT_SIZE * 0.8
|
||||||
text: i18n._("show ai dots")
|
text: i18n._("show ai dots")
|
||||||
@@ -396,7 +388,7 @@
|
|||||||
spacing: CP_SPACING
|
spacing: CP_SPACING
|
||||||
padding: CP_PADDING
|
padding: CP_PADDING
|
||||||
DescriptionLabel:
|
DescriptionLabel:
|
||||||
text: i18n._("names")
|
text: i18n._("player names")
|
||||||
AnchorLayout:
|
AnchorLayout:
|
||||||
LabelledTextInput:
|
LabelledTextInput:
|
||||||
text: ''
|
text: ''
|
||||||
|
|||||||
Reference in new issue
Block a user