weighted rank estimation added
This commit is contained in:
1 parent
689d505d5c
commit
32074d6616
5 files changed
+56
-7
No files matched your search
+15
-3
@@ -23,19 +23,31 @@ from katrain.core.constants import (
|
||||
OUTPUT_DEBUG,
|
||||
OUTPUT_ERROR,
|
||||
OUTPUT_INFO,
|
||||
AI_WEIGHTED_ELO,
|
||||
CALIBRATED_RANK_ELO,
|
||||
)
|
||||
from katrain.core.game import Game, GameNode, Move
|
||||
from katrain.core.utils import var_to_grid
|
||||
|
||||
|
||||
def interp1d(x, lookup):
|
||||
i = 0
|
||||
while i + 1 < len(lookup) - 1 and lookup[i + 1][0] < x:
|
||||
i += 1
|
||||
t = max(0, min(1, (x - lookup[i][0]) / (lookup[i + 1][0] - lookup[i][0])))
|
||||
return (1 - t) * lookup[i][1] + t * lookup[i + 1][1]
|
||||
|
||||
|
||||
def ai_rank_estimation(strategy, settings) -> Tuple[int, bool]:
|
||||
if strategy in [AI_DEFAULT, AI_HANDICAP, AI_JIGO]:
|
||||
return 9, True
|
||||
if strategy == AI_RANK:
|
||||
return 1 - settings["kyu_rank"], True
|
||||
if strategy == AI_WEIGHTED:
|
||||
dan_rank = -4
|
||||
return dan_rank, True
|
||||
if strategy in [AI_WEIGHTED]:
|
||||
if strategy == AI_WEIGHTED:
|
||||
elo = interp1d(settings["weaken_fac"], AI_WEIGHTED_ELO)
|
||||
kyu = interp1d(elo, CALIBRATED_RANK_ELO)
|
||||
return 1 - kyu, True
|
||||
else:
|
||||
return AI_STRENGTH[strategy], False
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ AI_STRATEGIES_RECOMMENDED_ORDER = [
|
||||
|
||||
AI_STRENGTH = { # dan ranks
|
||||
AI_DEFAULT: 9,
|
||||
AI_POLICY: 4,
|
||||
AI_POLICY: 5,
|
||||
AI_JIGO: float("nan"),
|
||||
AI_SCORELOSS: -4,
|
||||
AI_WEIGHTED: -4,
|
||||
@@ -76,7 +76,7 @@ AI_OPTION_VALUES = {
|
||||
"opening_moves": range(0, 51),
|
||||
"pick_override": [0, 0.5, 0.6, 0.7, 0.8, 0.85, 0.9, 0.95, 0.99, 1],
|
||||
"lower_bound": [(v, f"{v:.2%}") for v in [0, 0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05]],
|
||||
"weaken_fac": [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 4],
|
||||
"weaken_fac": [x/20 for x in range(10,3*20+1)],
|
||||
"endgame": [x / 100 for x in range(10, 80, 5)],
|
||||
"pick_frac": [x / 100 for x in range(0, 101, 5)],
|
||||
"pick_n": range(0, 26),
|
||||
@@ -87,3 +87,36 @@ AI_OPTION_VALUES = {
|
||||
"pda": [(x / 10, f"{'W' if x<0 else 'B'}+{abs(x/10):.1f}") for x in range(-30, 31)],
|
||||
}
|
||||
AI_KEY_PROPERTIES = {"kyu_rank", "strength", "weaken_fac", "pick_frac", "pick_n", "automatic"}
|
||||
|
||||
CALIBRATED_RANK_ELO =[(39.36921298625589, 18),
|
||||
(96.95581072853861, 17),
|
||||
(154.54240847082144, 16),
|
||||
(212.12900621310428, 15),
|
||||
(269.7156039553871, 14),
|
||||
(327.30220169766983, 13),
|
||||
(384.88879943995266, 12),
|
||||
(442.4753971822355, 11),
|
||||
(500.06199492451833, 10),
|
||||
(557.6485926668012, 9),
|
||||
(615.235190409084, 8),
|
||||
(672.8217881513667, 7),
|
||||
(730.4083858936496, 6),
|
||||
(787.9949836359324, 5),
|
||||
(845.5815813782152, 4),
|
||||
(903.168179120498, 3),
|
||||
(960.7547768627808, 2),
|
||||
(1018.3413746050636, 1),
|
||||
(1075.9279723473464, 0),
|
||||
(1133.5145700896292, -1),
|
||||
(1191.101167831912, -2),
|
||||
(1700,-4)]
|
||||
AI_WEIGHTED_ELO = [
|
||||
(0.5, 1591.4486833932992),
|
||||
(1.0, 1266.2591850212696),
|
||||
(1.25, 1121.5661132041557),
|
||||
(1.5, 960.0966363156612),
|
||||
(1.75, 800.3124873968906),
|
||||
(2, 670.1137021076612),
|
||||
(2.5, 516.8371296455036),
|
||||
(3.0, 359.9621037249864),
|
||||
]
|
||||
@@ -82,6 +82,7 @@ i18n = Lang(DEFAULT_LANGUAGE)
|
||||
def rank_label(rank):
|
||||
if rank is None:
|
||||
return "??k"
|
||||
|
||||
if rank > 0:
|
||||
return f"{rank:.0f}{i18n._('strength:dan')}"
|
||||
else:
|
||||
|
||||
@@ -6,7 +6,7 @@ from kivymd.uix.selectioncontrol import Thumb
|
||||
|
||||
|
||||
class SelectionSlider(Widget):
|
||||
__events__ = ["on_select"]
|
||||
__events__ = ["on_select","on_change"]
|
||||
active = BooleanProperty(False)
|
||||
hint = BooleanProperty(True)
|
||||
|
||||
@@ -44,6 +44,7 @@ class SelectionSlider(Widget):
|
||||
def set_from_pos(self, pos):
|
||||
norm_value = (pos[0] - self.x - self.padding) / (self.width - 2 * self.padding)
|
||||
self.index = round(norm_value * (len(self.values) - 1))
|
||||
self.dispatch("on_change", self.value)
|
||||
|
||||
def on_touch_down(self, touch):
|
||||
if self.disabled or not self.collide_point(*touch.pos):
|
||||
@@ -74,6 +75,8 @@ class SelectionSlider(Widget):
|
||||
def on_select(self, value):
|
||||
pass
|
||||
|
||||
def on_change(self, value):
|
||||
pass
|
||||
|
||||
KV = """
|
||||
#:import i18n katrain.core.lang.i18n
|
||||
|
||||
+1
-1
@@ -402,7 +402,7 @@
|
||||
id: slider
|
||||
size_hint: 2,1
|
||||
values: root.values
|
||||
on_select: textbox.text = str(slider.value)
|
||||
on_change: textbox.text = str(slider.value)
|
||||
track_color: LIGHTGREY
|
||||
thumb_color: (0.6, 0.7, 0.9, 1) if root.key_option else (0.3, 0.4, 0.6, 1)
|
||||
LabelledFloatInput:
|
||||
|
||||
Reference in new issue
Block a user