fewer dots by default (default off with 3 dots)
This commit is contained in:
1 parent
7ab37694d9
commit
2cce7ed4af
6 files changed
+47
-39
No files matched your search
@@ -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.
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
|
||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in new issue
Block a user