Skip to content

Commit

Permalink
Fix evals, use chess lib enum, stockfishv13
Browse files Browse the repository at this point in the history
  • Loading branch information
nickzuber committed May 24, 2021
1 parent 7d54904 commit 0a5c6d5
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 26 deletions.
9 changes: 5 additions & 4 deletions chs/__main__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#!/usr/bin/env python

import chess
import sys
import os
from chs.utils.core import Colors, Levels, Player
from chs.utils.core import Colors, Levels
from chs.client.runner import Client


Expand Down Expand Up @@ -42,8 +43,8 @@ def get_level_from_args(args):
def get_player_from_args(args):
player = [arg for arg in args if "--play-black" in arg]
if player:
return Player.BLACK
return Player.WHITE
return chess.BLACK
return chess.WHITE

def main():
if len(sys.argv) > 1 and is_help_command(sys.argv[1]):
Expand Down Expand Up @@ -73,7 +74,7 @@ def main():
play_as = get_player_from_args(sys.argv)
except:
level = Levels.ONE
play_as = Player.WHITE
play_as = chess.WHITE
client = Client(level, play_as)
client.run()

Expand Down
8 changes: 4 additions & 4 deletions chs/client/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from chs.engine.parser import FenParser
from chs.engine.stockfish import Engine
from chs.ui.board import Board
from chs.utils.core import Colors, Styles, Player
from chs.utils.core import Colors, Styles


class GameOverException(Exception):
Expand Down Expand Up @@ -112,7 +112,7 @@ def make_turn(self, meta=(False, None)):
self.board.help_engine_hint = self.board.uci(hint.move)
else:
s = self.board.parse_san(move)
if self.play_as == Player.WHITE:
if self.play_as == chess.WHITE:
self.board.san_move_stack_white.append(self.board.san(s))
else:
self.board.san_move_stack_black.append(self.board.san(s))
Expand All @@ -133,7 +133,7 @@ def computer_turn(self):
Styles.PADDING_SMALL, Styles.PADDING_SMALL, Colors.RESET, Colors.GRAY, Colors.RESET)
)
result = self.engine.play(self.board)
if self.play_as == Player.WHITE:
if self.play_as == chess.WHITE:
self.board.san_move_stack_black.append(self.board.san(result.move))
else:
self.board.san_move_stack_white.append(self.board.san(result.move))
Expand All @@ -144,7 +144,7 @@ def fen(self):

def is_user_move(self):
to_move = self.parser.get_to_move(self.fen())
if self.play_as == Player.WHITE:
if self.play_as == chess.WHITE:
return to_move == 'w'
else:
return to_move == 'b'
11 changes: 6 additions & 5 deletions chs/engine/stockfish.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
engine_path = 'stockfish_10_x64_windows.exe'
elif 'Linux' in platform.system():
engine_path = 'stockfish_10_x64_linux'
else:
engine_path = 'stockfish_10_x64_mac'
else:
engine_path = 'stockfish_13_x64_mac'

class Engine(object):
def __init__(self, level):
Expand All @@ -22,19 +22,20 @@ def __init__(self, level):
def play(self, board, time=1.500):
return self.engine.play(board, chess.engine.Limit(time=time))

def score(self, board):
def score(self, board, pov=chess.WHITE):
try:
info = self.engine.analyse(board, chess.engine.Limit(time=0.500))
cp = chess.engine.PovScore(info['score'], chess.WHITE).pov(chess.WHITE).relative.score()
cp = chess.engine.PovScore(info['score'], pov).pov(pov).relative.score()
return cp
except chess.engine.EngineTerminatedError:
return None

def normalize(self, cp):
if cp is None:
return None
# https://github.com/ornicar/lila/blob/80646821b238d044aed5baf9efb7201cd4793b8b/ui/ceval/src/winningChances.ts#L10
raw_score = 2 / (1 + math.exp(-0.004 * cp)) - 1
return round(raw_score, 1)
return round(raw_score, 3)

def done(self):
try:
Expand Down
Binary file added chs/engine/stockfish_13_x64_mac
Binary file not shown.
47 changes: 38 additions & 9 deletions chs/ui/board.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import os

from chs.client.ending import GameOver
from chs.utils.core import Colors, Styles, Player
from chs.utils.core import Colors, Styles


def disjoin(a, b):
Expand All @@ -24,6 +24,9 @@ def safe_pop(l):
except IndexError:
return None

def round_to_nearest(x, base=25):
return base * round(x / base)

