1.8.4: new zealand/tt rules, katago 1.8.1 (#406)
* new zealand and tt rules * test * 1.8.4 * note at start, avoid spaces * fix dict rules, test
This commit is contained in:
1 parent
82757e51d1
commit
7dcb80e873
26 files changed
+149
-38
No files matched your search
+6
-2
@@ -278,7 +278,9 @@ class KaTrainGui(Screen, KaTrainBase):
|
|||||||
"save_game",
|
"save_game",
|
||||||
"find_mistake",
|
"find_mistake",
|
||||||
]:
|
]:
|
||||||
self.controls.set_status(i18n._("gui-locked").format(action=msg), STATUS_INFO, check_level=False)
|
self.controls.set_status(
|
||||||
|
i18n._("gui-locked").format(action=msg), STATUS_INFO, check_level=False
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
fn = getattr(self, f"_do_{msg}")
|
fn = getattr(self, f"_do_{msg}")
|
||||||
fn(*args, **kwargs)
|
fn(*args, **kwargs)
|
||||||
@@ -292,7 +294,9 @@ class KaTrainGui(Screen, KaTrainBase):
|
|||||||
if self.game:
|
if self.game:
|
||||||
if message.endswith("popup"): # gui code needs to run in main kivy thread.
|
if message.endswith("popup"): # gui code needs to run in main kivy thread.
|
||||||
if self.contributing and "save" not in message and message != "contribute-popup":
|
if self.contributing and "save" not in message and message != "contribute-popup":
|
||||||
self.controls.set_status(i18n._("gui-locked").format(action=message), STATUS_INFO, check_level=False)
|
self.controls.set_status(
|
||||||
|
i18n._("gui-locked").format(action=message), STATUS_INFO, check_level=False
|
||||||
|
)
|
||||||
return
|
return
|
||||||
fn = getattr(self, f"_do_{message.replace('-', '_')}")
|
fn = getattr(self, f"_do_{message.replace('-', '_')}")
|
||||||
Clock.schedule_once(lambda _dt: fn(*args, **kwargs), -1)
|
Clock.schedule_once(lambda _dt: fn(*args, **kwargs), -1)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
PROGRAM_NAME = "KaTrain"
|
PROGRAM_NAME = "KaTrain"
|
||||||
VERSION = "1.8.3"
|
VERSION = "1.8.4"
|
||||||
HOMEPAGE = "https://github.com/sanderland/katrain"
|
HOMEPAGE = "https://github.com/sanderland/katrain"
|
||||||
CONFIG_MIN_VERSION = "1.8.0" # keep config files from this version
|
CONFIG_MIN_VERSION = "1.8.0" # keep config files from this version
|
||||||
ANALYSIS_FORMAT_VERSION = "1.0"
|
ANALYSIS_FORMAT_VERSION = "1.0"
|
||||||
|
|||||||
@@ -49,12 +49,15 @@ class KataGoContributeEngine(BaseEngine):
|
|||||||
self.move_speed = self.config.get("movespeed", 2.0)
|
self.move_speed = self.config.get("movespeed", 2.0)
|
||||||
|
|
||||||
exe = self.get_engine_path(self.config.get("katago"))
|
exe = self.get_engine_path(self.config.get("katago"))
|
||||||
cacert_path = os.path.join(os.path.split(exe)[0], 'cacert.pem')
|
cacert_path = os.path.join(os.path.split(exe)[0], "cacert.pem")
|
||||||
if not os.path.isfile(cacert_path):
|
if not os.path.isfile(cacert_path):
|
||||||
try:
|
try:
|
||||||
shutil.copyfile( find_package_resource('katrain/KataGo/cacert.pem'), cacert_path)
|
shutil.copyfile(find_package_resource("katrain/KataGo/cacert.pem"), cacert_path)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.katrain.log(f"Could not copy cacert file ({e}), please add it manually to your katago.exe directory",OUTPUT_ERROR)
|
self.katrain.log(
|
||||||
|
f"Could not copy cacert file ({e}), please add it manually to your katago.exe directory",
|
||||||
|
OUTPUT_ERROR,
|
||||||
|
)
|
||||||
cfg = find_package_resource(self.config.get("config"))
|
cfg = find_package_resource(self.config.get("config"))
|
||||||
|
|
||||||
settings_dict = {
|
settings_dict = {
|
||||||
@@ -63,7 +66,7 @@ class KataGoContributeEngine(BaseEngine):
|
|||||||
"maxSimultaneousGames": self.config.get("maxgames") or self.DEFAULT_MAX_GAMES,
|
"maxSimultaneousGames": self.config.get("maxgames") or self.DEFAULT_MAX_GAMES,
|
||||||
"includeOwnership": self.config.get("ownership") or False,
|
"includeOwnership": self.config.get("ownership") or False,
|
||||||
"logGamesAsJson": True,
|
"logGamesAsJson": True,
|
||||||
"homeDataDir": os.path.expanduser(DATA_FOLDER)
|
"homeDataDir": os.path.expanduser(DATA_FOLDER),
|
||||||
}
|
}
|
||||||
self.max_buffer_games = 2 * settings_dict["maxSimultaneousGames"]
|
self.max_buffer_games = 2 * settings_dict["maxSimultaneousGames"]
|
||||||
settings = {f"{k}={v}" for k, v in settings_dict.items()}
|
settings = {f"{k}={v}" for k, v in settings_dict.items()}
|
||||||
|
|||||||
@@ -26,12 +26,13 @@ class EngineDiedException(Exception):
|
|||||||
|
|
||||||
class BaseEngine: # some common elements between analysis and contribute engine
|
class BaseEngine: # some common elements between analysis and contribute engine
|
||||||
|
|
||||||
# TODO: we don't support suicide in game.py, so no "tt": "tromp-taylor", "nz": "new-zealand"
|
|
||||||
RULESETS_ABBR = [
|
RULESETS_ABBR = [
|
||||||
("jp", "japanese"),
|
("jp", "japanese"),
|
||||||
("cn", "chinese"),
|
("cn", "chinese"),
|
||||||
("ko", "korean"),
|
("ko", "korean"),
|
||||||
("aga", "aga"),
|
("aga", "aga"),
|
||||||
|
("tt", "tromp-taylor"),
|
||||||
|
("nz", "new zealand"),
|
||||||
("stone_scoring", "stone_scoring"),
|
("stone_scoring", "stone_scoring"),
|
||||||
]
|
]
|
||||||
RULESETS = {fromkey: name for abbr, name in RULESETS_ABBR for fromkey in [abbr, name]}
|
RULESETS = {fromkey: name for abbr, name in RULESETS_ABBR for fromkey in [abbr, name]}
|
||||||
@@ -41,8 +42,7 @@ class BaseEngine: # some common elements between analysis and contribute engine
|
|||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_rules(node):
|
def get_rules(ruleset):
|
||||||
ruleset = node.ruleset
|
|
||||||
if ruleset.strip().startswith("{"):
|
if ruleset.strip().startswith("{"):
|
||||||
try:
|
try:
|
||||||
ruleset = json.loads(ruleset)
|
ruleset = json.loads(ruleset)
|
||||||
@@ -386,7 +386,7 @@ class KataGoEngine(BaseEngine):
|
|||||||
if self.config.get("wide_root_noise", 0.0) > 0.0: # don't send if 0.0, so older versions don't error
|
if self.config.get("wide_root_noise", 0.0) > 0.0: # don't send if 0.0, so older versions don't error
|
||||||
settings["wideRootNoise"] = self.config["wide_root_noise"]
|
settings["wideRootNoise"] = self.config["wide_root_noise"]
|
||||||
query = {
|
query = {
|
||||||
"rules": self.get_rules(analysis_node),
|
"rules": self.get_rules(analysis_node.ruleset),
|
||||||
"priority": self.base_priority + priority,
|
"priority": self.base_priority + priority,
|
||||||
"analyzeTurns": [len(moves)],
|
"analyzeTurns": [len(moves)],
|
||||||
"maxVisits": visits,
|
"maxVisits": visits,
|
||||||
|
|||||||
+20
-11
@@ -153,12 +153,11 @@ class BaseGame:
|
|||||||
if self.board[move.coords[1]][move.coords[0]] != -1:
|
if self.board[move.coords[1]][move.coords[0]] != -1:
|
||||||
raise IllegalMoveException("Space occupied")
|
raise IllegalMoveException("Space occupied")
|
||||||
|
|
||||||
|
# merge chains connected by this move, or create a new one
|
||||||
nb_chains = list({c for c in neighbours([move]) if c >= 0 and self.chains[c][0].player == move.player})
|
nb_chains = list({c for c in neighbours([move]) if c >= 0 and self.chains[c][0].player == move.player})
|
||||||
if nb_chains:
|
if nb_chains:
|
||||||
this_chain = nb_chains[0]
|
this_chain = nb_chains[0]
|
||||||
self.board = [
|
self.board = [[nb_chains[0] if sq in nb_chains else sq for sq in line] for line in self.board]
|
||||||
[nb_chains[0] if sq in nb_chains else sq for sq in line] for line in self.board
|
|
||||||
] # merge chains connected by this move
|
|
||||||
for oc in nb_chains[1:]:
|
for oc in nb_chains[1:]:
|
||||||
self.chains[nb_chains[0]] += self.chains[oc]
|
self.chains[nb_chains[0]] += self.chains[oc]
|
||||||
self.chains[oc] = []
|
self.chains[oc] = []
|
||||||
@@ -168,9 +167,10 @@ class BaseGame:
|
|||||||
self.chains.append([move])
|
self.chains.append([move])
|
||||||
self.board[move.coords[1]][move.coords[0]] = this_chain
|
self.board[move.coords[1]][move.coords[0]] = this_chain
|
||||||
|
|
||||||
|
# check captures
|
||||||
opp_nb_chains = {c for c in neighbours([move]) if c >= 0 and self.chains[c][0].player != move.player}
|
opp_nb_chains = {c for c in neighbours([move]) if c >= 0 and self.chains[c][0].player != move.player}
|
||||||
for c in opp_nb_chains:
|
for c in opp_nb_chains:
|
||||||
if -1 not in neighbours(self.chains[c]):
|
if -1 not in neighbours(self.chains[c]): # no liberties
|
||||||
self.last_capture += self.chains[c]
|
self.last_capture += self.chains[c]
|
||||||
for om in self.chains[c]:
|
for om in self.chains[c]:
|
||||||
self.board[om.coords[1]][om.coords[0]] = -1
|
self.board[om.coords[1]][om.coords[0]] = -1
|
||||||
@@ -179,8 +179,21 @@ class BaseGame:
|
|||||||
raise IllegalMoveException("Ko")
|
raise IllegalMoveException("Ko")
|
||||||
self.prisoners += self.last_capture
|
self.prisoners += self.last_capture
|
||||||
|
|
||||||
if -1 not in neighbours(self.chains[this_chain]): # TODO: NZ rules?
|
# suicide: check rules and throw exception if needed
|
||||||
raise IllegalMoveException("Suicide")
|
if -1 not in neighbours(self.chains[this_chain]):
|
||||||
|
rules = self.rules
|
||||||
|
if len(self.chains[this_chain]) == 1: # even in new zealand rules, single stone suicide is not allowed
|
||||||
|
raise IllegalMoveException("Single stone suicide")
|
||||||
|
elif (isinstance(rules, str) and rules in ["tromp-taylor", "new zealand"]) or (
|
||||||
|
isinstance(rules, dict) and rules.get("suicide", False)
|
||||||
|
):
|
||||||
|
self.last_capture += self.chains[this_chain]
|
||||||
|
for om in self.chains[this_chain]:
|
||||||
|
self.board[om.coords[1]][om.coords[0]] = -1
|
||||||
|
self.chains[this_chain] = []
|
||||||
|
self.prisoners += self.last_capture
|
||||||
|
else: # suicide not allowed by rules
|
||||||
|
raise IllegalMoveException("Suicide")
|
||||||
|
|
||||||
# Play a Move from the current position, raise IllegalMoveException if invalid.
|
# Play a Move from the current position, raise IllegalMoveException if invalid.
|
||||||
def play(self, move: Move, ignore_ko: bool = False):
|
def play(self, move: Move, ignore_ko: bool = False):
|
||||||
@@ -290,7 +303,7 @@ class BaseGame:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def rules(self):
|
def rules(self):
|
||||||
return self.root.ruleset
|
return KataGoEngine.get_rules(self.root.ruleset)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def manual_score(self):
|
def manual_score(self):
|
||||||
@@ -437,10 +450,6 @@ class Game(BaseGame):
|
|||||||
node.clear_analysis()
|
node.clear_analysis()
|
||||||
node.analyze(self.engines[node.next_player], priority=priority, analyze_fast=analyze_fast)
|
node.analyze(self.engines[node.next_player], priority=priority, analyze_fast=analyze_fast)
|
||||||
|
|
||||||
@property
|
|
||||||
def rules(self): # maybe not needed
|
|
||||||
return self.engines["B"].get_rules(self.root)
|
|
||||||
|
|
||||||
def set_current_node(self, node):
|
def set_current_node(self, node):
|
||||||
if self.insert_mode:
|
if self.insert_mode:
|
||||||
self.katrain.controls.set_status(i18n._("finish inserting before navigating"), STATUS_ERROR)
|
self.katrain.controls.set_status(i18n._("finish inserting before navigating"), STATUS_ERROR)
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class GameNode(SGFNode):
|
|||||||
for c in v.split(SGF_SEPARATOR_MARKER)
|
for c in v.split(SGF_SEPARATOR_MARKER)
|
||||||
if c.strip() and SGF_INTERNAL_COMMENTS_MARKER not in c
|
if c.strip() and SGF_INTERNAL_COMMENTS_MARKER not in c
|
||||||
]
|
]
|
||||||
self.note = "".join(comments) # no super call intended, just save as note to be editable
|
self.note = "".join(comments).strip() # no super call intended, just save as note to be editable
|
||||||
else:
|
else:
|
||||||
return super().add_list_property(property, values)
|
return super().add_list_property(property, values)
|
||||||
|
|
||||||
@@ -143,10 +143,13 @@ class GameNode(SGFNode):
|
|||||||
properties["SQ"] = best_sq
|
properties["SQ"] = best_sq
|
||||||
if top_x and "MA" not in properties:
|
if top_x and "MA" not in properties:
|
||||||
properties["MA"] = [top_x]
|
properties["MA"] = [top_x]
|
||||||
comments.append(self.comment(sgf=True, interactive=False) + SGF_INTERNAL_COMMENTS_MARKER)
|
comments.append("\n" + self.comment(sgf=True, interactive=False) + SGF_INTERNAL_COMMENTS_MARKER)
|
||||||
if self.is_root:
|
if self.is_root:
|
||||||
comments = [
|
if save_marks:
|
||||||
i18n._("SGF start message") + SGF_INTERNAL_COMMENTS_MARKER + "\n",
|
comments = [i18n._("SGF start message") + SGF_INTERNAL_COMMENTS_MARKER + "\n"]
|
||||||
|
else:
|
||||||
|
comments = []
|
||||||
|
comments += [
|
||||||
*comments,
|
*comments,
|
||||||
f"\nSGF generated by {PROGRAM_NAME} {VERSION}{SGF_INTERNAL_COMMENTS_MARKER}\n",
|
f"\nSGF generated by {PROGRAM_NAME} {VERSION}{SGF_INTERNAL_COMMENTS_MARKER}\n",
|
||||||
]
|
]
|
||||||
@@ -162,9 +165,9 @@ class GameNode(SGFNode):
|
|||||||
elif "KTSID" in properties:
|
elif "KTSID" in properties:
|
||||||
del properties["KTSID"]
|
del properties["KTSID"]
|
||||||
if note:
|
if note:
|
||||||
comments.append(f"{self.note}")
|
comments.insert(0, f"{self.note}\n") # user notes at top!
|
||||||
if comments:
|
if comments:
|
||||||
properties["C"] = [SGF_SEPARATOR_MARKER.join(comments)]
|
properties["C"] = [SGF_SEPARATOR_MARKER.join(comments).strip("\n")]
|
||||||
elif "C" in properties:
|
elif "C" in properties:
|
||||||
del properties["C"]
|
del properties["C"]
|
||||||
return properties
|
return properties
|
||||||
|
|||||||
@@ -455,20 +455,20 @@ class BaseConfigPopup(QuickConfigGui):
|
|||||||
|
|
||||||
KATAGOS = {
|
KATAGOS = {
|
||||||
"win": {
|
"win": {
|
||||||
"OpenCL v1.8.0": "https://github.com/lightvector/KataGo/releases/download/v1.8.0/katago-v1.8.0-opencl-windows-x64.zip",
|
"OpenCL v1.8.1": "https://github.com/lightvector/KataGo/releases/download/v1.8.1/katago-v1.8.1-opencl-windows-x64.zip",
|
||||||
"Eigen AVX2 (Modern CPUs) v1.8.0": "https://github.com/lightvector/KataGo/releases/download/v1.8.0/katago-v1.8.0-eigenavx2-windows-x64.zip",
|
"Eigen AVX2 (Modern CPUs) v1.8.1": "https://github.com/lightvector/KataGo/releases/download/v1.8.1/katago-v1.8.1-eigenavx2-windows-x64.zip",
|
||||||
"Eigen (CPU, Non-optimized) v1.8.0": "https://github.com/lightvector/KataGo/releases/download/v1.8.0/katago-v1.8.0-eigen-windows-x64.zip",
|
"Eigen (CPU, Non-optimized) v1.8.1": "https://github.com/lightvector/KataGo/releases/download/v1.8.1/katago-v1.8.1-eigen-windows-x64.zip",
|
||||||
"OpenCL v1.6.1 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.6.1%2Bbs29/katago-v1.6.1+bs29-gpu-opencl-windows-x64.zip",
|
"OpenCL v1.6.1 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.6.1%2Bbs29/katago-v1.6.1+bs29-gpu-opencl-windows-x64.zip",
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"OpenCL v1.8.0": "https://github.com/lightvector/KataGo/releases/download/v1.8.0/katago-v1.8.0-opencl-linux-x64.zip",
|
"OpenCL v1.8.1": "https://github.com/lightvector/KataGo/releases/download/v1.8.1/katago-v1.8.1-opencl-linux-x64.zip",
|
||||||
"Eigen AVX2 (Modern CPUs) v1.8.0": "https://github.com/lightvector/KataGo/releases/download/v1.8.0/katago-v1.8.0-eigenavx2-linux-x64.zip",
|
"Eigen AVX2 (Modern CPUs) v1.8.1": "https://github.com/lightvector/KataGo/releases/download/v1.8.1/katago-v1.8.1-eigenavx2-linux-x64.zip",
|
||||||
"Eigen (CPU, Non-optimized) v1.8.0": "https://github.com/lightvector/KataGo/releases/download/v1.8.0/katago-v1.8.0-eigen-linux-x64.zip",
|
"Eigen (CPU, Non-optimized) v1.8.1": "https://github.com/lightvector/KataGo/releases/download/v1.8.1/katago-v1.8.1-eigen-linux-x64.zip",
|
||||||
"OpenCL v1.6.1 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.6.1%2Bbs29/katago-v1.6.1+bs29-gpu-opencl-linux-x64.zip",
|
"OpenCL v1.6.1 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.6.1%2Bbs29/katago-v1.6.1+bs29-gpu-opencl-linux-x64.zip",
|
||||||
},
|
},
|
||||||
"just-descriptions": {
|
"just-descriptions": {
|
||||||
"CUDA v1.8.0 (Windows)": "https://github.com/lightvector/KataGo/releases/download/v1.8.0/katago-v1.8.0-gpu-cuda10.2-windows-x64.zip",
|
"CUDA v1.8.1 (Windows)": "https://github.com/lightvector/KataGo/releases/download/v1.8.1/katago-v1.8.1-gpu-cuda10.2-windows-x64.zip",
|
||||||
"CUDA v1.8.0 (Linux)": "https://github.com/lightvector/KataGo/releases/download/v1.8.0/katago-v1.8.0-gpu-cuda10.2-linux-x64.zip",
|
"CUDA v1.8.1 (Linux)": "https://github.com/lightvector/KataGo/releases/download/v1.8.1/katago-v1.8.1-gpu-cuda10.2-linux-x64.zip",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -837,3 +837,11 @@ msgstr "这会产生部分的对局让你接著下。例如:你可以使用它
|
|||||||
#. change komi etc in current game
|
#. change komi etc in current game
|
||||||
msgid "editgame"
|
msgid "editgame"
|
||||||
msgstr "编辑对局资讯"
|
msgstr "编辑对局资讯"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "new zealand"
|
||||||
|
msgstr "New Zealand"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tromp-taylor"
|
||||||
|
msgstr "Tromp-Taylor"
|
||||||
Binary file not shown.
@@ -904,3 +904,11 @@ msgstr ""
|
|||||||
#. change komi etc in current game
|
#. change komi etc in current game
|
||||||
msgid "editgame"
|
msgid "editgame"
|
||||||
msgstr "Spiel editieren"
|
msgstr "Spiel editieren"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "new zealand"
|
||||||
|
msgstr "New Zealand"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tromp-taylor"
|
||||||
|
msgstr "Tromp-Taylor"
|
||||||
Binary file not shown.
@@ -398,6 +398,12 @@ msgstr "Korean"
|
|||||||
msgid "aga"
|
msgid "aga"
|
||||||
msgstr "AGA"
|
msgstr "AGA"
|
||||||
|
|
||||||
|
msgid "tromp-taylor"
|
||||||
|
msgstr "Tromp-Taylor"
|
||||||
|
|
||||||
|
msgid "new zealand"
|
||||||
|
msgstr "New Zealand"
|
||||||
|
|
||||||
msgid "stone_scoring"
|
msgid "stone_scoring"
|
||||||
msgstr "Ancient Chinese"
|
msgstr "Ancient Chinese"
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -916,3 +916,11 @@ msgstr ""
|
|||||||
#. TODO - change komi etc in current game
|
#. TODO - change komi etc in current game
|
||||||
msgid "editgame"
|
msgid "editgame"
|
||||||
msgstr "Edit Game Info"
|
msgstr "Edit Game Info"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "new zealand"
|
||||||
|
msgstr "New Zealand"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tromp-taylor"
|
||||||
|
msgstr "Tromp-Taylor"
|
||||||
Binary file not shown.
@@ -898,3 +898,11 @@ msgstr ""
|
|||||||
|
|
||||||
msgid "editgame"
|
msgid "editgame"
|
||||||
msgstr "Partie en cours"
|
msgstr "Partie en cours"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "new zealand"
|
||||||
|
msgstr "New Zealand"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tromp-taylor"
|
||||||
|
msgstr "Tromp-Taylor"
|
||||||
Binary file not shown.
@@ -881,3 +881,11 @@ msgstr ""
|
|||||||
#. change komi etc in current game
|
#. change komi etc in current game
|
||||||
msgid "editgame"
|
msgid "editgame"
|
||||||
msgstr "対局情報を編集"
|
msgstr "対局情報を編集"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "new zealand"
|
||||||
|
msgstr "New Zealand"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tromp-taylor"
|
||||||
|
msgstr "Tromp-Taylor"
|
||||||
Binary file not shown.
@@ -836,3 +836,11 @@ msgstr ""
|
|||||||
|
|
||||||
msgid "editgame"
|
msgid "editgame"
|
||||||
msgstr "대국 정보 편집"
|
msgstr "대국 정보 편집"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "new zealand"
|
||||||
|
msgstr "New Zealand"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tromp-taylor"
|
||||||
|
msgstr "Tromp-Taylor"
|
||||||
Binary file not shown.
@@ -855,3 +855,11 @@ msgstr ""
|
|||||||
|
|
||||||
msgid "editgame"
|
msgid "editgame"
|
||||||
msgstr "Редактировать игры"
|
msgstr "Редактировать игры"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "new zealand"
|
||||||
|
msgstr "New Zealand"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tromp-taylor"
|
||||||
|
msgstr "Tromp-Taylor"
|
||||||
Binary file not shown.
@@ -863,3 +863,11 @@ msgstr "這會產生部分的對局讓你接著下。例如:你可以使用它
|
|||||||
#. change komi etc in current game
|
#. change komi etc in current game
|
||||||
msgid "editgame"
|
msgid "editgame"
|
||||||
msgstr "編輯對局資訊"
|
msgstr "編輯對局資訊"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "new zealand"
|
||||||
|
msgstr "New Zealand"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tromp-taylor"
|
||||||
|
msgstr "Tromp-Taylor"
|
||||||
+24
-2
@@ -1,6 +1,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from katrain.core.base_katrain import KaTrainBase
|
from katrain.core.base_katrain import KaTrainBase
|
||||||
|
from katrain.core.engine import BaseEngine
|
||||||
from katrain.core.game import Game, IllegalMoveException, Move, KaTrainSGF
|
from katrain.core.game import Game, IllegalMoveException, Move, KaTrainSGF
|
||||||
from katrain.core.game_node import GameNode
|
from katrain.core.game_node import GameNode
|
||||||
|
|
||||||
@@ -55,9 +56,8 @@ class TestBoard:
|
|||||||
assert 3 == len(b.stones)
|
assert 3 == len(b.stones)
|
||||||
assert 2 == len(b.prisoners)
|
assert 2 == len(b.prisoners)
|
||||||
b.play(Move.from_gtp("B1", player="B"))
|
b.play(Move.from_gtp("B1", player="B"))
|
||||||
with pytest.raises(IllegalMoveException) as exc:
|
with pytest.raises(IllegalMoveException, match="Single stone suicide"):
|
||||||
b.play(Move.from_gtp("A1", player="W"))
|
b.play(Move.from_gtp("A1", player="W"))
|
||||||
assert "Suicide" in str(exc.value)
|
|
||||||
assert 1 == len(self.nonempty_chains(b))
|
assert 1 == len(self.nonempty_chains(b))
|
||||||
assert 4 == len(b.stones)
|
assert 4 == len(b.stones)
|
||||||
assert 2 == len(b.prisoners)
|
assert 2 == len(b.prisoners)
|
||||||
@@ -118,3 +118,25 @@ class TestBoard:
|
|||||||
root2 = KaTrainSGF.parse_sgf("(;GM[1]FF[4]SZ[19]HA[2];)")
|
root2 = KaTrainSGF.parse_sgf("(;GM[1]FF[4]SZ[19]HA[2];)")
|
||||||
game2 = Game(MockKaTrain(force_package_config=True), MockEngine(), move_tree=root2)
|
game2 = Game(MockKaTrain(force_package_config=True), MockEngine(), move_tree=root2)
|
||||||
assert 2 == len(game2.root.placements)
|
assert 2 == len(game2.root.placements)
|
||||||
|
|
||||||
|
def test_suicide(self):
|
||||||
|
rulesets_to_test = BaseEngine.RULESETS_ABBR + [('{"suicide":true}', ""), ('{"suicide":false}', "")]
|
||||||
|
for shortrule, _ in rulesets_to_test:
|
||||||
|
new_game = GameNode(properties={"SZ": 19, "RU": shortrule})
|
||||||
|
b = Game(MockKaTrain(force_package_config=True), MockEngine(), move_tree=new_game)
|
||||||
|
b.play(Move.from_gtp("A18", player="B"))
|
||||||
|
b.play(Move.from_gtp("B18", player="B"))
|
||||||
|
b.play(Move.from_gtp("C19", player="B"))
|
||||||
|
b.play(Move.from_gtp("A19", player="W"))
|
||||||
|
assert 4 == len(b.stones)
|
||||||
|
assert 0 == len(b.prisoners)
|
||||||
|
|
||||||
|
if shortrule in ["tt", "nz", '{"suicide":true}']:
|
||||||
|
b.play(Move.from_gtp("B19", player="W"))
|
||||||
|
assert 3 == len(b.stones)
|
||||||
|
assert 2 == len(b.prisoners)
|
||||||
|
else:
|
||||||
|
with pytest.raises(IllegalMoveException, match="Suicide"):
|
||||||
|
b.play(Move.from_gtp("B19", player="W"))
|
||||||
|
assert 4 == len(b.stones)
|
||||||
|
assert 0 == len(b.prisoners)
|
||||||
Reference in new issue
Block a user