From 20809d7c4d6fdab14d1922c58ab8ccb9bd36e362 Mon Sep 17 00:00:00 2001 From: Sander Land Date: Fri, 26 Jun 2020 21:57:09 +0200 Subject: [PATCH 1/2] Implements PDA strategy / issue #102 --- katrain/__main__.py | 11 +++- katrain/config.json | 4 ++ katrain/core/ai.py | 54 +++++++++++++++++- katrain/core/constants.py | 22 ++----- katrain/core/engine.py | 15 +++-- katrain/gui/popups.py | 16 ++++-- .../i18n/locales/cn/LC_MESSAGES/katrain.mo | Bin 10707 -> 11005 bytes .../i18n/locales/cn/LC_MESSAGES/katrain.po | 12 ++++ .../i18n/locales/de/LC_MESSAGES/katrain.mo | Bin 12531 -> 12829 bytes .../i18n/locales/de/LC_MESSAGES/katrain.po | 12 ++++ .../i18n/locales/en/LC_MESSAGES/katrain.mo | Bin 11681 -> 11980 bytes .../i18n/locales/en/LC_MESSAGES/katrain.po | 10 ++++ .../i18n/locales/es/LC_MESSAGES/katrain.mo | Bin 12429 -> 12727 bytes .../i18n/locales/es/LC_MESSAGES/katrain.po | 12 ++++ .../i18n/locales/fr/LC_MESSAGES/katrain.mo | Bin 13142 -> 13440 bytes .../i18n/locales/fr/LC_MESSAGES/katrain.po | 12 ++++ .../i18n/locales/ko/LC_MESSAGES/katrain.mo | Bin 13373 -> 13671 bytes .../i18n/locales/ko/LC_MESSAGES/katrain.po | 12 ++++ .../i18n/locales/ru/LC_MESSAGES/katrain.mo | Bin 16738 -> 17036 bytes .../i18n/locales/ru/LC_MESSAGES/katrain.po | 12 ++++ setup.py | 3 +- 21 files changed, 172 insertions(+), 35 deletions(-) diff --git a/katrain/__main__.py b/katrain/__main__.py index f833d5a..76961c8 100644 --- a/katrain/__main__.py +++ b/katrain/__main__.py @@ -3,7 +3,8 @@ import os os.environ["KCFG_KIVY_LOG_LEVEL"] = os.environ.get("KCFG_KIVY_LOG_LEVEL", "warning") -os.environ["KIVY_AUDIO"] = "ffpyplayer" # force working audio +if "KIVY_AUDIO" not in os.environ: + os.environ["KIVY_AUDIO"] = "sdl2" # seems to be most stable / some players hard crash # next, icon from katrain.core.utils import find_package_resource, PATHS @@ -161,7 +162,10 @@ class KaTrainGui(Screen, KaTrainBase): # update move tree self.controls.move_tree.current_node = self.game.current_node - def update_state( + def update_state(self, redraw_board=False): # redirect to message queue thread + self("update_state", redraw_board=redraw_board) + + def _do_update_state( self, redraw_board=False ): # is called after every message and on receiving analyses and config changes # AI and Trainer/auto-undo handlers @@ -214,7 +218,8 @@ class KaTrainGui(Screen, KaTrainBase): continue fn = getattr(self, f"_do_{msg.replace('-','_')}") fn(*args, **kwargs) - self.update_state() + if msg != "update_state": + self._do_update_state() except Exception as exc: self.log(f"Exception in processing message {msg} {args}: {exc}", OUTPUT_ERROR) traceback.print_exc() diff --git a/katrain/config.json b/katrain/config.json index 8b111d4..7b18d4f 100644 --- a/katrain/config.json +++ b/katrain/config.json @@ -69,6 +69,10 @@ }, "ai": { "ai:default": {}, + "ai:handicap": { + "automatic": true, + "pda": 0 + }, "ai:jigo": { "target_score": 0.5 }, diff --git a/katrain/core/ai.py b/katrain/core/ai.py index ffcbb59..6918295 100644 --- a/katrain/core/ai.py +++ b/katrain/core/ai.py @@ -21,6 +21,8 @@ from katrain.core.constants import ( AI_TERRITORY, AI_PICK, AI_RANK, + AI_HANDICAP, + OUTPUT_ERROR, ) from katrain.core.game import Game, GameNode, Move @@ -93,8 +95,51 @@ def generate_local_tenuki_weights(ai_mode, ai_settings, policy_grid, cn, size): return weighted_coords, ai_thoughts +def request_ai_analysis(game: Game, cn: GameNode, extra_settings: Dict) -> Dict: + error = False + analysis = None + + def set_analysis(a): + nonlocal analysis + analysis = a["moveInfos"] + + def set_error(a): + nonlocal error + game.katrain.log("Error in PDA-based analysis", a) + error = True + + engine = game.engines[cn.player] + engine.request_analysis( + cn, + callback=set_analysis, + error_callback=set_error, + priority=1_000, + ownership=False, + extra_settings=extra_settings, + ) + while not (error or analysis): + time.sleep(0.01) + engine.check_alive(exception_if_dead=True) + return analysis + + def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, GameNode]: cn = game.current_node + + if ai_mode == AI_HANDICAP: + pda = ai_settings["pda"] + if ai_settings["automatic"]: + n_handicaps = len(game.root.get_list_property("AB")) + MOVE_VALUE = 14 # could be rules dependent + b_stones_advantage = max(n_handicaps - 1, 0) - (cn.komi - MOVE_VALUE/2) / MOVE_VALUE + pda = min(3, max(-3, b_stones_advantage * (3/8) )) # max PDA at 8 stone adv, normal 9 stone game is 8.46 + handicap_analysis = request_ai_analysis( + game, cn, {"playoutDoublingAdvantage": pda, "playoutDoublingAdvantagePla": "BLACK"} + ) + if not handicap_analysis: + game.katrain.log(f"Error getting handicap-based move", OUTPUT_ERROR) + ai_mode = AI_DEFAULT + while not cn.analysis_ready: time.sleep(0.01) game.engines[cn.next_player].check_alive(exception_if_dead=True) @@ -187,7 +232,12 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, else: raise ValueError(f"Unknown Policy-based AI mode {ai_mode}") else: # Engine based move + handicap_or_default = "Default" candidate_ai_moves = cn.candidate_moves + if ai_mode == AI_HANDICAP: + candidate_ai_moves = handicap_analysis + handicap_or_default = "Handicap" + top_cand = Move.from_gtp(candidate_ai_moves[0]["move"], player=cn.next_player) if top_cand.is_pass: # don't play suicidal to balance score - pass when it's best aimove = top_cand @@ -214,11 +264,11 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, aimove = topmove[2] ai_thoughts += f"ScoreLoss strategy found {len(candidate_ai_moves)} candidate moves (best {top_cand.gtp()}) and chose {aimove.gtp()} (weight {topmove[1]:.3f}, point loss {topmove[0]:.1f}) based on score weights." else: - if ai_mode != AI_DEFAULT: + if ai_mode not in [AI_DEFAULT, AI_HANDICAP]: game.katrain.log(f"Unknown AI mode {ai_mode} or policy missing, using default.", OUTPUT_INFO) ai_thoughts += f"Strategy {ai_mode} not found or unexpected fallback." aimove = top_cand - ai_thoughts += f"Default strategy found {len(candidate_ai_moves)} moves returned from the engine and chose {aimove.gtp()} as top move" + ai_thoughts += f"{handicap_or_default} strategy found {len(candidate_ai_moves)} moves returned from the engine and chose {aimove.gtp()} as top move" game.katrain.log(f"AI thoughts: {ai_thoughts}", OUTPUT_DEBUG) played_node = game.play(aimove) played_node.ai_thoughts = ai_thoughts diff --git a/katrain/core/constants.py b/katrain/core/constants.py index 1e5c0fe..f90a925 100644 --- a/katrain/core/constants.py +++ b/katrain/core/constants.py @@ -1,6 +1,6 @@ VERSION = "1.3.0" HOMEPAGE = "https://github.com/sanderland/katrain" -CONFIG_MIN_VERSION = "1.2.0" # keep config files from this version +CONFIG_MIN_VERSION = "1.3.0" # keep config files from this version OUTPUT_ERROR = -1 OUTPUT_KATAGO_STDERR = -0.5 @@ -17,6 +17,7 @@ GAME_TYPES = [PLAYING_NORMAL, PLAYING_TEACHING] MODE_PLAY, MODE_ANALYZE = "play", "analyze" AI_DEFAULT = "ai:default" +AI_HANDICAP = "ai:handicap" AI_SCORELOSS = "ai:scoreloss" AI_WEIGHTED = "ai:p:weighted" AI_JIGO = "ai:jigo" @@ -30,13 +31,14 @@ AI_RANK = "ai:p:rank" AI_CONFIG_DEFAULT = AI_SCORELOSS -AI_STRATEGIES_ENGINE = [AI_DEFAULT, AI_SCORELOSS, AI_JIGO] +AI_STRATEGIES_ENGINE = [AI_DEFAULT, AI_HANDICAP, AI_SCORELOSS, AI_JIGO] 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 = [ AI_DEFAULT, AI_RANK, + AI_HANDICAP, AI_SCORELOSS, AI_POLICY, AI_WEIGHTED, @@ -49,20 +51,6 @@ AI_STRATEGIES_RECOMMENDED_ORDER = [ ] -AI_STRENGTH = { # not used - AI_DEFAULT: "9d", - AI_POLICY: "4d", - AI_JIGO: "?d", - AI_SCORELOSS: "5k", - AI_WEIGHTED: "5k", - AI_PICK: "8k", - AI_LOCAL: "5k", - AI_TENUKI: "8k", - AI_INFLUENCE: "8k", - AI_TERRITORY: "5k", - AI_RANK: "15k - 3d", -} - AI_OPTION_VALUES = { "kyu_rank": [(k, f"{k}[strength:kyu]") for k in range(15, 0, -1)] + [(k, f"{1-k}[strength:dan]") for k in range(0, -3, -1)], @@ -77,4 +65,6 @@ AI_OPTION_VALUES = { "stddev": [x / 2 for x in range(21)], "line_weight": range(0, 11), "threshold": [2, 2.5, 3, 3.5, 4, 4.5], + "automatic": "bool", + "pda": [(x / 10, f"{'W' if x<0 else 'B'}+{abs(x/10):.1f}") for x in range(-30, 31)], } diff --git a/katrain/core/engine.py b/katrain/core/engine.py index b0c81fc..69065be 100644 --- a/katrain/core/engine.py +++ b/katrain/core/engine.py @@ -5,7 +5,7 @@ import subprocess import threading import time import traceback -from typing import Callable, Optional +from typing import Callable, Optional, Dict from katrain.core.constants import OUTPUT_DEBUG, OUTPUT_ERROR, OUTPUT_EXTRA_DEBUG, OUTPUT_KATAGO_STDERR from katrain.core.game_node import GameNode @@ -206,9 +206,11 @@ class KataGoEngine: time_limit=True, priority: int = 0, ownership: Optional[bool] = None, - next_move=None, + next_move: Optional[GameNode] = None, + extra_settings: Optional[Dict] = None, ): - moves = [m for node in analysis_node.nodes_from_root for m in node.move_with_placements] + moves = [m for node in analysis_node.nodes_from_root for m in node.moves] + initial_stones = analysis_node.root.placements if next_move: moves.append(next_move) if ownership is None: @@ -233,10 +235,11 @@ class KataGoEngine: "komi": analysis_node.komi, "boardXSize": size_x, "boardYSize": size_y, - "includeOwnership": ownership, + "includeOwnership": ownership and not next_move, "includePolicy": not next_move, + "initialStones": [[m.player, m.gtp()] for m in initial_stones], "moves": [[m.player, m.gtp()] for m in moves], - "overrideSettings": settings, + "overrideSettings": {**settings, **(extra_settings or {})}, } self.send_query(query, callback, error_callback, next_move) - analysis_node.analysis_visits_requested = max(analysis_node.analysis_visits_requested,visits) \ No newline at end of file + analysis_node.analysis_visits_requested = max(analysis_node.analysis_visits_requested, visits) diff --git a/katrain/gui/popups.py b/katrain/gui/popups.py index 23d3ee0..5a7b618 100644 --- a/katrain/gui/popups.py +++ b/katrain/gui/popups.py @@ -322,12 +322,16 @@ class ConfigAIPopup(QuickConfigGui): self.options_grid.add_widget(DescriptionLabel(text=k, size_hint_x=0.25)) if k in AI_OPTION_VALUES: values = AI_OPTION_VALUES[k] - if isinstance(values[0], Tuple): # with descriptions, possibly language-specific - fixed_values = [(v, re.sub(r"\[(.*?)\]", lambda m: i18n._(m[1]), l)) for v, l in values] - else: # just numbers - fixed_values = [(v, str(v)) for v in values] - widget = LabelledSelectionSlider(values=fixed_values, input_property=f"ai/{strategy}/{k}") - widget.set_value(v) + if values == "bool": + widget = LabelledCheckBox(input_property=f"ai/{strategy}/{k}") + widget.active = v + else: + if isinstance(values[0], Tuple): # with descriptions, possibly language-specific + fixed_values = [(v, re.sub(r"\[(.*?)\]", lambda m: i18n._(m[1]), l)) for v, l in values] + else: # just numbers + fixed_values = [(v, str(v)) for v in values] + widget = LabelledSelectionSlider(values=fixed_values, input_property=f"ai/{strategy}/{k}") + widget.set_value(v) self.options_grid.add_widget(wrap_anchor(widget)) else: self.options_grid.add_widget( diff --git a/katrain/i18n/locales/cn/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/cn/LC_MESSAGES/katrain.mo index 837684882b0747d11e89cd065cf7682638d33f44..78189a9d0dec28c099c648fc0279353f8070faca 100644 GIT binary patch delta 3064 zcmYM#3v3is6vpuj6f6ZwLBvwfjy%e{P!d#>LNEkGqai#b5)GYpx7`if?y|cDT7?a$ z2tg>KMKmNt8c@JQ(h?1lY6L_JLR1pU+b1GXRE&t!p#DGhh-5my`@ZL%nOTm_ygoa1 zu4hKQT8MVYj2btkJNc*VW^+?&gQ$U(sApe;dWP$)z74fuvw0Mi(l4$5B68grq!Z>aSO>Wi zRWGvoMAWz$Ipkj_DWyS?CXvf6gcb<%uP z{}9xA<4`Z@bkur5W$iPFzOi=p(c*E_GzevXQIZ>L!C5+T5yH6*W-%&ux*u|27JPG0til@EU62H@J<*W}Jd;Sb&pw;Cd-TsFXj88ovhfu>p&4 zKi-R1P=OTQp5A8y4xwI-DNU@Spww?gy;Sew1biPS;&t4F#k{Ha;3?FCJ^Q3j+8>p< zu{a$kqB61$pT^DB-;dvEwHIJDj?E+g+HfZgTCfq7`hBQO95GLs7tG(ycBDb$vdzAz z^@dn|6t1N{9?#-o)Pc71KixXK*pK}0qELGWojCkX=T_rYJb}-UPYry+;|0S@_#(c1 z7rz-;&_8{mRj5a?5%p|eN43jx_H_^-n`B zRA%ilRLYm4PQ23k>#V-X>J8>Dv)Md^di1GQYq*43uniSq#=vwyeUYrWLewLA$lB*3 zuYs#XF1Nz!JCWqL1E{aydnB3en)T-nO1Br`Xnp^aDU4u1H4euuNK)KU)P|R_5Ze`` zGcXzzXtC9&nzK+R@=+TuLIu77bFk6+_nRlNlfM67C@8gmpiU$*nyMq)I`7zYQi>Qr$MV&++tLpjYC?uP1 zB5K0`YT*Ug9-l(3v($VJ^(bCIJ(|s^c^_g*g`*UP;c4W{aGi#x2Mj=(+-R#mZkD4q zNSL+eGIJ&BQPx>~uer}`LGAn5P&e;J%FkNIkLGWv6JNu{*qP`wVL58!I@Axz25aAn z%3vevq@SQpdU{yXj;ulLGedq=AYA6hUOL=$&CN>F^lrntb(tFV9<<)3>b$IWsfYcf zPh&Ke3|EG0g8{ER8uwxmzb0H&;f2B#piIeebcK|b}$Br>e#@U#Ji!l~gVj>pcSX}SV zw}cJs84Ao{`%x1#U;-Y;iTEML<9Uq6OQ?W;LG}L^Q!$xNDR>=f!R4ra`CczYZD1RY z#wtv)z-%vtC>jnSbJ-E^@D3`l4%AM%P!pf?_I}hv1MXj_@sUKYeu=1!q;XTfIY<|~ z2}c6NF|2R-6tt5E{lVkNWr16bN?jeQ-x1VK+Wh%hRLU=+0{#Ql|8E?RajZts(oy4b zQ2{LDrZsF81x>sbHE=U>*;C$LjT+d9TIe`xp-$woFTDOOYKK3gGBJdsFoH=bS{!Qr zDcqFN?6Kru9p}-YvtEiivqGZMF! zRn3=;`g)e4`mGMUP>PzM!mUI_ybJZ#*J218P!l)#^AAt~oi3z~dr=ErLM=Rq z3UnBWF|cIvqL*PNYJyx;#|5Z?%f0RBOLQLJgRK+Ub1Mgm-&;5sn0eIno;`RL(Q_#d4xh=s;T!C$vi7_0wUdmk54(>$t&&Lcb#d-KVF2Z+Ff&7VDC~^|# zjX9`s1xV`c5e)QFZKtpdpT=9T1M4w@S9KvCKuy?#+Ubv|3|+xIjG7Y8NFhE+{bAJe z@4fw3+^YVl^&aEzwKBdfmHaD3l{Cm2x6VE6o^VgP-KdHByxxyB)Gwnp5Rk5yupQsR zJpQwt#)vet7w`;Tz@l{WuZ}m8$0qE=JyZ~8SHk|s+sIx3by=*U{0WS}Ox*&nPxrLYjS(_(*K;`J?Ff5Lsv-RCx< z&br0xov8WFq5|wi1r!WY(90D)BYeiwP!HxJ$7{FYOkC&nN@NpOi|Y42ren81AMo~A z2F;~C6?1VV&cO;~Njr$VQ-OU#;d&a*qcRYh6^?W~s-EWNpmwwnwcsjL;F~ZBtNi(E z?whF0eTa2n*e{sH0eqI-0Ghaj&=s zF^BpwEW7pdxLJ|=uEy_d-JdW$q4iX1 MOhjw*)WXF70Q`RgNdN!< diff --git a/katrain/i18n/locales/cn/LC_MESSAGES/katrain.po b/katrain/i18n/locales/cn/LC_MESSAGES/katrain.po index eaa954a..fc88241 100644 --- a/katrain/i18n/locales/cn/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/cn/LC_MESSAGES/katrain.po @@ -584,3 +584,15 @@ msgstr "Re-analyze entire game" #. TODO msgid "analysis:continuous" msgstr "Continuously analyze" + +#. TODO +msgid "ai:handicap" +msgstr "KataGo Handicap" + +#. TODO +msgid "aihelp:handicap" +msgstr "" +"KataGo optimized for playing higher handicap games.The `pda` setting " +"corresponds to `playoutDoublingAdvantage` in KataGo, from black's " +"perspective.When `automatic` is set, KaTrain will find a suitable value " +"automatically." diff --git a/katrain/i18n/locales/de/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/de/LC_MESSAGES/katrain.mo index bcfc2c69e0debdfd40d42c42b1066839115b42ce..cc9fac0a0b1e73c94fd5788b929d8bb630464447 100644 GIT binary patch delta 3064 zcmYM$4NO&K9LMoT(RdLAl}JJ5q!_4(QmNDBOqQBD)A^Dc&dGs$;9kAld%O37p|jh| zrc7N|A9L|h%*MH>1uIegp0oA! zr~qEWRNRBvCSlC`6q0yw99hG(+YV<@8~ffqzk!PAHfjOwQtg?j33IIlsCi0I{U#%q znZ-^0mLO9Y7yGil2~kjL)}jV(Mn$$m9dI9VnUAb(sQzbB{jQ-R>$2_X4AK$gqBb}h z)qesGz!^waQ;rD@^i$w6t8K#u)Wol&2JS^J^Pzp-h8lMswb0L~h5kV8hr)(B;Q))d_$6D0cH=xdNtF1Sq7CdPE0+rH>w*5!sy4Oh&X3<%J z3`NyTZG9@L--0aiuShC+pq<8%%e=%*8)(Eld>fUzqo|#qvtCCobBmicp2B2`JR22h zKB~P4HQyxEOFADlpQrrmb80|!Y_#q|P0(sRh}!Wn)K_o@AHZ)>6JNINcTgKlC2TD; z5H)TLDic$ zy9_m>a1@r|My$n=cpE>#VSGaR4SNOkHC^Mj8IuN+f4#-8@|Q=cYC=V{2bHS#tRJJ! zvK_9DaJx3BRUzfqZ6D zZyjb#8}+u~90B!h1;+eD{mKYqHsQ%fx))l;`Dp_yP-nXa^$u;tBHW1z@CYh%r%~@r zXM%!u+JyvRlIg7o3s4bGK$=V$s^1Fxd=)CvS1=hjq84bh^|w&($X@&W2x>#8QS)3x zZ6tAnf>N8rfvKS%60{kLDL4(ak=dvPo<&7ijoR=U9E(k;cjyF?EOP;QT})4243cH? zP-j04m8oSoQ{R7xg5K8s_#|G(i8yj}_d+g~P_IX&Y&UAdt(c03Q44jT7QTw(Ftxb* z{{@p#^~I3#Je@FRB@iny3sl@jO(9s!$8> zM7<09uqU?I`hL{AaS-(`9L2}+qHWLS+!C4~j{<9&VkAgYj@s#Zq_5eAnRwWG3Kh|1 zRK%Ug$6@}o-bNj17b=s*vk)YcU2-P_LK#kvvI{(e*)VQ@?tYnejb1EV} zx59~e@woa`g`-g~772%ZF()3Tk@4ZW_*3D!${_92eD!W9?$&q}P9WrTuUPCy_ delta 2780 zcmYM#e@vBC9LMo5X#BW<5F%h8Vv2%X69!^6O>(&mVh&9<7H-)ng_Z?dWo!1N{u5Vd zO=U62a5@tN|M5!HECOw%MT*VRoYI!8pG2c%OPizjhkLf%!}B`lJm>kI@A>gu4^;oX z*&9xr-faBqbq1k>-PQcEQ-ge-;HN56~A?k;auvGF=mOl2ovx@jKor$fg3O$ zpLWmdLwdHG0x@hqDnL8N;R#H}evHM-I2}h&3H^%dKZ*BXBAt?O32MOAsD90--pDnX24d@HA*nQU?oUPLbQoK2{uYeV(xLd~SlJs(0X`7kQsKT-W}<4p818b!-M zz2`?I@DMkRVPzB)_({}@+mOp%ckNB67Z0KaI)NJK4073dSHF&$;V-C_n7}9uBPd1l zq2kZxrWMVJXZ_VNp9byqO4Ob`;p(-h0e3q0qL%Wodwv|b>@#kf$R*T7esuK-SD!`@ zik6I;$U;=2_b0Ia8ek1KB~XEB_&jRq8c>-ZaCRe?o#Lj%2T?0=1vS$f$YrD46z>k| zP$n^|;^m;eo|UM66`m_>K?T_E+=0*FKI~i7;+j zu_R{(D)DU83V4MSl*z-c!+O+GR=Ezf$Yrl^Q@;Qzp*B>)2T@zri5lorRKIhseib#) z2x{PQRHAo~96d{9U33^0paS?&9g9#eu6FI~P=PCvcdgddccA*eg-W~?^n`u=~Xpgo*Gy{Pn*NE|9~3hIUVsF@a`0+zV;N}NgvwPicp^Cnchcah6F zxjlz{xCj>$ELq?GdJ40#2DjpFT!*8$3|Fw>dR~v3K_kw?X7pn(=Hmz!U~)?6l$W6D zRk#%2#yQxJgtlSyw3jz2Y`|Msf@K`hzpw>MaSx*t+b$zrYz!A;1i!lh%*P!382j-j zoccxOQ_|Pe#jOdyKpo`U)IVCltnp}8 zXn=x+p@EB0ds&V;GtXi+)}i*k6}3{wP-kQSmEaJPn_Wju>^5p*u^uNuhar`lIu@fI zlwkx`VkAC=8eprdZ%3VpH(YxwDxqVjI6bIDPNP=zd)NLmGFQ8a+5#_y^fh26Y5+fK zhAU7Rm!l5PHq@bc4_PETiTWkGf-I7aqxL$5gP<)cz(?^B)ZuKzV(i1^IEjqo*>X6k;)TNhoj@YKa~|1*k)vg~YV3L%lzaTo%qU zGnD0_65WIze^$dyd*9;hK+Whw)Qks^kHZF?=TUn)gj&jQ4u}$oLcQTFZiV|D}3L-u?@lf SaZ&NX?)0@`!EZ83XZ{DXt_;rr diff --git a/katrain/i18n/locales/de/LC_MESSAGES/katrain.po b/katrain/i18n/locales/de/LC_MESSAGES/katrain.po index cbab7b4..c7548c4 100644 --- a/katrain/i18n/locales/de/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/de/LC_MESSAGES/katrain.po @@ -627,3 +627,15 @@ msgstr "Re-analyze entire game" #. TODO msgid "analysis:continuous" msgstr "Continuously analyze" + +#. TODO +msgid "ai:handicap" +msgstr "KataGo Handicap" + +#. TODO +msgid "aihelp:handicap" +msgstr "" +"KataGo optimized for playing higher handicap games.The `pda` setting " +"corresponds to `playoutDoublingAdvantage` in KataGo, from black's " +"perspective.When `automatic` is set, KaTrain will find a suitable value " +"automatically." diff --git a/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo index c6ca5caed7b04233d17b29435605f641c0701937..8090a202c6169f4d837854abfb3e01e104d627b3 100644 GIT binary patch delta 3097 zcmYM#e@sy2bH2eV~9F0&3bf(ThWaY?;;j15f4-=k@$L&+~o0&pFrq zOV2J(Tp5_W%kb|l{tEbeK1DTSE~o$RAc|j8AArB&P)y0_wGfM_PsV|`7;|tnrs8v$ zjZN4eci8?ndQF%%3R>$E)C6B*7Ji3=@n_7$RBp+biwYEj?#!u3*?~si%=7mS|_6BnTZ;= z0J+T5+%&ERnaZriY}Pj$C@3{sQ4hADc6LYuupPO~=hiON_-@p=+o+wTGnk?&KpjCT zD!}Qe@$>LLT!b388WVbOJq0ea#df@cn)o2nYR(Us*4s0=|y=8g5}f{1Y{C65CY& zP*i}UQ43AB?F*61EaRq(CBnAQh>E-km4R)jK=#`Hw^6Bl-}ZMPmpR8xywam5@r?!ExZsF=@Mi!rVjNkBv2E)h#I#Y6<~{PKa86A7_z46 zu=R_m@!z8YzlD0PFN??=%+~imoPr`QLrpXZwctF|8CIYkSZdpAQ4>c|<2Rsox($`` zH*Nbd>VxQJjnG zct{g|fW&4xu>`-x^_a@5$9oYd}KY~49g>COZPR(?pGIbSu zzOGvol-j$t!^fMWiHD)uOOWF<51|%Xh&qC&P&@Hk7)4# zpk9phC(Pp%G*LB9#u##$BiyFqc^r?~%&M33VH}H$3q89iN$*wtz3ivlv zz{za85Be|#Gf@iBv}wFgmWw+j_{yKO&>3g9Mc{9V+-zVhCk z<{=-68EGv>9bpM7uqBv^%gf2XBJ*g_PS;=-HlW&@QAe@`^#ijL^}}+=)<^OpXu>I| zuVe-)kP6h1RADAI;-k13&Fo;%sSEqPV9fD{+d9(+^+~IBL;gUu8`*g&bL+iITUC}X zJ7a#>dCc~<`G-wQN<87lT^hrYc%Uxutmk)Dg`-X+=r#sIHBN1yrq+u(|IO#rxOHA^ zY-O$IR7L!5l@s&gagD1EN26XW5)S!ePCQH}&xh;dkA&-22I-&eZ*W6#x5le-0wJe& z#WH7AG+gJbSQ&Jy*Nloe5ic5xc-8ShgE!V$TG-gE9ft+2K)=@T4+E3 delta 2796 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 WxT&Kl=~Qw@P5MJo9d8FSQvU;HcnOaH diff --git a/katrain/i18n/locales/es/LC_MESSAGES/katrain.po b/katrain/i18n/locales/es/LC_MESSAGES/katrain.po index 0ee6641..50d8e35 100644 --- a/katrain/i18n/locales/es/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/es/LC_MESSAGES/katrain.po @@ -622,3 +622,15 @@ msgstr "Re-analyze entire game" #. TODO msgid "analysis:continuous" msgstr "Continuously analyze" + +#. TODO +msgid "ai:handicap" +msgstr "KataGo Handicap" + +#. TODO +msgid "aihelp:handicap" +msgstr "" +"KataGo optimized for playing higher handicap games.The `pda` setting " +"corresponds to `playoutDoublingAdvantage` in KataGo, from black's " +"perspective.When `automatic` is set, KaTrain will find a suitable value " +"automatically." diff --git a/katrain/i18n/locales/fr/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/fr/LC_MESSAGES/katrain.mo index 145fba755fd584670ccc431b151308c39515b35e..6a4ecda50a7b46c0e16abcd715b69e8843de9a40 100644 GIT binary patch delta 3063 zcmYM#eQXp(7{~G9z4Yx0(h8N*RSN}aiv>a`7T+Me1YfFv5E4SS?Y4K}dUxJk(SmS* z0b>ZHsa8deK`@{dHKF_g8mxaPq#~k}w7wu!v7!V`h++|=`2F<;CENYX%+5SB^UUti zRl6~eI6HE1i{am!{Eg)=K14NRK1u!GY>FqSkHB*{8ZTQj(~QZdUWg-cK4#$x9EPhg z6JzMZ&Gvb7(uCPVL315M1!%_%JcT*0&rg z$YmCCQ@>?M2;*WV^P3O_rDi>9;C9r`cB%vJM=tZ8wFA|^8`bYTYG+sN^K=I32y#&i zoQ&!}18=~2NLRB06B_8Jz-89j2T!8{KaU#Nid^Ph+ung1cLp`luc(QxA(u&Ikm_Sl zJ1szMtQ1plHmct|ANi+jmU2^SJygef)Y&(p&albW_o5~|V*M1A(jNQ#XXNVdq#b6_ zSsNLLs+ZdOU8sH!XOVyHq>2WuG>%+m6E`iO8E?WjP^tR}wel~mKOvXtiI-eyfV~FT7in^DgXMM8c`jat$R=b4qA_(R(uro6?EZH{2CSbd;9!P)B=aI zZA~;9HLe(yiP_wgu?lNq1qH3V29<#bY9Z@whaITYy4yHJT5;72VmiW<1Vwr@iPZb9ZSdu{zN zs{hBRg?FLG{b0R>%FsWUqVGS0*%c@UHDMv@3`m+9rUTHpUw3WZopG!|uc-~`-_RoH>mSj0ik#3sB|?KlR1vGrj$ zl2+=Iu?+9S3fziXNH;FV^H_v;@Zu%(oA0N<9A*pZEMLO)xC_HLj#=gmU}4xm{S?2q z3b=qzLqEOCaR$b4Gq$2KQcUpOSdRLI?Llqu9B#tCvE*NGabsRG;6~I-)P#BmcB1}2 zdeyoQbu@3G#vMW(Njs|lan$%u)Y+fGJ$M1X!5!m_sl#ACnPNky^U41h3YQ&LkG@-s zS%goL-$FcDU`!tNjb}p4=A2S->_lT$V&SCZnQpnw7_w@bQD@tV+G#s7m+3^k6Tcy+ zWrj{pW+*Q~L8&Z4vS!LrXSy6UAc`fp1yk`LYG>`J44gpi{51A|ezv_Ab)*+j3mM3P z_kVtuR0u!da+12R1kITva7h|qyIRF3v delta 2779 zcmYM#e@sCRKsDyq)jUUHZ7-Ucg7osLCM2#zQ z{R-3qc40j3#gKVs`)R~+p$&;;?QXzlsKmZPt)v$f_@cXh0~P4D^Dor%v1G4t$*6^d zIcZ!DGQ=Lli3Bl$`K^eCRO@U+8aeD6*T05Z;jgGljNsiE zLr|LLL&Z5(yslNs;=7RRR0JUc&u3w3ou-dsFRmxU(|2T5k*POJFi>QV4yZ(sl z#}S04O-C&x6P0Lwfck5Kr#LBrb$BnngeqMPD)WQR4&<;NPD;ENRf)@}mEJ%OyTwWI z#!xS1h*=dc8};=RpvJB9T%!UN;B{v;D&tzzTi=9tVGAnoQFs3fRDu^!6J2%Jhf$S? z;iQU%oT;e9=c6j%Eu*1K9(MzZQKfv|4X8v8dySLE)uIw=MkRb0wPg|1L|>xDopt>y zsEKZ(CLTs5I)>!vS&+KuWtfKwkc%3ahkCHkU0;I=T#7tvm9Aff8ov*fcoXWmkDT48 z3Y|hF{2eOJ6^z&SKS)D+ID&dm=_!#URNxt?2hve1U4{y{%3UwTiG)yFR^{&3q2hgj z92ViU6;EImE+E)cegDNYGO-*tVjXV6AH0pW4}&hY#T% z+>WZqFn)-dMZc)6NKvf~tFZ_55*LJ{Tk&L=`fKl3b3uQ1o^zI=wqyh9fo-U*cm*}y zL+$0es6BrlTk#N9U|}kiVFAZ51<$APEDp@!4-%H%#}?p`bm||babX@4;a~<6*KZ?KD49Jj-X4TW;p~QH!DKLtKy`Eb)XNsQSncr z;+~nf&i?n(Nan&NR4IQ!-VYna#TdRndVLM5gqu)-wxafMCnn)L=*N20yV8oPL=P(Q zGnj~dsQCslmHBOyh61EK5S=IsRiZ~xFWVN>gjJ}OyzTn$IS-&FIEeG{Q&ghYkT2N= zFcbep)?^v1il1I9K~F0!r=gP6pgzNW&IZ(kO~}V!N1Sb#M?Zpk?q}4v0oNZwB|L&! z*gvSaz9rGE4Pb!&tR?oC9ioxL1(oC+D)XOQ|GIO?IgWZal9%!$f-{$Po%3bH*8iPY T)76kP(>VtUm!8Zn zE7T=PWpmbYveGUq{D;i7Y3j^!<{wzgGHLW;LlQ6cB6FDiw!vXkV8`tHGpH3^Kuw@1RiB9(Fwa_q8mA1^ z?hfQKRov8W5i*2vaR~F9AP-8-GE~RasFkf(1AGs;%y#QORQtoIcBfG*yJYLr>7*^l zLj^bq)qWZd#|osWsl~WD`gq_nOKruAsDWQYb=-nn<`esVAFAIG)I{e{6a9l+CXG%i z=b~0xgj!fRrr<18yNXQm&$D@$n^Nnc8n&YLz5}&~FWYhtYQi1X1E`c9we>$E*R@7k zVHSI|Q^u;T@md}fc@ruFVN@W?Y=bqZ)V*%&dyvcYa#OoKsDKWm0zQJ; zvQwyuE~DBFV!0}hM9t$M^Ttgn4~ldK61;g3br$MT9ek(&BdCtc?fXvDz}?6krpK21 zQ0>1!1>TS9chdSBDnnN>Mc;o0vumJ{s0oWvdsvR@IMcqbLJeGlYF~$1X&5!&^Y(o= zUJD47`aWB~4>jI5$YoA(TcYp(5)Z}L%xH>u4Nk-j*ok{FiZyKXY?W~wCXcdvi-nYD z;TWvLJ8>CSVIS%jGKqsW1@mz_F2J}BPbUvt=521uz;m48qU;3U*9>?KqnS8*rijv@a##YYHRsXBo=MCVbdx`Ik| zYJTE#$wOtR4E25{s@;6lz_q9aw4t^zjvwJm_&v@nAd8si81p*@9r9nu%3Q)-fGfuu zbCHVvoB2_qe6T3da2)x*mvS!qbcXu6@fV z{5ezxH^h11Aes-b5O-o4o4wZ=m$S#@_ z$S#-xrHQY|L9Vzd;Xa#+TCBwNI0uiR1|D0+eq$xK3~a}AeAbrNTHi#i=zU}^vj?@1 z^EeGtZ%qU+$6ANU`u>++dtgsc6Rbj=);H|?ji^1_jC=s*Q`A=VBS|tBP+M4ZTcZDT zROTvBXJ9^RD?QZKhA<14;wa`fojh9E?fji9?f#)szb{3nQq& zSEBl_MFp@CHSuQD57LLIt=VbouV7qzlr)+DrC<)u#TwMW-B^V^sK|e{UdEx6lR251 zI0u!nan_0W2<0+VAf47O>w469Z%yInL<4NKFZxjB&r#p=A?(7lI2@mznpn{~RQ*O& z`#w~v_hL34#R&c}wRcO}EjOh2++dTx(G9<{KYjJ}LT`1(;;g}yA?H3@+uJkd{sHj^ z+?dPDP&npq^)L0BoaRu(2?yK`f3U^z`CEKm#QASLr^RjcqGbzxo>L!ga_gO_7mKM~ zV<-~wqTx`mDeA;RRMJ1x7P}|Z))1h6Zd1D(jJYjdz2gr$i5W|r=18d3d9)$mHZCcS zI$cqxW3?LnHnLqiJft delta 2780 zcmYM#4@^~M7{~GF3Ta%th=iCXXyU(%Xrf}K6UDN!GXG#SvQ{`3?z+MmSGq?~nUzx#Rh~?>X;z-sgSZb1uKe znpOwr(-OBC{|@kf1pimvrk+_t_7qzoW+A!r_?4pmdysns7d9+*0qC zp%$*cS>`T;2+EIZ|`SnYvKwa)N)bstwUgJ_w3(4f9 zaTAdtmXCc2VlwmFQW{#xGk#+&a#-Njph~wBHSQp4CCz^SdsNBKqY~~$jlYg}V3^rx zS{CZLTvP%DoHU0mqM^VmP!GO{9QKA^uR%Sy7d6pg)I_bwVIAH-hg#ups7mzW?HD2` zO$(#q596eYMh8)U4b0<$_IeI#&z5^XhMKU-twojc1HXR=IqWM=TF5EXLN0p0*ZTI)}p4;ypK~<;) zmGDVaoHLlD@Ba@P+QVMdgGx_{L{Nc;q8`Xbt#mpn;3Iy$1p5*~ZCRz?uR+Dzg&cN( z(;95X@t8xfh`#@2G;;7c+>D#?B^=5|7pRZpunjdq58jQTq5QaDHqORET!@vZU&L>5 z8eYVin8BOJqqZ3J5}#$MS4)Jl5rKJ3q@@-EIp zC3FHiup9M@+RPsmCDMW|cnKD>wt## z=sUlWz>A=jr??|fCCl-Cp7-aXD)ylJq+eg{{c>a%?M+m?9muZOKIHYXR#e=elZM{r zpHVMYH|l{~s0Shw`7|+#>OYR!`xvScA0oSBpCVPa)0m8Z<0R~t8-IzX;6wDwaULE; z;s$n&#$+yJGFlTqh6C{_@0YnRqgJ#LdBk?1R&pF?;006y83dF0s1+`ES73zxO4Q4_ zw(mOoUqM5AwgGwJtroRc4ag#_1GR_OQ2|o!i3c8m+VgDGUe3laE()@x;@G2_M!&BlDm!JZap;lIbns@{12k33o)@=9tKcKd# z6K7!;7Gg9n9(N4}3%T$*4Q2j~dlCoJKZ{y%7pi18T${?@2l|PqL`vP&ZaFI6derk( z-rwT=I@IsN{;4+CYH74`K_w~XQ_zZHr~wtI09#O{-i=z(5nP9D(;C~tWBa}T@4)KD Tt&yVC#;chNLXE>mEgJG4F3t_w diff --git a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po index 9ce8469..5f1eedd 100644 --- a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po @@ -599,3 +599,15 @@ msgstr "Re-analyze entire game" #. TODO msgid "analysis:continuous" msgstr "Continuously analyze" + +#. TODO +msgid "ai:handicap" +msgstr "KataGo Handicap" + +#. TODO +msgid "aihelp:handicap" +msgstr "" +"KataGo optimized for playing higher handicap games.The `pda` setting " +"corresponds to `playoutDoublingAdvantage` in KataGo, from black's " +"perspective.When `automatic` is set, KaTrain will find a suitable value " +"automatically." diff --git a/katrain/i18n/locales/ru/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/ru/LC_MESSAGES/katrain.mo index 70212a2629aa6dc8da1e6482cf9ed2d041d00f8a..1229229e9fdb23cadf4fa455a880c97c5138cd1f 100644 GIT binary patch delta 3066 zcmYM#e@vBC9LMp4LV=9nEMnrotIS(>Aq*^lY`)vEW0douQLU*|l}`SCs9bDn!I zY>0bhV_fw6wD_%tzYqBz%YP(6HDkUQ^uHr0eo1{8Uc^y&-8yuzFDCZW%I!ad9Z~8$Si5W*w?y8){|S)c|)RmpN$dLACEiwd+Hz?6!TLOebx@ zXjFg?pxRHz;aH9|H7hWxjtvyJ%v$^4MbyA=qB`zEE_1-%??LrDhnnarYNCIT%M7BE z>Y1pO=Asr>h>2K&YFC~@{wbTKd?>XZRKq6J-nXLm@HJcSL``_e`V}gr=k4=fkgLCu zR+vg-Eo3~ZUTEv3sCJ7}$-h=o%?(8wK`!$=9}1uy$KVI3)Ez}de#ZJUa+w=^DDXrE z)5_CPE6qYZpM)B3ChCw@qQ>(m|9YKTQ4QOz9jF2JSr4HiK8AV=PT@Ux7B%n%`}`Iv zz$BKfiAJINO+jU%gb!t`(i&YsL6O&@G7v-svd%Vm6_vWT?DJ0KGF^PA-7!=^y{LfC zp|DVT|3jEv17)Bl%tP&AA*$mnd%prT@RO+at5GWrq6U1y z-rtJ-0ijagZJ+m`#ygE%<`N(EdjD@z$ir$z(^+^4i?9Qm@H9rSoQv0jD#^_WExtY8oxCFKGFt+1*Y{OxEzxv{gc@H;I zPv(c>K5WNq?8Y)Yifv|I3LqVp5LuQ^d;)=*fP zYs}mD%|w2|Fvxyf#Ql>vc(`LSD;+?P`TU|$FJu`5@g35qiFQ87D~8>ufclV_&0nZ3 z8(YYC0M?;i*UhLc?2J-S#D`H^aSnABlBdNER}pHj7NREFh8$e82bH zejXQ7&v=-hWc1BmK!wI+)XJaeQ!UL#@Z(upjp2@c1CL{*ajs5TcZxoceo0y47#j%x7z%=UlsJ$vh zj){2&HNbONhM(X_yoJi-ut#J43sL=wQCsvB4#yhI#x*#G^Jli(8y{mj^)JJF;(){k*I(8c!3mNs~Pz*%6QcC}^gjEgREBQ7@s!HBoXyVg_d)CEFL(C4;#{q;_R zx4yv>a{e37sdt+^;esU%9;Yf;>sC2oPb8vtHGxpb6AlLawP7a`;3543&5^l*=4v0$ z=hU{i{)k)esdBu2CpKfgQx^&}IjgFDZcSre*a><<;h?7`;%)I1ENk%iohr9E5@>QG z-Wqy^HB~-cmxNq~SmX8ioI0<+)^VM1vp3>a`#esI>udHncYC=$Uu#!>_H^f8Z>e;< delta 2782 zcmYM#eN0zX9LMo5sDVF4=qHb%fT%q9ln6csD6EWf=CGt#vXx~te5lYxwd^M8QWI=M z%Y+778%e_2V6HzLW=d_6l9tX!MH^UAl4gyjIcM*W_iVZAeVudex#xV(_niA<@6M2c z>JYC#IQm`VUn~D7@&D;Ds+qL~{x^nVJM}y91jgfe=VeT$9yZP_i0K%GOE3&q-~@aa zBXOO3Ug_)E8x$DB>QMtUVFY$yEFQ!0cmYS_MN~k)q59v#yD&(nXq=6jun^U+*wxEX z3wRO7;x3Ff&#aEZC>lOO#6dgK1Z$O6l&meu6+>?(pFyR(9~JNwRR4c*A_ka^ zq9vi;n}rG>pPS~el@v7aQ~~qLOE)Hmz>*C5${2r`U7|eHlYS?anHL@0iH%p^n+`^ipoR? zH)Sl^nS=^F1C;?Uhk_z0a2-~oQn}W3s6Z~O;--FkPyscd0&YfaSu1Ly&rtnNx_TdK zqKl}Buc89IiNxqxki6(HOhXMY3)OJ}>cv9Wz6v#PDe|sWxcW9!|5{Yw2T<=FbRI@! z=r}6iv#4?UaIC)nOBA$+Bd8Y@o&t$L4IGDhVJd2+Ij8|2bnT^hJ0R4SZFA3SP~$Zs zm$h;$$D^2zX$%&x@BbkRIarRHuo1UnfQ^0tJ=CE*iCV$WcrRYYJj{+WdlFy3wfHTP zTARyBE5$-wfsJ@K4q+0;Cor~FzK}v47Ge#a$BiLoPw~6DllmEEPs0-aKup1HScpyd zI}Ttfo}O&>1pbNoMJ;BQIk*Nx8E*&b5Wku1FQhh^{4163(ZD;_;_OEKrVk*Cv71QN zEGEV8Hv@^$icrtjVJE(V^*DzpH#6Z0tipLyIk5QgG_(70Ijb4O+H}vXl0s!BD+?vH zGt4$n51Y*ja0}sUf-3SxlkGzV(uKri-=MbWFU-K)x&G(59<^n!q5|EIbg>T9-VY$V zYymIJ-rNFXgg4;+K)O!O&Eo3uHJ>}--FX}0Cfn%=lSi4m_t1q73j0BeHSvf zHKWdwcb0-y)Q6FH1+~|=Z~>-en>~tUsQO`Cjl)P6Tgog&ScxRhj-U?LFIbIZ=KF_w z7jB{c59;t%Fc@3x*(VfqNP19b;W`E}e4!suBC>rp6PMvC%*D4+6Q9QA7`uqSBUpya zVf#=k`~sD^Ues3n?#r~yi_5cgsnevL}yuc(2;miX^Qp|)ri zPQ=AH1y{P~&$;?r7)^USYQe`biTUj+1*Jaf9F=4zCvZHANBeE zfvI>6br=&#kDjl`1l)=w$!c*8eu-MhBz`=+brfivTlfyYq&dQszDKw_{<`L@)CDP%154^zxCKb1wO!?Xr=4.3.1", + "kivy==2.0.0rc2", # rc3 failing on mac "kivymd>=0.104.1", "screeninfo;platform_system!='Darwin'", # for screen resolution, has problems on macos ], From 399e5ffd87caa82463e9ccb8f49611128fc1d212 Mon Sep 17 00:00:00 2001 From: Sander Land Date: Sat, 27 Jun 2020 01:04:08 +0200 Subject: [PATCH 2/2] fix pda sign --- katrain/core/ai.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/katrain/core/ai.py b/katrain/core/ai.py index 6918295..882f1c3 100644 --- a/katrain/core/ai.py +++ b/katrain/core/ai.py @@ -101,7 +101,7 @@ def request_ai_analysis(game: Game, cn: GameNode, extra_settings: Dict) -> Dict: def set_analysis(a): nonlocal analysis - analysis = a["moveInfos"] + analysis = a def set_error(a): nonlocal error @@ -129,10 +129,10 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, if ai_mode == AI_HANDICAP: pda = ai_settings["pda"] if ai_settings["automatic"]: - n_handicaps = len(game.root.get_list_property("AB")) + n_handicaps = len(game.root.get_list_property("AB", [])) MOVE_VALUE = 14 # could be rules dependent - b_stones_advantage = max(n_handicaps - 1, 0) - (cn.komi - MOVE_VALUE/2) / MOVE_VALUE - pda = min(3, max(-3, b_stones_advantage * (3/8) )) # max PDA at 8 stone adv, normal 9 stone game is 8.46 + b_stones_advantage = max(n_handicaps - 1, 0) - (cn.komi - MOVE_VALUE / 2) / MOVE_VALUE + pda = min(3, max(-3, -b_stones_advantage * (3 / 8))) # max PDA at 8 stone adv, normal 9 stone game is 8.46 handicap_analysis = request_ai_analysis( game, cn, {"playoutDoublingAdvantage": pda, "playoutDoublingAdvantagePla": "BLACK"} ) @@ -232,11 +232,9 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, else: raise ValueError(f"Unknown Policy-based AI mode {ai_mode}") else: # Engine based move - handicap_or_default = "Default" candidate_ai_moves = cn.candidate_moves if ai_mode == AI_HANDICAP: - candidate_ai_moves = handicap_analysis - handicap_or_default = "Handicap" + candidate_ai_moves = handicap_analysis["moveInfos"] top_cand = Move.from_gtp(candidate_ai_moves[0]["move"], player=cn.next_player) if top_cand.is_pass: # don't play suicidal to balance score - pass when it's best @@ -268,7 +266,10 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, game.katrain.log(f"Unknown AI mode {ai_mode} or policy missing, using default.", OUTPUT_INFO) ai_thoughts += f"Strategy {ai_mode} not found or unexpected fallback." aimove = top_cand - ai_thoughts += f"{handicap_or_default} strategy found {len(candidate_ai_moves)} moves returned from the engine and chose {aimove.gtp()} as top move" + if ai_mode == AI_HANDICAP: + ai_thoughts += f"Handicap strategy found {len(candidate_ai_moves)} moves returned from the engine and chose {aimove.gtp()} as top move. PDA based score {cn.format_score(handicap_analysis['rootInfo']['scoreLead'])} and win rate {cn.format_winrate(handicap_analysis['rootInfo']['winrate'])}" + else: + ai_thoughts += f"Default strategy found {len(candidate_ai_moves)} moves returned from the engine and chose {aimove.gtp()} as top move" game.katrain.log(f"AI thoughts: {ai_thoughts}", OUTPUT_DEBUG) played_node = game.play(aimove) played_node.ai_thoughts = ai_thoughts