score from black side

This commit is contained in:
Sander Land committed 2020-01-24 23:16:58 +01:00
1 parent e60f709543
commit ff1db55a97
5 files changed
+61 -76

No files matched your search

+1 -1
View File
@@ -11,7 +11,7 @@ logFile = gtp.log
# analysisPVLen = 15
# Report winrates for analysis as (BLACK|WHITE|SIDETOMOVE).
reportAnalysisWinratesAs = SIDETOMOVE
reportAnalysisWinratesAs = BLACK
# Bot behavior---------------------------------------------------------------------------------------
+34 -17
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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'