clean up old files
This commit is contained in:
1 parent
fcfafae2ce
commit
45abd04230
3 files changed
+1
-270
No files matched your search
@@ -100,7 +100,7 @@ class Move:
|
||||
text += f"(Was considered last move as: {outdated_evaluation:.0%})\n"
|
||||
points_lost = self.player_sign * (prev_best_score - score)
|
||||
if points_lost > 0.5:
|
||||
text += f"Estimate point loss: {points_lost:.1f}\n"
|
||||
text += f"Estimated point loss: {points_lost:.1f}\n"
|
||||
if eval or sgf: # show undos on move itself in both sgf and while playing
|
||||
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 undids:
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
{
|
||||
"analysis": {
|
||||
"pass_visits": 200,
|
||||
"pass_visits_fast": 50,
|
||||
"visits": 3500,
|
||||
"visits_fast": 1500
|
||||
},
|
||||
"board": {
|
||||
"size": 19,
|
||||
"komi_19": 6.5,
|
||||
"komi_13": 6.5,
|
||||
"komi_9": 6.5
|
||||
},
|
||||
"ui": {
|
||||
"size_min": 1,
|
||||
"size_max": 15,
|
||||
"stones": [ [0.05, 0.05, 0.05], [0.95, 0.95, 0.95] ],
|
||||
"ghost_alpha": 0.5,
|
||||
"eval_colors": [[0.537, 0.129, 0.42], [1, 0, 0], [1, 0.95, 0], [0.117, 0.588, 0]],
|
||||
"undo_circle_col": [0.88,0.02,0.17,0.5],
|
||||
"undo_alpha": 0.5,
|
||||
"eval_knots": [0, 0.5, 0.875, 1],
|
||||
"eval_bounds": [1,12],
|
||||
"board_margin": 1.5,
|
||||
"starpoint_size": 0.1,
|
||||
"stone_size": 0.475,
|
||||
"board_color": [0.85, 0.68, 0.40],
|
||||
"line_color": [0,0,0]
|
||||
},
|
||||
"engine": {
|
||||
"command": "KataGo/katago-cuda analysis -model models/b10-1.3.gz -config KataGo/analysis_config.cfg -analysis-threads 8"
|
||||
},
|
||||
"trainer": {
|
||||
"balance_play_target_score": 2,
|
||||
"balance_play_randomize_eval": 0.95,
|
||||
"balance_play_min_eval": 0.875,
|
||||
"balance_play_min_visits": 20,
|
||||
"undo_eval_threshold": 0.875,
|
||||
"undo_point_threshold": 1,
|
||||
"num_undo_prompts": 1,
|
||||
"sgf_show_best_move_threshold": 0.95
|
||||
},
|
||||
"debug": {
|
||||
"level": 1
|
||||
}
|
||||
}
|
||||
@@ -1,223 +0,0 @@
|
||||
import random
|
||||
import re
|
||||
import shlex
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
|
||||
DEBUG = True
|
||||
|
||||
|
||||
class GoEngine:
|
||||
GTP_COORD = "ABCDEFGHJKLMNOPQRSTUVWYXYZ"
|
||||
SGF_COORD = [chr(i) for i in range(97, 123)]
|
||||
|
||||
def __init__(self, boardsize=19):
|
||||
self.boardsize = boardsize
|
||||
self.moves = []
|
||||
self.stones = [] # TODO refactor stones vs moves distinction
|
||||
self.komi = 7.5
|
||||
self.turn = 0
|
||||
|
||||
def start(self, boardsize):
|
||||
self.__init__(boardsize)
|
||||
|
||||
def play(self, coords, player=None, temp=False):
|
||||
if not temp:
|
||||
self.moves.append((player or self.turn, *(coords or [None, None]))) # pass is x=y=None
|
||||
if not player:
|
||||
self.turn = 1 - self.turn
|
||||
|
||||
def generate_move(self):
|
||||
for _ in range(1000):
|
||||
move = (random.randint(0, self.boardsize - 1), random.randint(0, self.boardsize - 1))
|
||||
if move not in [(x, y) for _, x, y in self.stones]:
|
||||
break
|
||||
self.play(move)
|
||||
|
||||
def undo(self):
|
||||
if self.moves:
|
||||
self.moves.pop()
|
||||
self.turn = 1 - self.turn
|
||||
|
||||
def gtp2ix(self, gtpmove):
|
||||
if "pass" in gtpmove:
|
||||
return (None, None)
|
||||
return (GoEngine.GTP_COORD.index(gtpmove[0]), int(gtpmove[1:]) - 1)
|
||||
|
||||
def ix2gtp(self, coords):
|
||||
if not coords:
|
||||
return "pass"
|
||||
return GoEngine.GTP_COORD[coords[0]] + str(coords[1] + 1)
|
||||
|
||||
def coord2sgf(self, pl, x, y):
|
||||
if x is None:
|
||||
return f"{'BW'[pl]}[]"
|
||||
else:
|
||||
return f"{'BW'[pl]}[{GoEngine.SGF_COORD[x]}{GoEngine.SGF_COORD[self.boardsize - y - 1]}]"
|
||||
|
||||
def sgf(self):
|
||||
sgfmoves = [self.coord2sgf(pl, x, y) for pl, x, y in self.moves]
|
||||
return f"(;GM[1]SZ[{self.boardsize}]KM[{self.komi}];" + ";".join(sgfmoves) + ")"
|
||||
|
||||
|
||||
NEXT_BEST_PLAYOUTS = 1000
|
||||
PASS_PLAYOUTS = 250
|
||||
|
||||
|
||||
class KataEngine(GoEngine):
|
||||
# CMD = "kg/cpp/katago gtp -model modelb6/model.txt.gz -config katagtp.cfg"
|
||||
CMD = "../lizzie/katago/katago.exe gtp -model ../lizzie/katanetwork.gz -config katagtp.cfg"
|
||||
|
||||
def __init__(self, boardsize=19):
|
||||
super().__init__(boardsize)
|
||||
self.stones = []
|
||||
self.temperature = 0
|
||||
if getattr(self, "kata", None):
|
||||
self.stop()
|
||||
else:
|
||||
signal.signal(signal.SIGINT, lambda *args: self.stop() and sys.exit(0))
|
||||
self.lock = threading.Lock()
|
||||
threading.Thread(target=self.create_pipe, daemon=True).start()
|
||||
|
||||
def create_pipe(self):
|
||||
with self.lock: # prevent other commands until started
|
||||
self.kata = subprocess.Popen(shlex.split(KataEngine.CMD), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
self._command(f"boardsize {self.boardsize}")
|
||||
self.calc_temperature()
|
||||
|
||||
def stop(self):
|
||||
if self.kata:
|
||||
print("STOPPING KATA")
|
||||
self.kata.terminate()
|
||||
|
||||
def start(self, boardsize):
|
||||
self.__init__(boardsize)
|
||||
|
||||
def _read(self):
|
||||
lines = []
|
||||
while self.kata:
|
||||
lines.append(self.kata.stdout.readline().decode())
|
||||
if DEBUG:
|
||||
print("READ", lines[-1].rstrip())
|
||||
if lines[-1].strip() == "":
|
||||
break
|
||||
return lines[:-1]
|
||||
|
||||
def _write(self, cmd):
|
||||
if DEBUG:
|
||||
print("WRITE", cmd)
|
||||
self.kata.stdin.write((cmd + "\n").encode("utf-8"))
|
||||
self.kata.stdin.flush()
|
||||
|
||||
def _command(self, cmd):
|
||||
self._write(cmd)
|
||||
return self._read()
|
||||
|
||||
def _eq_command(self, cmd):
|
||||
return [l for l in self._command(cmd) if "=" in l][0][1:].strip()
|
||||
|
||||
def current_player(self):
|
||||
return "BW"[self.turn]
|
||||
|
||||
def generate_move(self):
|
||||
with self.lock: # lock to ensure temp is done / hacky eh
|
||||
coords = self.gtp2ix(self.best_analysis[0]["move"])
|
||||
return self.play(coords)
|
||||
|
||||
def _play(self, coords, player=None):
|
||||
self._command(f"play {player or self.current_player()} {self.ix2gtp(coords)}")
|
||||
|
||||
def play(self, coords, player=None):
|
||||
with self.lock:
|
||||
self._play(coords, player)
|
||||
super().play(coords, player)
|
||||
self.update_position()
|
||||
best_score = float(self.best_analysis[0]["scoreMean"])
|
||||
worst_score = -float(self.pass_analysis[0]["scoreMean"])
|
||||
self.calc_temperature()
|
||||
last_move_score = -float(self.best_analysis[0]["scoreMean"])
|
||||
print("BEST", best_score, "WORST", worst_score, "LAST MOVE", last_move_score)
|
||||
return (last_move_score - worst_score) / (best_score - worst_score)
|
||||
|
||||
def undo(self):
|
||||
with self.lock:
|
||||
super().undo()
|
||||
self._command("undo")
|
||||
self.update_position()
|
||||
|
||||
def showboard(self):
|
||||
with self.lock:
|
||||
output = self._command("showboard")
|
||||
return [re.sub("[^\.ox]", "", l.lower()) for l in output[2:]]
|
||||
|
||||
def update_position(self):
|
||||
print("UPDATING POSITION")
|
||||
board = self.showboard()
|
||||
self.stones = []
|
||||
for y, line in enumerate(board[::-1]):
|
||||
for x, st in enumerate(line):
|
||||
if st != ".":
|
||||
self.stones.append(("xo".index(st), x, y))
|
||||
|
||||
def analyze(self, nvisits=100, interval=10):
|
||||
self._write(f"kata-analyze interval {interval} ownership true")
|
||||
stopped = False
|
||||
move_dicts = []
|
||||
while self.kata:
|
||||
line = self.kata.stdout.readline().decode()
|
||||
if stopped and line.strip() == "":
|
||||
self._read() # stop cause previous line break and then =, another double line break
|
||||
break
|
||||
elif "info" not in line:
|
||||
continue
|
||||
line, ownership = line.split("ownership")
|
||||
moves = [re.sub("pv .*", "", str).split(" ") for str in line.split("info ")[1:]]
|
||||
move_dicts = [{move[i]: move[i + 1] for i in range(0, len(move) - 1, 2)} for move in moves]
|
||||
tot_visits = sum([int(d["visits"]) for d in move_dicts], 0)
|
||||
if not stopped and tot_visits > nvisits:
|
||||
stopped = True
|
||||
self._write("stop")
|
||||
print("analyzed", move_dicts)
|
||||
return move_dicts # {d['move']: d for d in move_dict} #/by order?
|
||||
|
||||
def calc_temperature(self):
|
||||
with self.lock:
|
||||
self.best_analysis = self.analyze(NEXT_BEST_PLAYOUTS)
|
||||
print("playing pass")
|
||||
self._play((0, 0)) # pass does some weird things with pass being optimal
|
||||
print("analyzing post pass")
|
||||
self.pass_analysis = self.analyze(PASS_PLAYOUTS)
|
||||
self._command("undo")
|
||||
# score after best move - score after pass = temp, but score after pass is negated here bc opponent's perspective
|
||||
self.temperature = float(self.best_analysis[0]["scoreMean"]) + float(self.pass_analysis[0]["scoreMean"])
|
||||
return self.temperature
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# https://github.com/lightvector/KataGo/issues/25
|
||||
k = KataEngine()
|
||||
|
||||
# print(k.genmove("b"))
|
||||
# print(k.showboard())
|
||||
# print(k.genmove("w"))
|
||||
# print(k.showboard())
|
||||
# print(k.genmove("w"))
|
||||
# print(k.showboard())
|
||||
print(k.play((3, 3)))
|
||||
print("TEMPERATURE:", k.temperature())
|
||||
print(k.play((15, 3)))
|
||||
print("TEMPERATURE:", k.temperature())
|
||||
print(k.showboard())
|
||||
|
||||
print(k.analyze(1000))
|
||||
print(k.play((0, 0)))
|
||||
print("TEMPERATURE:", k.temperature())
|
||||
print(k.showboard())
|
||||
|
||||
# k.stop()
|
||||
|
||||
# k.play('b','pass')
|
||||
# md = k.analyze()
|
||||
Reference in new issue
Block a user