diff --git a/README.md b/README.md index 05b6813..1f50bd3 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ This section describes the available AIs, with strength based on their current O * **[~4d]** **Policy** uses the top move from the policy network (it's 'shape sense' without reading). * **[~5k]** **Policy Weighted** picks a random move weighted by the policy, leading to a varied style with mostly small mistakes, and occasional blunders due to a lack of reading. * **[~8k]** **Blinded Policy** picks a number of moves at random and play the best move among them, being effectively 'blind' to part of the board each turn. + * **[3d - 12k]** **Calibrated Rank Bot** was calibrated on various bots (e.g. GnuGo and Pachi at different strength settings) to play a balanced game from the opening to the endgame without making serious (DDK) blunders. Further discussion can be found on [this](https://github.com/sanderland/katrain/issues/44) thread. * Options that are more on the 'fun and experimental' side include: * Variants of **Blinded Policy**, which use the same basic strategy, but with a twist.: * **[~5k]** **Local Style** will consider mostly moves close to the last move. diff --git a/katrain/config.json b/katrain/config.json index f0b8e33..c1a9509 100644 --- a/katrain/config.json +++ b/katrain/config.json @@ -118,6 +118,9 @@ "threshold": 3.5, "line_weight": 2, "endgame": 0.4 + }, + "ai:p:rank": { + "kyu": 4.0 } } -} \ No newline at end of file +} diff --git a/katrain/core/ai.py b/katrain/core/ai.py index f19be7e..833fced 100644 --- a/katrain/core/ai.py +++ b/katrain/core/ai.py @@ -20,6 +20,7 @@ from katrain.core.constants import ( AI_TENUKI, AI_TERRITORY, AI_PICK, + AI_RANK, ) from katrain.core.engine import EngineDiedException from katrain.core.game import Game, GameNode, Move @@ -60,10 +61,13 @@ def ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, GameNode policy_grid = var_to_grid(cn.policy, size) # type: List[List[float]] top_policy_move = policy_moves[0][1] ai_thoughts += f"Using policy based strategy, base top 5 moves are {fmt_moves(policy_moves[:5])}. " + len_legal_policy_moves = len([(pol, mv) for pol, mv in policy_moves if not mv.is_pass if pol > 0]) if ai_mode == AI_POLICY and cn.depth <= ai_settings["opening_moves"]: ai_mode = AI_WEIGHTED ai_thoughts += f"Switching to weighted strategy in the opening {int(ai_settings['opening_moves'])} moves. " ai_settings = {"pick_override": 0.9, "weaken_fac": 1, "lower_bound": 0.02} + if ai_mode == AI_RANK: + ai_settings = {"pick_override": (0.8*(1-((size[0]*size[1])-len_legal_policy_moves)/(size[0]*size[1])*.5)), "kyu": ai_settings["kyu"] } if top_5_pass: aimove = top_policy_move ai_thoughts += "Playing top one because one of them is pass." @@ -103,7 +107,8 @@ def ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, GameNode ) elif ai_mode in AI_STRATEGIES_PICK: legal_policy_moves = [(pol, mv) for pol, mv in policy_moves if not mv.is_pass if pol > 0] - n_moves = int(ai_settings["pick_frac"] * len(legal_policy_moves) + ai_settings["pick_n"]) + if ai_mode!=AI_RANK: + n_moves = int(ai_settings["pick_frac"] * len(legal_policy_moves) + ai_settings["pick_n"]) if ai_mode in [AI_INFLUENCE, AI_TERRITORY]: thr_line = ai_settings["threshold"] - 1 # zero-based @@ -164,6 +169,14 @@ def ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, GameNode for y in range(size[1]) if policy_grid[y][x] > 0 ] + elif ai_mode == AI_RANK: + n_moves = int(round((size[0]*size[1])/361*10**(-0.05737*ai_settings["kyu"] + 1.9482))) + weighted_coords = [ + (policy_grid[y][x], 1, x, y) + for x in range(size[0]) + for y in range(size[1]) + if policy_grid[y][x] > 0 + ] else: raise ValueError(f"Unknown AI mode {ai_mode}") pick_moves = weighted_selection_without_replacement(weighted_coords, n_moves) diff --git a/katrain/core/constants.py b/katrain/core/constants.py index 7081e30..c4244dd 100644 --- a/katrain/core/constants.py +++ b/katrain/core/constants.py @@ -20,11 +20,12 @@ AI_LOCAL = "ai:p:local" AI_TENUKI = "ai:p:tenuki" AI_INFLUENCE = "ai:p:influence" AI_TERRITORY = "ai:p:territory" +AI_RANK = "ai:p:rank" AI_CONFIG_DEFAULT = AI_SCORELOSS AI_STRATEGIES_ENGINE = [AI_DEFAULT, AI_SCORELOSS, AI_JIGO] -AI_STRATEGIES_PICK = [AI_PICK, AI_LOCAL, AI_TENUKI, AI_INFLUENCE, AI_TERRITORY] +AI_STRATEGIES_PICK = [AI_PICK, AI_LOCAL, AI_TENUKI, AI_INFLUENCE, AI_TERRITORY, AI_RANK] AI_STRATEGIES_POLICY = [AI_WEIGHTED, AI_POLICY] + AI_STRATEGIES_PICK AI_STRATEGIES = AI_STRATEGIES_ENGINE + AI_STRATEGIES_POLICY AI_STRATEGIES_RECOMMENDED_ORDER = [ @@ -38,6 +39,7 @@ AI_STRATEGIES_RECOMMENDED_ORDER = [ AI_TERRITORY, AI_INFLUENCE, AI_JIGO, + AI_RANK, ] @@ -52,6 +54,7 @@ AI_STRENGTH = { AI_TENUKI: "8k", AI_INFLUENCE: "8k", AI_TERRITORY: "5k", + AI_RANK: "12k - 3d", } diff --git a/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo index 11da12f..88acc05 100644 Binary files a/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo and b/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo differ diff --git a/katrain/i18n/locales/en/LC_MESSAGES/katrain.po b/katrain/i18n/locales/en/LC_MESSAGES/katrain.po index e8c848c..7e43428 100644 --- a/katrain/i18n/locales/en/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/en/LC_MESSAGES/katrain.po @@ -556,3 +556,12 @@ msgstr "" "Picks moves biased below the `threshold` line and plays the best one. " "Increase `line_weight` to penalize moves near the center more. Stops " "strategy after the 'endgame' fraction of the board is filled." + +msgid "ai:p:rank" +msgstr "Calibrated Rank" + +msgid "aihelp:p:rank" +msgstr "" +"Picks moves at random from a limited selection of moves and plays the best " +"one. Stronger settings select the best move from a larger selection. Since " +"there is no 0 kyu/dan, 3 dan = -2 kyu." diff --git a/katrain/i18n/locales/fr/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/fr/LC_MESSAGES/katrain.mo index 1a8a054..8df582d 100644 Binary files a/katrain/i18n/locales/fr/LC_MESSAGES/katrain.mo and b/katrain/i18n/locales/fr/LC_MESSAGES/katrain.mo differ diff --git a/katrain/i18n/locales/fr/LC_MESSAGES/katrain.po b/katrain/i18n/locales/fr/LC_MESSAGES/katrain.po index 61066cb..06f18df 100644 --- a/katrain/i18n/locales/fr/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/fr/LC_MESSAGES/katrain.po @@ -597,3 +597,14 @@ msgstr "" "Le coup {move} a été annulé car il perdait {points_lost:.1f} points. Vous " "pouvez survoler le coup pour voir la réfutation. Veuillez jouer un nouveau " "coup." + +#. TODO +msgid "aihelp:p:rank" +msgstr "" +"Picks moves at random from a limited selection of moves and plays the best " +"one. Stronger settings select the best move from a larger selection. Since " +"there is no 0 kyu/dan, 3 dan = -2 kyu." + +#. TODO +msgid "ai:p:rank" +msgstr "Calibrated Rank Bot" diff --git a/katrain/i18n/locales/haha/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/haha/LC_MESSAGES/katrain.mo index f14021b..801b4f4 100644 Binary files a/katrain/i18n/locales/haha/LC_MESSAGES/katrain.mo and b/katrain/i18n/locales/haha/LC_MESSAGES/katrain.mo differ diff --git a/katrain/i18n/locales/haha/LC_MESSAGES/katrain.po b/katrain/i18n/locales/haha/LC_MESSAGES/katrain.po index fa0918c..41118a5 100644 --- a/katrain/i18n/locales/haha/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/haha/LC_MESSAGES/katrain.po @@ -529,3 +529,12 @@ msgid "analysis:nextmoves" msgstr "" "ㅋㅋNext\n" "Moves" + +msgid "aihelp:p:rank" +msgstr "" +"ㅋㅋPicks moves at random from a limited selection of moves and plays the best" +" one. Stronger settings select the best move from a larger selection. Since " +"there is no 0 kyu/dan, 3 dan = -2 kyu." + +msgid "ai:p:rank" +msgstr "ㅋㅋCalibrated Rank Bot" diff --git a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.mo index fa5e2fd..ecd9e06 100644 Binary files a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.mo and b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.mo differ diff --git a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po index f646ae4..8eb7175 100644 --- a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po @@ -538,3 +538,14 @@ msgstr "" msgid "teaching undo message" msgstr "" "{points_lost:.1f}집 손해이므로 {move}을/를 물렀습니다. 커서를 올려 상대의 대응책을 보십시오. 다시 두어 주세요." + +#. TODO +msgid "aihelp:p:rank" +msgstr "" +"Picks moves at random from a limited selection of moves and plays the best " +"one. Stronger settings select the best move from a larger selection. Since " +"there is no 0 kyu/dan, 3 dan = -2 kyu." + +#. TODO +msgid "ai:p:rank" +msgstr "Calibrated Rank Bot"