fewer dots by default (default off with 3 dots)

This commit is contained in:
Sander Land committed 2020-02-23 22:11:51 +01:00
1 parent 7ab37694d9
commit 2cce7ed4af
6 files changed
+47 -39

No files matched your search

+19 -14
View File
@@ -1,18 +1,18 @@
Introduction Introduction
============ ============
This repository contains tool for playing go with AI feedback aimed at kyu players. This repository contains tool for playing go with AI feedback.
The idea is to give immediate feedback on the many large mistakes we make in terms of inefficient moves. The idea is to give immediate feedback on the many large mistakes we make in terms of inefficient moves.
It is based on the KataGo AI and relies heavily on score estimation rather than win rate. It is based on the KataGo AI and relies heavily on score estimation rather than win rate.
Some uses include: Some uses include:
* Analyze your games to find the moves that were most costly in terms of points lost. * Review your games to find the moves that were most costly in terms of points lost.
* Play against AI and get immediate feedback on mistakes with option to retry. * Play against AI and get immediate feedback on mistakes with option to retry.
* Play against a stronger player and use the retry option instead of handicap stones. * Play against a stronger player and use the retry option instead of handicap stones.
* Play a match with an evenly matched friend where both players get instant feedback. * Play a match with an evenly matched friend where both players get instant feedback.
![screenshot](https://i.imgur.com/2T2b6qL.png) ![screenshot](https://imgur.com/t3Im6Xu.png)
Manual Manual
====== ======
@@ -24,7 +24,7 @@ Installation for Windows users
* Execute the command 'pip install kivy' * Execute the command 'pip install kivy'
* Start the app by running `python katrain.py` in the directory where you downloaded the scripts. Note that the program can be slow to initialize the first time, due to kata's gpu tuning. * Start the app by running `python katrain.py` in the directory where you downloaded the scripts. Note that the program can be slow to initialize the first time, due to kata's gpu tuning.
Installation for linux/Mac users Installation for Linux/Mac users
-------------------------------- --------------------------------
* This assumed you have a working Python 3.6/3.7 installation, use pip3/python3 etc. if your default is python 2. Kivy currently does not have a release for Python 3.8. * This assumed you have a working Python 3.6/3.7 installation, use pip3/python3 etc. if your default is python 2. Kivy currently does not have a release for Python 3.8.
* pip install kivy * pip install kivy
@@ -35,14 +35,14 @@ Installation for linux/Mac users
Options Options
------- -------
* Check box options * Check box options
* Eval: show the coloured dots on the moves for this player. * All Eval: show the coloured dots on all the moves for this player.
* Hints: show suggested moves for this player. * Hints: show suggested moves for this player and output more statistics on moves.
* Undo: automatically undo poor moves for this player and make them try again. * Undo: automatically undo poor moves for this player and make them try again.
* AI: let the AI control this player. Check both for self-play. * AI: let the AI control this player. Check both for self-play.
* Show owner: show expected control of territory. * Show owner: show expected control of territory.
* Lock AI: disallow extra undos, changing hints options, changing auto move, or AI move. Also turns off the option to click on a move to see detailed comments. * Lock AI: disallow extra undos, changing hints options, changing auto move, or AI move. Also turns off the option to click on a move to see detailed comments.
* Fast: use a lower number of max visits for evaluation/AI move. * Fast: use a lower number of max visits for evaluation/AI move.
* Balance score: Deliberately make sub-optimal moves as the AI in an attempt to balance the score towawrds a slight win. * Balance score: Deliberately make sub-optimal moves as the AI in an attempt to balance the score towards a slight win.
* Temperature/Evaluation/Score: Not that these fields can be hidden by clicking on the text. * Temperature/Evaluation/Score: Not that these fields can be hidden by clicking on the text.
* Temperature is the point difference between passing and the best move. * Temperature is the point difference between passing and the best move.
@@ -88,14 +88,19 @@ Configuration
`config.json` has a number of options, many of them are stylistic, but also including the command kata is started with (and so the kata config and model). `config.json` has a number of options, many of them are stylistic, but also including the command kata is started with (and so the kata config and model).
You can use `python katrain.py your_config_file.json` to use another config file instead. You can use `python katrain.py your_config_file.json` to use another config file instead.
The `trainer` block has the following options to tweak: The `trainer` block has the following options to tweak for engine assisted play and reviewing:
* `eval_off_show_last`: when the `eval` checkbox is off for a player, show coloured dots on the last this many moves regardless.
* `undo_eval_threshold`, `undo_point_threshold`: prompt player to undo if move is worse than this in terms of points AND evaluation.
* `num_undo_prompts`: automatically undo bad moves when `undo` is on at most this many times. Can be a fraction like 0.5 for 50% chance of being granted an undo on a bad move.
* `dont_lock_undos`: don't lock the undo button when `ai lock` is active.
The following options are relevant for the `balance score` AI play mode.
* `balance_play_target_score`: indicates how many points the AI aims to win by when using 'balance score'. * `balance_play_target_score`: indicates how many points the AI aims to win by when using 'balance score'.
* `balance_play_randomize_eval`: when not needing to balance score, the AI will pick a random move which is at least this good as long as it stays ahead. * `balance_play_randomize_eval`: when not needing to balance score, the AI will pick a random move which is at least this good as long as it stays ahead.
* `balance_play_min_eval`: when needing to balance score, the AI will pick a move which is at least this good. * `balance_play_min_eval`: when needing to balance score, the AI will pick a move which is at least this good.
* `balance_play_min_visits`: never pick a move with fewer playouts than this. * `balance_play_min_visits`: never pick a move with fewer playouts than this.
* `undo_eval_threshold`, `undo_point_threshold`: prompt player to undo if move is worse than this in terms of points AND evaluation.
* `num_undo_prompts`: automatically undo bad moves when `undo` is on at most this many times. Can be a fraction like 0.5 for 50% chance of being granted an undo on a bad move.
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). 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).
@@ -104,13 +109,13 @@ FAQ
* The program is slow to start! * The program is slow to start!
* The first startup of KataGo can be slow, after that it should be much faster. * The first startup of KataGo can be slow, after that it should be much faster.
* The program is running too slowly! * The program is running too slowly!
* Lower the visits count in `config.json` by half or so and try again. * Lower the visits count in the `analysis` block of `config.json` by half or so and try again.
* Why are the dots changing colour?
* If the next move made is the predicted top move, more information is available to analyze the previous move and this is used to update the evaluation.
* Can I play on sizes other than 9, 13 or 19? * 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. * Type in `SZ[n]HA[h]KM[k]` in the text box and hit 'load' for a game on a n by n board with h handicap stones and k komi, but note that the default KataGo does not support sizes above 19x19.
Contributing Contributing
============ ============
* Feedback and pull requests are both very welcome. * Feedback and pull requests are both very welcome.
* For suggestions and planned improvements, see the 'issues' tab on github. * For suggestions and planned improvements, see the 'issues' tab on github.
+11 -11
View File
@@ -98,18 +98,18 @@ class Move:
if prev_temperature < 0.5: if prev_temperature < 0.5:
text += f"Previous temperature ({prev_temperature:.1f}) too low for evaluation\n" text += f"Previous temperature ({prev_temperature:.1f}) too low for evaluation\n"
elif not self.is_pass and self.parent.analysis[0]["move"] != self.gtp(): elif not self.is_pass and self.parent.analysis[0]["move"] != self.gtp():
if sgf or eval: if sgf: # shown in stats anyway
outdated_evaluation = self.outdated_evaluation
text += f"Evaluation: {self.evaluation:.1%} efficient\n" text += f"Evaluation: {self.evaluation:.1%} efficient\n"
if outdated_evaluation and outdated_evaluation > self.evaluation and outdated_evaluation > self.evaluation + 0.05: outdated_evaluation = self.outdated_evaluation
text += f"(Was considered last move as {outdated_evaluation:.0%})\n" if outdated_evaluation and outdated_evaluation > self.evaluation and outdated_evaluation > self.evaluation + 0.05:
points_lost = self.player_sign * (prev_best_score - score) text += f"(Was considered last move as {outdated_evaluation:.0%})\n"
if points_lost > 0.5: points_lost = self.player_sign * (prev_best_score - score)
text += f"Estimated point loss: {points_lost:.1f}\n" if points_lost > 0.5:
if eval or sgf: # show undos on move itself in both sgf and while playing text += f"Estimated point loss: {points_lost:.1f}\n"
undids = [m.gtp() + (f"({m.evaluation_info[0]:.1%} efficient)" if m.evaluation_info[0] else "") for m in self.parent.children if m != self] if eval or sgf: # show undos on move itself in both sgf and while playing
if undids: undids = [m.gtp() + (f"({m.evaluation_info[0]:.1%} efficient)" if m.evaluation_info[0] else "") for m in self.parent.children if m != self]
text += "Other attempted move(s): " + ", ".join(undids) + "\n" if undids:
text += "Other attempted move(s): " + ", ".join(undids) + "\n"
else: else:
text = "No analysis available" if sgf else "Analyzing move..." text = "No analysis available" if sgf else "Analyzing move..."
return text return text
+6 -5
View File
@@ -1,9 +1,9 @@
{ {
"analysis": { "analysis": {
"pass_visits": 125, "pass_visits": 100,
"pass_visits_fast": 50, "pass_visits_fast": 25,
"visits": 2500, "visits": 2000,
"visits_fast": 1000 "visits_fast": 500
}, },
"board": { "board": {
"size": 19, "size": 19,
@@ -40,7 +40,8 @@
"undo_point_threshold": 1, "undo_point_threshold": 1,
"num_undo_prompts": 1, "num_undo_prompts": 1,
"sgf_show_best_move_threshold": 0.95, "sgf_show_best_move_threshold": 0.95,
"dont_lock_undos": false "dont_lock_undos": false,
"eval_off_show_last": 3
}, },
"debug": { "debug": {
"level": 1 "level": 1
+3 -3
View File
@@ -103,10 +103,10 @@ class EngineControls(GridLayout):
def update_evaluation(self): def update_evaluation(self):
current_move = self.board.current_move current_move = self.board.current_move
self.score.set_prisoners(self.board.prisoner_count) self.score.set_prisoners(self.board.prisoner_count)
if self.eval.active(current_move.player) and current_move is not self.board.root: if not self.ai_auto.active(current_move.player) and current_move is not self.board.root:
self.info.text = current_move.comment(eval=self.eval.active(current_move.player), hints=self.hints.active(current_move.player)) self.info.text = current_move.comment(eval=True, hints=self.hints.active(current_move.player))
self.evaluation.text = "" self.evaluation.text = ""
if self.eval.active(current_move.player): if not self.ai_auto.active(current_move.player):
self.show_evaluation_stats(current_move) self.show_evaluation_stats(current_move)
if current_move.analysis_ready and current_move.parent and current_move.parent.analysis_ready and not current_move.children and not current_move.x_comment: if current_move.analysis_ready and current_move.parent and current_move.parent.analysis_ready and not current_move.children and not current_move.x_comment:
+3 -3
View File
@@ -182,14 +182,14 @@
BWCheckBoxHint: BWCheckBoxHint:
size_hint: 0.2, 0.5 size_hint: 0.2, 0.5
id: eval id: eval
text: 'eval' text: 'all eval'
default_active: True default_active: False
on_active: root.parent.board.redraw() on_active: root.parent.board.redraw()
BWCheckBoxHint: BWCheckBoxHint:
size_hint: 0.2, 0.5 size_hint: 0.2, 0.5
id: hints id: hints
text: 'hints' text: 'hints'
on_active: root.parent.board.redraw() on_active: root.parent.board.engine.update_evaluation()
BWCheckBoxHint: BWCheckBoxHint:
size_hint: 0.2, 0.5 size_hint: 0.2, 0.5
id: auto_undo id: auto_undo
+5 -3
View File
@@ -126,12 +126,14 @@ class BadukPanWidget(Widget):
moves = self.engine.board.moves moves = self.engine.board.moves
last_move = moves[-1] if moves else self.engine.board.root last_move = moves[-1] if moves else self.engine.board.root
current_player = self.engine.board.current_player current_player = self.engine.board.current_player
eval_on = [self.engine.eval.active(0), self.engine.eval.active(1)] full_eval_on = [self.engine.eval.active(0), self.engine.eval.active(1)]
has_stone = {} has_stone = {}
last_few_moves = self.engine.board.moves[-Config.get("trainer").get("eval_off_show_last", 3) :]
for i, m in enumerate(self.engine.board.stones): for i, m in enumerate(self.engine.board.stones):
has_stone[m.coords] = m.player has_stone[m.coords] = m.player
eval, evalsize = m.evaluation_info eval, evalsize = m.evaluation_info
evalcol = self._eval_spectrum(eval) if eval_on[m.player] and eval and evalsize > Config.get("ui").get("min_eval_temperature", 0.5) else None move_eval_on = full_eval_on[m.player] or m in last_few_moves
evalcol = self._eval_spectrum(eval) if move_eval_on and eval and evalsize > Config.get("ui").get("min_eval_temperature", 0.5) else None
inner = COLORS[1 - m.player] if (m == last_move) else None inner = COLORS[1 - m.player] if (m == last_move) else None
self.draw_stone(m.coords[0], m.coords[1], COLORS[m.player], inner, evalcol, evalsize) self.draw_stone(m.coords[0], m.coords[1], COLORS[m.player], inner, evalcol, evalsize)
@@ -155,7 +157,7 @@ class BadukPanWidget(Widget):
eval_info = m.evaluation_info eval_info = m.evaluation_info
if m.coords[0] is not None: if m.coords[0] is not None:
undo_coords.add(m.coords) undo_coords.add(m.coords)
evalcol = (*self._eval_spectrum(eval_info[0]), alpha) if eval_info[0] and eval_on[m.player] else None evalcol = (*self._eval_spectrum(eval_info[0]), alpha) if eval_info[0] else None
self.draw_stone(m.coords[0], m.coords[1], (*COLORS[m.player][:3], alpha), None, evalcol, self.EVAL_BOUNDS[1], scale=Config.get("ui").get("undo_scale", 0.95)) self.draw_stone(m.coords[0], m.coords[1], (*COLORS[m.player][:3], alpha), None, evalcol, self.EVAL_BOUNDS[1], scale=Config.get("ui").get("undo_scale", 0.95))
# hints # hints