class Board(object):
def __init__(self, level, play_as):
self._play_as = play_as
Expand Down Expand Up @@ -137,9 +140,15 @@ def get_meta_section(self, board, fen, rank, game_over):
# Calculate advantage pieces
(captured_white, captured_black) = self._get_captured_pieces(positions)
(white_advantage, black_advantage) = self._diff_pieces(captured_white, captured_black)
advantage_text = ''.join(map(self.get_piece, list(white_advantage)))
advantage_text = ''.join(map(
self.get_piece,
list(self.white_or_black(white_advantage, black_advantage))
))
# Calculate advantage score
diff_score = self._score_pieces(white_advantage) - self._score_pieces(black_advantage)
diff_score = self.white_or_black(
self._score_pieces(white_advantage) - self._score_pieces(black_advantage),
self._score_pieces(black_advantage) - self._score_pieces(white_advantage)
)
score_text = '+{}'.format(diff_score) if diff_score > 0 else ''
return '{}{}{}{}'.format(padding, Colors.DULL_GRAY, advantage_text, score_text)
if rank == 1:
Expand All @@ -149,7 +158,10 @@ def get_meta_section(self, board, fen, rank, game_over):
text = '{}{}'.format(Colors.ORANGE, self.string_of_game_over(game_over))
return '{}{}'.format(padding, text)
else:
return '{}{}{} cp:{}'.format(padding, Colors.DULL_GRAY, str(self._score).ljust(11), self._cp)
normalized_score = round(self._score * 100, 1)
prefix = '+' if normalized_score >= 0 else ''
winning_potential = '{}{}'.format(prefix, normalized_score)
return '{}{}{} cp:{}'.format(padding, Colors.DULL_GRAY, winning_potential.ljust(11), self._cp)
if rank == 3:
return '{}{}┗━━━━━━━━━━━━━━━━━━━┛'.format(padding_alt, Colors.DULL_GRAY)
if rank == 4:
Expand Down Expand Up @@ -181,9 +193,15 @@ def get_meta_section(self, board, fen, rank, game_over):
# Calculate advantage pieces
(captured_white, captured_black) = self._get_captured_pieces(positions)
(white_advantage, black_advantage) = self._diff_pieces(captured_white, captured_black)
advantage_text = ''.join(map(self.get_piece, list(black_advantage)))
advantage_text = ''.join(map(
self.get_piece,
list(self.white_or_black(black_advantage, white_advantage))
))
# Calculate advantage score
diff_score = self._score_pieces(black_advantage) - self._score_pieces(white_advantage)
diff_score = self.white_or_black(
self._score_pieces(black_advantage) - self._score_pieces(white_advantage),
self._score_pieces(white_advantage) - self._score_pieces(black_advantage)
)
score_text = '+{}'.format(diff_score) if diff_score > 0 else ''
return '{}{}{}{}'.format(padding, Colors.DULL_GRAY, advantage_text, score_text)
if rank == 8:
Expand All @@ -199,11 +217,22 @@ def get_bar_section(self, rank):
percentage = ''
tick = ' '
color = Colors.DULL_GRAY
normalized_score = self._score + 100
normalized_score = self.white_or_black(
round_to_nearest((self._score * 100) + 100),
200 - (round_to_nearest((self._score * 100) + 100))
)
block_range = rank * 25

# Color the bar blocks
if normalized_score >= block_range:
color = Colors.GREEN if self._score >= 0 else Colors.RED
if normalized_score == 100:
color = Colors.GREEN if self._score >= 0 else Colors.RED
else:
pos_color = self.white_or_black(Colors.GREEN, Colors.RED)
neg_color = self.white_or_black(Colors.RED, Colors.GREEN)
color = pos_color if self._score >= 0 else neg_color

# Include the tick if we're in the center.
if block_range == 125:
tick = '{}_{}'.format(Colors.DULL_GRAY, color)
return '{}{}█ {}{}'.format(color, tick, percentage, Colors.RESET)
Expand Down Expand Up @@ -354,7 +383,7 @@ def string_of_game_over(self, game_over):
return 'Game over'

def is_user_white(self):
return self._play_as == Player.WHITE
return self._play_as == chess.WHITE

def white_or_black(self, a, b):
return a if self.is_user_white() else b
Expand Down
4 changes: 0 additions & 4 deletions chs/utils/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ class Styles:
PADDING_MEDIUM = ' '
PADDING_LARGE = ' '

class Player(Enum):
BLACK = 1
WHITE = 2

class Levels:
ONE = 1
TWO = 2
Expand Down

0 comments on commit 0a5c6d5

Please sign in to comment.