From 847eb10c7dab9c87c94baeb46688f218ff1c8f15 Mon Sep 17 00:00:00 2001 From: Sander Land Date: Thu, 20 Feb 2020 21:26:50 +0100 Subject: [PATCH] fractional undos are probably a terrible idea --- board.py | 3 +++ controller.py | 33 ++++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/board.py b/board.py index 624bc72..9cba08f 100644 --- a/board.py +++ b/board.py @@ -1,4 +1,5 @@ import os +import random from datetime import datetime @@ -26,6 +27,7 @@ class Move: self.x_comment = "" self.auto_undid = False self.move_number = 0 + self.undo_threshold = random.random() # for fractional undos, store the random threshold in the move itself for consistency def __repr__(self): return f"{Move.PLAYERS[self.player]}{self.gtp()}" @@ -82,6 +84,7 @@ class Move: text += f"Move {self.move_number}: {self.bw_player()} {self.gtp()} {'(AI Move)' if self.robot else ''}\n" text += self.x_comment + print("xc = ", self.x_comment) if self.analysis_ready: score, _, temperature = self.temperature_stats diff --git a/controller.py b/controller.py index c3129d4..0ffeafe 100644 --- a/controller.py +++ b/controller.py @@ -1,6 +1,7 @@ import copy import json import os +import math import random import re import shlex @@ -109,7 +110,7 @@ class EngineControls(GridLayout): if self.eval.active(current_move.player): self.show_evaluation_stats(current_move) - if current_move.analysis_ready and current_move.parent and current_move.parent.analysis_ready and not current_move.children: + if current_move.analysis_ready and current_move.parent and current_move.parent.analysis_ready and not current_move.children and not current_move.x_comment: # handle automatic undo if self.auto_undo.active(current_move.player) and not self.ai_auto.active(current_move.player) and not current_move.auto_undid: ts = self.train_settings @@ -117,14 +118,18 @@ class EngineControls(GridLayout): eval = max(current_move.evaluation, current_move.outdated_evaluation or 0) points_lost = (current_move.parent or current_move).temperature_stats[2] * (1 - eval) if eval < ts["undo_eval_threshold"] and points_lost >= ts["undo_point_threshold"]: - current_move.auto_undid = True - self.board.undo() - if len(current_move.parent.children) >= ts["num_undo_prompts"] + 1: - best_move = sorted([m for m in current_move.parent.children], key=lambda m: -(m.evaluation_info[0] or 0))[0] - best_move.x_comment = f"Automatically played as best option after max. {ts['num_undo_prompts']} undo(s).\n" - self.board.play(best_move) - self.update_evaluation() - return + if self.num_undos(current_move) == 0: + current_move.x_comment = f"Move was below threshold, but no undo granted (probability is {ts['num_undo_prompts']:.0%}).\n" + self.update_evaluation() + else: + current_move.auto_undid = True + self.board.undo() + if len(current_move.parent.children) >= ts["num_undo_prompts"] + 1: + best_move = sorted([m for m in current_move.parent.children], key=lambda m: -(m.evaluation_info[0] or 0))[0] + best_move.x_comment = f"Automatically played as best option after max. {ts['num_undo_prompts']} undo(s).\n" + self.board.play(best_move) + self.update_evaluation() + return # ai player doesn't technically need parent ready, but don't want to override waiting for undo current_move = self.board.current_move # this effectively checks undo didn't just happen if self.ai_auto.active(1 - current_move.player) and not self.board.game_ended: @@ -162,14 +167,20 @@ class EngineControls(GridLayout): aimove.x_comment = "AI Balance on, moves considered: " + ", ".join(f"{move} ({aimove.format_score(score)})" for move, score, _ in sel_moves) + "\n" self.play(aimove) + def num_undos(self, move): + if self.train_settings["num_undo_prompts"] < 1: + return int(move.undo_threshold < self.train_settings["num_undo_prompts"]) + else: + return self.train_settings["num_undo_prompts"] + def _do_undo(self): if ( self.ai_lock.active and self.auto_undo.active(self.board.current_move.player) - and len(self.board.current_move.parent.children) > self.train_settings["num_undo_prompts"] + and len(self.board.current_move.parent.children) > self.num_undos(self.board.current_move) and not self.train_settings.get("dont_lock_undos") ): - self.info.text = f"Can't undo more than {self.train_settings['num_undo_prompts']} time(s) when locked" + self.info.text = f"Can't undo this move more than {self.num_undos(self.board.current_move)} time(s) when locked" return self.board.undo() self.update_evaluation()