Skip to content

Commit

Permalink
Add sf16.1 WDL model
Browse files Browse the repository at this point in the history
  • Loading branch information
niklasf committed Feb 24, 2024
1 parent cd7f595 commit 8e91525
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
17 changes: 15 additions & 2 deletions chess/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from types import TracebackType
from typing import Any, Callable, Coroutine, Deque, Dict, Generator, Generic, Iterable, Iterator, List, Literal, Mapping, MutableMapping, Optional, Tuple, Type, TypedDict, TypeVar, Union

WdlModel = Literal["sf", "sf16", "sf15.1", "sf15", "sf14", "sf12", "lichess"]
WdlModel = Literal["sf", "sf16.1", "sf16", "sf15.1", "sf15", "sf14", "sf12", "lichess"]


T = TypeVar("T")
Expand Down Expand Up @@ -516,6 +516,16 @@ def __ge__(self, other: object) -> bool:
else:
return NotImplemented

def _sf16_1_wins(cp: int, *, ply=int) -> int:
# https://github.com/official-stockfish/Stockfish/blob/sf_16.1/src/uci.cpp#L48
NormalizeToPawnValue = 356
# https://github.com/official-stockfish/Stockfish/blob/sf_16.1/src/uci.cpp#L383-L384
m = min(120, max(8, ply / 2 + 1)) / 32
a = (((-1.06249702 * m + 7.42016937) * m + 0.89425629) * m) + 348.60356174
b = (((-5.33122190 * m + 39.57831533) * m + -90.84473771) * m) + 123.40620748
x = min(4000, max(cp * NormalizeToPawnValue / 100, -4000))
return int(0.5 + 1000 / (1 + math.exp((a - x) / b)))

def _sf16_wins(cp: int, *, ply: int) -> int:
# https://github.com/official-stockfish/Stockfish/blob/sf_16/src/uci.h#L38
NormalizeToPawnValue = 328
Expand Down Expand Up @@ -594,9 +604,12 @@ def wdl(self, *, model: WdlModel = "sf", ply: int = 30) -> Wdl:
elif model == "sf15.1":
wins = _sf15_1_wins(self.cp, ply=ply)
losses = _sf15_1_wins(-self.cp, ply=ply)
else:
elif model == "sf16":
wins = _sf16_wins(self.cp, ply=ply)
losses = _sf16_wins(-self.cp, ply=ply)
else:
wins = _sf16_1_wins(self.cp, ply=ply)
losses = _sf16_1_wins(-self.cp, ply=ply)
draws = 1000 - wins - losses
return Wdl(wins, draws, losses)

Expand Down
3 changes: 2 additions & 1 deletion test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2995,7 +2995,7 @@ def test_score_ordering(self):
self.assertEqual(i >= j, a >= b)
self.assertEqual(i < j, a.score(mate_score=100000) < b.score(mate_score=100000))

for model in ["sf12", "sf14", "sf15", "sf15.1", "sf16"]:
for model in ["sf12", "sf14", "sf15", "sf15.1", "sf16", "sf16.1"]:
self.assertTrue(not (i < j) or a.wdl(model=model).expectation() <= b.wdl(model=model).expectation())
self.assertTrue(not (i < j) or a.wdl(model=model).winning_chance() <= b.wdl(model=model).winning_chance())
self.assertTrue(not (i < j) or a.wdl(model=model).losing_chance() >= b.wdl(model=model).losing_chance())
Expand Down Expand Up @@ -3035,6 +3035,7 @@ def test_wdl_model(self):
self.assertEqual(chess.engine.Cp(40).wdl(model="sf15", ply=25), chess.engine.Wdl(58, 937, 5))
self.assertEqual(chess.engine.Cp(100).wdl(model="sf15.1", ply=64), chess.engine.Wdl(497, 503, 0))
self.assertEqual(chess.engine.Cp(-52).wdl(model="sf16", ply=63), chess.engine.Wdl(0, 932, 68))
self.assertEqual(chess.engine.Cp(51).wdl(model="sf16.1", ply=158), chess.engine.Wdl(36, 964, 0))

@catchAndSkip(FileNotFoundError, "need stockfish")
def test_sf_forced_mates(self):
Expand Down

0 comments on commit 8e91525

Please sign in to comment.