score from black side
This commit is contained in:
1 parent
e60f709543
commit
ff1db55a97
5 files changed
+61
-76
No files matched your search
@@ -11,7 +11,7 @@ logFile = gtp.log
|
||||
# analysisPVLen = 15
|
||||
|
||||
# Report winrates for analysis as (BLACK|WHITE|SIDETOMOVE).
|
||||
reportAnalysisWinratesAs = SIDETOMOVE
|
||||
reportAnalysisWinratesAs = BLACK
|
||||
|
||||
# Bot behavior---------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ class Move:
|
||||
self.analysis = None
|
||||
self.pass_analysis = None
|
||||
self.ownership = None
|
||||
self.move_number = 0
|
||||
|
||||
def __repr__(self):
|
||||
return f"{Move.PLAYERS[self.player]}{self.gtp()}"
|
||||
@@ -32,6 +33,7 @@ class Move:
|
||||
return self.children[self.children.index(move)]
|
||||
except ValueError:
|
||||
move.parent = self
|
||||
move.move_number = self.move_number + 1
|
||||
self.children.append(move)
|
||||
return move
|
||||
|
||||
@@ -55,59 +57,74 @@ class Move:
|
||||
def analysis_ready(self):
|
||||
return self.analysis and self.pass_analysis
|
||||
|
||||
def format_score(self,score=None):
|
||||
score = score or self.score
|
||||
return f"{'B' if score >= 0 else 'W'}+{abs(score):.1f}"
|
||||
|
||||
@property
|
||||
def comment(self):
|
||||
text = "(AI Move)\n" if self.robot else ""
|
||||
def comment(self,sgf=False):
|
||||
if not self.parent: # root
|
||||
return ""
|
||||
text = f"Move {self.move_number}: {self.bw_player()} @ {self.gtp()} {'(AI Move)' if self.robot else ''}\n"
|
||||
if self.analysis_ready:
|
||||
score, _, temperature = self.temperature_stats
|
||||
text += f"Current score: {self.bw_player()}{score:+.1f}\n"
|
||||
text += f"Current temperature: {temperature:+.1f}\n"
|
||||
if sgf:
|
||||
text += f"Score: {self.format_score(score)}\n"
|
||||
text += f"Temperature: {temperature:.1f}\n"
|
||||
if self.parent and self.parent.analysis_ready:
|
||||
prev_best_score, prev_worst_score, prev_temperature = self.parent.temperature_stats
|
||||
text += f"Score of top move was {prev_best_score:.1f} @ {self.parent.analysis[0]['move']}\n"
|
||||
text += f"Pass score was {prev_worst_score:.1f}\n"
|
||||
text += f"Top move was {self.format_score(prev_best_score)} @ {self.parent.analysis[0]['move']}\n"
|
||||
text += f"Pass score was {self.format_score(prev_worst_score)}\n"
|
||||
if prev_temperature < 0.5:
|
||||
text += f"Previous temperature ({prev_temperature}) too low for evaluation\n"
|
||||
else:
|
||||
if eval:
|
||||
text += f"Evaluation: {100*self.evaluation:.1f}%\n"
|
||||
text += f"Estimate point loss: {prev_best_score - score:.1f}\n"
|
||||
if self.outdated_evaluation:
|
||||
text += f"(Was considered last move as: {100 * self.outdated_evaluation:.1f}%)\n"
|
||||
outdated_evaluation = self.outdated_evaluation
|
||||
if outdated_evaluation and outdated_evaluation > self.evaluation and outdated_evaluation > self.evaluation + 0.01:
|
||||
text += f"(Was considered last move as: {100 * outdated_evaluation :.1f}%)\n"
|
||||
points_lost = self.player_sign * (prev_best_score - score)
|
||||
if points_lost > 0.5:
|
||||
text += f"Estimate point loss: {points_lost:.1f}\n"
|
||||
else:
|
||||
text += "(No analysis available yet)"
|
||||
text = "No analysis available" if sgf else "Analyzing move..."
|
||||
return text
|
||||
|
||||
# returns evaluation, temperature scale or None, None when not ready
|
||||
@property
|
||||
def evaluation_info(self):
|
||||
if self.parent and self.parent.analysis_ready and self.analysis_ready:
|
||||
return (self.evaluation,self.parent.temperature_stats[2])
|
||||
return self.evaluation,self.parent.temperature_stats[2]
|
||||
else:
|
||||
return (None,None)
|
||||
return None,None
|
||||
|
||||
# needing own analysis ready
|
||||
@property
|
||||
def temperature_stats(self):
|
||||
best = -float(self.analysis[0]["scoreLead"])
|
||||
best = float(self.analysis[0]["scoreLead"])
|
||||
worst= float(self.pass_analysis[0]["scoreLead"])
|
||||
return best, worst, best - worst
|
||||
return best, worst, abs(best - worst)
|
||||
|
||||
@property
|
||||
def score(self):
|
||||
return self.temperature_stats[0]
|
||||
|
||||
@property
|
||||
def player_sign(self):
|
||||
return 1 if self.player == 0 else -1
|
||||
|
||||
# need parent analysis ready
|
||||
@property
|
||||
def evaluation(self):
|
||||
best, worst, temp = self.parent.temperature_stats
|
||||
return (self.score - worst) / temp
|
||||
return self.player_sign * (self.score - worst) / temp
|
||||
|
||||
@property
|
||||
def outdated_evaluation(self):
|
||||
prev_analysis_current_move = [d for d in self.parent.analysis if d["move"] == self.gtp()]
|
||||
if prev_analysis_current_move:
|
||||
best_score, worst_score, prev_temp = self.parent.temperature_stats
|
||||
return (prev_analysis_current_move[0]["scoreLead"] - worst_score) / prev_temp
|
||||
return self.player_sign * (prev_analysis_current_move[0]["scoreLead"] - worst_score) / prev_temp
|
||||
|
||||
@property
|
||||
def ai_moves(self):
|
||||
@@ -115,7 +132,7 @@ class Move:
|
||||
return []
|
||||
_, worst_score, temperature = self.temperature_stats
|
||||
for d in self.analysis:
|
||||
d["evaluation"] = (d["scoreLead"] - worst_score) / temperature
|
||||
d["evaluation"] = -self.player_sign * (d["scoreLead"] - worst_score) / temperature
|
||||
return self.analysis
|
||||
|
||||
### various output and conversion functions
|
||||
|
||||
+1
-2
@@ -37,8 +37,7 @@
|
||||
"undo_eval_threshold": 0.875,
|
||||
"undo_outdated_eval_threshold": 0.8,
|
||||
"undo_point_threshold": 1,
|
||||
"num_undo_prompts": 1,
|
||||
"show_ai_options": true
|
||||
"num_undo_prompts": 1
|
||||
},
|
||||
"debug": {
|
||||
"level": 1
|
||||
|
||||
+24
-55
@@ -91,12 +91,16 @@ class EngineControls(GridLayout):
|
||||
self.redraw()
|
||||
|
||||
def update_evaluation(self):
|
||||
self.info.text = self.board.current_move.comment
|
||||
#self.temperature.text = f"{self.board.current_move.temperature_stats[2]:.1f}"
|
||||
#self.score.text = f"{Move.PLAYERS[self.board.current_player]}{self.board.current_move.score}".replace("-", "\u2013") # en dash
|
||||
#self.evaluation.text = f"{100 * self.board.current_move.evaluation:.1f}%"
|
||||
current_move = self.board.current_move
|
||||
if self.eval.active(current_move.player):
|
||||
self.info.text = current_move.comment
|
||||
self.evaluation.text = ''
|
||||
if current_move.analysis_ready:
|
||||
self.score.text = current_move.format_score().replace("-", "\u2013")
|
||||
self.temperature.text = f"{current_move.temperature_stats[2]:.1f}"
|
||||
if current_move.parent and current_move.parent.analysis_ready:
|
||||
self.evaluation.text = f"{100 * current_move.evaluation:.1f}%"
|
||||
|
||||
#f"Your move {self.board.current_move.gtp()} was {100 * self.board.current_move.evaluation:.1f}% efficient and lost {self.moves[-1].points_lost:.1f} point(s).\n"
|
||||
# when to trigger auto undo?
|
||||
# self.undo.disabled = True # undo while waiting for this does weird things
|
||||
# undid = False
|
||||
@@ -107,7 +111,6 @@ class EngineControls(GridLayout):
|
||||
# self._do_aimove(move, True)
|
||||
# self.undo.disabled = False
|
||||
|
||||
|
||||
def _auto_undo(self, move):
|
||||
ts = self.train_settings
|
||||
self.info.text = "Evaluating..."
|
||||
@@ -149,34 +152,33 @@ class EngineControls(GridLayout):
|
||||
self.info.text += f"\nYour moves:\n{summary}.\nLet's continue with {evaled_moves[0].gtp()}.\n"
|
||||
return False
|
||||
|
||||
def _do_aimove(self, move, auto=False):
|
||||
def _do_aimove(self, auto=False):
|
||||
ts = self.train_settings
|
||||
if not auto:
|
||||
while not self.board.current_move.analysis_ready:
|
||||
self.info.text = "Thinking..."
|
||||
self._evaluate_move(auto and not self.auto_undo.active(1 - self.board.current_player))
|
||||
time.sleep(0.05)
|
||||
|
||||
# select move
|
||||
current_move = self.board.current_move
|
||||
pos_moves = [
|
||||
(d["move"], float(d["scoreMean"]), d["evaluation"])
|
||||
for d in move.analysis
|
||||
for d in current_move.ai_moves
|
||||
if int(d["visits"]) >= ts["balance_play_min_visits"]
|
||||
]
|
||||
if ts["show_ai_options"]:
|
||||
self.info.text += "AI Options: " + " ".join(
|
||||
[f"{move}({100*eval:.0f}%,{score:.1f}pt)" for move, score, eval in pos_moves]
|
||||
)
|
||||
selmove = pos_moves[0][0]
|
||||
if (
|
||||
self.ai_balance.active and pos_moves[0][0] != "pass"
|
||||
): # don't play suicidal to balance score - pass when it's best
|
||||
# don't play suicidal to balance score - pass when it's best
|
||||
if self.ai_balance.active and pos_moves[0][0] != "pass":
|
||||
selmoves = [
|
||||
move
|
||||
for move, score, eval in pos_moves
|
||||
if eval > ts["balance_play_randomize_eval"]
|
||||
or eval > ts["balance_play_min_eval"]
|
||||
and score > ts["balance_play_target_score"]
|
||||
and current_move.player_sign * score > ts["balance_play_target_score"]
|
||||
]
|
||||
selmove = random.choice(selmoves) # some kind of when further ahead play worse?
|
||||
self.board.play(Move(player=self.board.current_player, gtpcoords=selmove, robot=True))
|
||||
selmove = random.choice(selmoves) # TODO: some kind of when further ahead play worse?
|
||||
print('SEL',selmoves)
|
||||
print('POS',pos_moves, 'MOVE', selmove)
|
||||
self.play(Move(player=self.board.current_player, gtpcoords=selmove, robot=True))
|
||||
|
||||
def _do_undo(self):
|
||||
if self.ai_auto.active and self.board.current_move.robot:
|
||||
@@ -213,7 +215,7 @@ class EngineControls(GridLayout):
|
||||
while self.outstanding_analysis_queries:
|
||||
self._send_analysis_query(self.outstanding_analysis_queries.pop(0))
|
||||
line = self.kata.stdout.readline()
|
||||
print("KATA ANALYSIS RECEIVED:", line)
|
||||
print("KATA ANALYSIS RECEIVED:", line[:50])
|
||||
self.board.store_analysis(json.loads(line))
|
||||
self.update_evaluation()
|
||||
self.redraw(include_board=False)
|
||||
@@ -250,43 +252,10 @@ class EngineControls(GridLayout):
|
||||
print("pass-query", query)
|
||||
self._send_analysis_query(query)
|
||||
|
||||
# def update_analysis(self, analysis, mode, ownership):
|
||||
# for d in analysis:
|
||||
# d["scoreMean"] = float(d["scoreMean"])
|
||||
#
|
||||
# if mode == 0:
|
||||
# pm = [d for d in analysis if d["move"] == "pass"]
|
||||
# npm = [d for d in analysis if d["move"] != "pass"]
|
||||
# if pm:
|
||||
# pv = sum([int(d["visits"]) for d in pm], 0)
|
||||
# npv = sum([int(d["visits"]) for d in npm], 0)
|
||||
# print("pass visits", pv, "other", npv)
|
||||
# if pv > npv:
|
||||
# print(analysis)
|
||||
# self.moves[-1].pass_analysis = [d for d in analysis if d["move"] != "pass"]
|
||||
# else:
|
||||
# if ownership:
|
||||
# self.moves[-1].ownership = [float(p) for p in ownership[0].strip().split(" ")]
|
||||
# best = analysis[0]["scoreMean"]
|
||||
# worst = -self.moves[-1].pass_analysis[0]["scoreMean"]
|
||||
# for d in analysis:
|
||||
# d["evaluation"] = (d["scoreMean"] - worst) / (best - worst)
|
||||
# self.moves[-1].analysis = analysis
|
||||
# if self.eval.active(1 - self.board.current_player):
|
||||
# self.temperature.text = f"{self.moves[-1].temperature():.1f}"
|
||||
# self.score.text = f"{Move.PLAYERS[self.board.current_player]}{float(analysis[0]['scoreMean']):+.1f}".replace("-", "\u2013") # en dash
|
||||
# if len(self.moves) >= 2 and self.moves[-2].analysis:
|
||||
# self.moves[-1].evaluate(self.moves[-2])
|
||||
# if self.eval.active(1 - self.board.current_player):
|
||||
# if self.moves[-1].evaluation:
|
||||
# self.evaluation.text = f"{100 * self.moves[-1].evaluation:.1f}%"
|
||||
# else:
|
||||
# self.evaluation.text = "N/A"
|
||||
# self.redraw(include_board=False) # for dots and stuff
|
||||
|
||||
def sgf(self):
|
||||
def sgfify(mvs):
|
||||
return f"(;GM[1]FF[4]SZ[{self.board_size}]KM[{self.komi}]RU[CN];" + ";".join(mvs) + ")"
|
||||
return f"(;GM[1]FF[4]SZ[{self.board_size}]KM[{self.komi}]RU[JP];" + ";".join(mvs) + ")"
|
||||
|
||||
def format_move(m, pm):
|
||||
undo_comment = "".join(f"\nUndo: {u.gtp()} was {100*u.evaluation:.1f}%" for u in pm.undos if u.evaluation)
|
||||
|
||||
+1
-1
@@ -196,7 +196,7 @@
|
||||
size_hint: 0.166, 0.5
|
||||
text: 'balance\nscore'
|
||||
id: ai_balance
|
||||
default_active: True
|
||||
default_active: False
|
||||
CheckBoxHint:
|
||||
size_hint: 0.166, 0.5
|
||||
text: 'fast'
|
||||
|
||||
Reference in new issue
Block a user