Files
katrain-qt/katrain/core/base_katrain.py
T
c5587bf6e1 1.8.0 (#356)
* distributed option

* i18n, pause, etc

* fixes galore

* max buffer etc

* test override config

* maxgame

* visit

* contribute menu

* restore vars

* i18n

* actually start

* retry distr and errors

* pw eye / move speed

* cfg/no log

* shutdown fix

* shutdown fix

* download fix

* wut

* stats and desc

* esc fix

* Omit terminate queries from KataGoEngine.queries. (#353)

* press key h to clear current node analysis. (#352)

* clear current node all analysis

* add reset key binding

* reset all analysis off.

* code refactor

* code change according to review.

* remove useless variable

* code review changes

* clean up reset node

* oops

* Setup position feature (#354)

* go for zebras

* setup working!

* uhh

* tweak

* img

* fix i18n

* AEEEEEEEEEE and stop

* link in readme

* new game options for edit/new/setup (#357)

* new game options for edit/new/setup

* feedback

* fix

* ai thoughts

* no tristate cb

* branch fixing (#358)

* new game options for edit/new/setup

* feedback

* fix

* ai thoughts

* no tristate cb

* fix comma etc

* normal katago

* kata

* dll

* save window pos/size

* BAD comma

* new linux binary + allow default engine

* fix

* unused icon, build mac

* exe

* player new game fix

* fix i18n

* test test

* just print

* 한국어

* –활성화

* Add new Traditional Chinese translation (#362)

Improve some translations as well.

* cn (#363)

* cn

* rm old

* rm old

* informal you

* mo

* jp (#364)

* config and readme

* mo

* kgtraining

* fix score

* lower stddev a bit

* tweak weights

* 1.8 French Po (#365)

* fr and getattr fix

* -DBUILD_DISTRIBUTED=1

* openssl

* openssl

* openssl

* openssl

* config

* jp (num undos) (#366)

* clarify undo in en, po->mo

* fix player name

* new kata

* new kata

* Load game option save config (#367)

* in the load dialog,  "load fast analysis" and "rewind to the start" option ,save to config file

* in the load dialog,  "load fast analysis" and "rewind to the start" option ,save to config file

* default option

* remove useless override

* save check state when file dialog's submit event ,

* save config in callback

* readme

* active games

* de

* log games as json always

* black

* Russian localization for 1.8.0 (#375)

* ru

Co-authored-by: pdeblanc <peter@spaceandgames.com>
Co-authored-by: xiaoyifang <105986+xiaoyifang@users.noreply.github.com>
Co-authored-by: Liou, Guan-Cheng <Tony-Liou@users.noreply.github.com>
Co-authored-by: kaorahi <38910552+kaorahi@users.noreply.github.com>
Co-authored-by: Dontbtme <66470440+Dontbtme@users.noreply.github.com>
Co-authored-by: Alexander Kiselev <satoshi.yoda.register.264@gmail.com>
2021-03-05 20:40:48 +01:00

173 lines
6.7 KiB
Python

import os
import shutil
import sys
from kivy import Config
from kivy.storage.jsonstore import JsonStore
from katrain.core.ai import ai_rank_estimation
from katrain.core.constants import (
PLAYER_HUMAN,
PLAYER_AI,
PLAYING_NORMAL,
PLAYING_TEACHING,
OUTPUT_INFO,
OUTPUT_ERROR,
OUTPUT_DEBUG,
AI_DEFAULT,
CONFIG_MIN_VERSION,
DATA_FOLDER,
)
from katrain.core.utils import find_package_resource
class Player:
def __init__(self, player="B", player_type=PLAYER_HUMAN, player_subtype=PLAYING_NORMAL, periods_used=0):
self.player = player
self.sgf_rank = None
self.calculated_rank = None
self.name = ""
self.update(player_type, player_subtype)
self.periods_used = periods_used
def update(self, player_type=PLAYER_HUMAN, player_subtype=PLAYING_NORMAL):
self.player_type = player_type
self.player_subtype = player_subtype
@property
def ai(self):
return self.player_type == PLAYER_AI
@property
def human(self):
return self.player_type == PLAYER_HUMAN
@property
def being_taught(self):
return self.player_type == PLAYER_HUMAN and self.player_subtype == PLAYING_TEACHING
@property
def strategy(self):
return self.player_subtype if self.ai else AI_DEFAULT
def __str__(self):
return f"{self.player_type} ({self.player_subtype})"
class KaTrainBase:
USER_CONFIG_FILE = os.path.expanduser(os.path.join(DATA_FOLDER, "config.json"))
PACKAGE_CONFIG_FILE = "katrain/config.json"
"""Settings, logging, and players functionality, so other classes like bots who need a katrain instance can be used without a GUI"""
def __init__(self, force_package_config=False, debug_level=None, **kwargs):
self.debug_level = debug_level or 0
self.game = None
self.logger = lambda message, level=OUTPUT_INFO: self.log(message, level)
self.config_file = self._load_config(force_package_config=force_package_config)
self.debug_level = self.config("general/debug_level", OUTPUT_INFO) if debug_level is None else debug_level
Config.set("kivy", "log_level", "warning")
if self.debug_level >= OUTPUT_DEBUG:
Config.set("kivy", "log_enable", 1)
Config.set("kivy", "log_level", "debug")
# if self.debug_level >= OUTPUT_EXTRA_DEBUG:
# Config.set("kivy", "log_level", "trace")
self.players_info = {"B": Player("B"), "W": Player("W")}
self.reset_players()
def log(self, message, level=OUTPUT_INFO):
if level == OUTPUT_ERROR:
print(f"ERROR: {message}")
elif self.debug_level >= level:
print(message)
def _load_config(self, force_package_config):
if len(sys.argv) > 1 and sys.argv[1].endswith("config.json"):
config_file = os.path.abspath(sys.argv[1])
self.log(f"Using command line config file {config_file}", OUTPUT_INFO)
else:
user_config_file = find_package_resource(self.USER_CONFIG_FILE)
package_config_file = find_package_resource(self.PACKAGE_CONFIG_FILE)
if force_package_config:
config_file = package_config_file
else:
try:
if not os.path.exists(user_config_file):
os.makedirs(os.path.split(user_config_file)[0], exist_ok=True)
shutil.copyfile(package_config_file, user_config_file)
config_file = user_config_file
self.log(f"Copied package config to local file {config_file}", OUTPUT_INFO)
else: # user file exists
try:
version = JsonStore(user_config_file).get("general")["version"]
except Exception: # noqa E722 broken file etc
version = "0.0.0"
if version < CONFIG_MIN_VERSION:
backup = user_config_file + f".{version}.backup"
shutil.copyfile(user_config_file, backup)
shutil.copyfile(package_config_file, user_config_file)
self.log(
f"Copied package config file to {user_config_file} as user file is outdated or broken ({version}<{CONFIG_MIN_VERSION}). Old version stored as {backup}",
OUTPUT_INFO,
)
config_file = user_config_file
self.log(f"Using user config file {config_file}", OUTPUT_INFO)
except Exception as e:
config_file = package_config_file
self.log(
f"Using package config file {config_file} (exception {e} occurred when finding or creating user config)",
OUTPUT_INFO,
)
try:
self._config_store = JsonStore(config_file, indent=4)
except Exception as e:
self.log(f"Failed to load config {config_file}: {e}", OUTPUT_ERROR)
sys.exit(1)
self._config = dict(self._config_store)
return config_file
def save_config(self, key=None):
if key is None:
for k, v in self._config.items():
self._config_store.put(k, **v)
else:
self._config_store.put(key, **self._config[key])
def config(self, setting, default=None):
try:
if "/" in setting:
cat, key = setting.split("/")
return self._config.get(cat, {}).get(key, default)
else:
return self._config.get(setting, default)
except KeyError:
self.log(f"Missing configuration option {setting}", OUTPUT_ERROR)
def update_player(self, bw, **kwargs):
self.players_info[bw].update(**kwargs)
self.update_calculated_ranks()
def update_calculated_ranks(self):
for bw, player_info in self.players_info.items():
if player_info.player_type == PLAYER_AI:
settings = self.config(f"ai/{player_info.strategy}")
player_info.calculated_rank = ai_rank_estimation(player_info.player_subtype, settings)
else:
player_info.calculated_rank = None
def reset_players(self):
self.update_player("B")
self.update_player("W")
for v in self.players_info.values():
v.periods_used = 0
@property
def last_player_info(self) -> Player:
return self.players_info[self.game.current_node.player]
@property
def next_player_info(self) -> Player:
return self.players_info[self.game.current_node.next_player]