Skip to content

Commit

Permalink
new psts
Browse files Browse the repository at this point in the history
  • Loading branch information
Avo-k committed Jul 7, 2021
1 parent 65e1b7c commit d8dd01a
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 126 deletions.
1 change: 1 addition & 0 deletions bb_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"""


@njit(nb.b1(nb.uint64, nb.uint8), cache=True)
def get_bit(bb, sq):
return bb & (1 << sq)
Expand Down
94 changes: 17 additions & 77 deletions constants.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import numpy as np
import numba as nb
from numba import njit
from bb_operations import print_bb

EMPTY = np.uint64(0)
BIT = np.uint64(1)
Expand All @@ -10,7 +9,6 @@
white, black, both = np.arange(3, dtype=np.uint8)

pawn, knight, bishop, rook, queen, king = range(6)
# piece_names = ("pawn", "knight", "bishop", "rook", "queen", "king")

a8, b8, c8, d8, e8, f8, g8, h8, \
a7, b7, c7, d7, e7, f7, g7, h7, \
Expand All @@ -19,9 +17,16 @@
a4, b4, c4, d4, e4, f4, g4, h4, \
a3, b3, c3, d3, e3, f3, g3, h3, \
a2, b2, c2, d2, e2, f2, g2, h2, \
a1, b1, c1, d1, e1, f1, g1, h1, no_sq = range(65)
a1, b1, c1, d1, e1, f1, g1, h1, no_sq = np.arange(65, dtype=np.uint8)
squares = range(64)

black_squares = np.array(sorted([s for s in range(1, 64, 2) if not (s // 8) % 2] +
[s for s in range(0, 64, 2) if (s // 8) % 2]),
dtype=np.uint8)
white_squares = np.array(sorted([s for s in range(0, 64, 2) if not (s // 8) % 2] +
[s for s in range(1, 64, 2) if (s // 8) % 2]),
dtype=np.uint8)

square_to_coordinates = (
"a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8",
"a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7",
Expand Down Expand Up @@ -116,9 +121,9 @@
# Evaluation Constants

# Material values
# P N B R Q K
material_scores = ((100, 325, 335, 500, 1000, 12000),
(110, 310, 315, 550, 1050, 12000))
# P N B R Q K
material_scores = ((70, 325, 325, 500, 975, 12000),
(90, 315, 315, 500, 975, 12000))

# P N B R Q K
phase_scores = (0, 1, 1, 2, 4, 0)
Expand All @@ -129,77 +134,6 @@

opening, end_game, middle_game = np.arange(3, dtype=np.uint8)

pawn_pst = (
0, 0, 0, 0, 0, 0, 0, 0,
-10, -4, 0, -5, -5, 0, -4, -10,
-10, -4, 0, 8, 5, 0, -4, -10,
-10, -4, 0, 16, 12, 0, -4, -10,
-10, -4, 0, 18, 14, 0, -4, -10,
-10, -4, 0, 17, 13, 0, -4, -10,
-10, -4, 0, 16, 12, 0, -4, -10,
0, 0, 0, 0, 0, 0, 0, 0)

pawn_pst_eg = (
0, 0, 0, 0, 0, 0, 0, 0,
-5, -2, 0, 0, 0, 0, -2, -5,
-5, -2, 0, 3, 3, 0, -2, -5,
-5, -2, 1, 7, 7, 1, -2, -5,
-5, -2, 1, 7, 7, 1, -2, -5,
-5, -2, 1, 7, 7, 1, -2, -5,
-5, -2, 1, 7, 7, 1, -2, -5,
0, 0, 0, 0, 0, 0, 0, -5)

knight_pst = (
-20, 0, -10, -10, -10, -10, -10, -20,
-10, 0, 0, 3, 3, 0, 0, -10,
-10, 0, 5, 5, 5, 5, 0, -10,
-10, 0, 5, 10, 10, 5, 0, -10,
-10, 0, 5, 10, 10, 5, 0, -10,
-10, 0, 5, 5, 5, 5, 0, -10,
-10, 0, 0, 3, 3, 0, 0, -10,
-20, -10, -10, -10, -10, -10, -10, -20)

bishop_pst = (
-2, -2, -2, -2, -2, -2, -2, -2,
-2, 8, 5, 5, 5, 5, 8, -2,
-2, 3, 3, 5, 5, 3, 3, -2,
-2, 2, 5, 4, 4, 5, 2, -2,
-2, 2, 5, 4, 4, 5, 2, -2,
-2, 3, 3, 5, 5, 3, 3, -2,
-2, 8, 5, 5, 5, 5, 8, -2,
-2, -2, -2, -2, -2, -2, -2, -2)

rook_pst = (
0, 0, 0, 0, 0, 0, 0, 0,
5, 10, 10, 10, 10, 10, 10, 5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
0, 0, 0, 5, 5, 0, 0, 0)

king_pst_eg = (-17, -14, -10, -7, -7, -10, -14, -17,
-10, -7, -4, 0, 0, -4, -7, -10,
-10, -4, 6, 10, 10, 6, -4, -10,
-10, -4, 10, 13, 13, 10, -4, -10,
-10, -4, 10, 13, 13, 10, -4, -10,
-10, -4, 6, 10, 10, 6, -4, -10,
-10, -10, 0, 0, 0, 0, -10, -10,
-17, -10, -10, -10, -10, -10, -10, -17)

king_pst = (-10, -14, -14, -17, -17, -14, -14, -10,
-10, -14, -14, -17, -17, -14, -14, -10,
-10, -14, -14, -17, -17, -14, -14, -10,
-10, -14, -14, -17, -17, -14, -14, -10,
-7, -10, -10, -14, -14, -10, -10, -7,
-4, -7, -7, -7, -7, -7, -7, -4,
6, 6, 0, 0, 0, 0, 6, 6,
6, 10, 3, 0, 0, 3, 10, 6)

PST = np.array(((pawn_pst, knight_pst, bishop_pst, rook_pst, np.zeros(64), king_pst),
(pawn_pst_eg, knight_pst, bishop_pst, rook_pst, np.zeros(64), king_pst_eg)), dtype=np.int8)

mirror_pst = (
a1, b1, c1, d1, e1, f1, g1, h1,
a2, b2, c2, d2, e2, f2, g2, h2,
Expand Down Expand Up @@ -267,6 +201,9 @@

king_shield_bonus = 5

bishop_pair_mg = 50
bishop_pair_eg = 70

knight_tropism_mg = 3
bishop_tropism_mg = 2
rook_tropism_mg = 2
Expand All @@ -277,6 +214,9 @@
rook_tropism_eg = 1
queen_tropism_eg = 4

pawns_on_bishop_colour_opening = (9,6,3,0,-3,-6,-9,-12,-15)
pawns_on_bishop_colour_endgame = (12,8,4,0,-4,-8,-12,-16,-20)


@njit
def manhattan_distance(sq1, sq2):
Expand Down
14 changes: 10 additions & 4 deletions evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from bb_operations import *
from position import Position
from attack_tables import get_bishop_attacks, get_queen_attacks, king_attacks, knight_attacks, get_rook_attacks
from pst import PST


@njit(nb.uint16(Position.class_type.instance_type), cache=True)
Expand Down Expand Up @@ -171,17 +172,17 @@ def evaluate(pos) -> int:
eg_score = 0

game_phase_score = get_game_phase_score(pos)

wk_sq = get_ls1b_index(pos.pieces[white][king])
bk_sq = get_ls1b_index(pos.pieces[black][king])
kings_sq = (wk_sq, bk_sq)
kings_sq = (get_ls1b_index(pos.pieces[white][king]), get_ls1b_index(pos.pieces[black][king]))

for color in (black, white):

opp = color ^ 1

# double pawns
double_pawns = count_bits(pos.pieces[color][pawn] & (pos.pieces[color][pawn] << 8))
mg_score += double_pawns * double_pawn_penalty
# bishop counter
bish = 0

for piece in range(6):
bb = pos.pieces[color][piece]
Expand Down Expand Up @@ -218,11 +219,16 @@ def evaluate(pos) -> int:
eg_score += knight_eg(pos, sq, kings_sq, opp, color)

elif piece == bishop:
bish += 1
mg_score += bishop_mg(pos, sq, kings_sq, opp)
eg_score += bishop_eg(pos, sq, kings_sq, opp)

bb = pop_bit(bb, sq)

if bish > 1:
mg_score += bishop_pair_mg
eg_score += bishop_pair_eg

if color:
mg_score, eg_score = -mg_score, -eg_score

Expand Down
94 changes: 55 additions & 39 deletions lichess.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import threading

from position import parse_fen, print_position
from constants import start_position, LOWER_MATE
from constants import start_position
from search import Black_numba, search, random_move
from moves import get_move_uci, make_move
from uci import parse_move
Expand All @@ -17,18 +17,17 @@
client = berserk.Client(session=session)


class Game(threading.Thread):
def __init__(self, client, game_id, **kwargs):
super().__init__(**kwargs)
class Game:
def __init__(self, client, game_id):
self.game_id = game_id
self.client = client
self.stream = client.bots.stream_game_state(game_id)
self.current_state = next(self.stream)
self.bot_is_white = self.current_state['white'].get('id') == bot_id
self.time_str = "wtime" if self.bot_is_white else "btime"
self.pos = parse_fen(start_position)
self.moves = ""
self.bot = Black_numba()
self.pos = parse_fen(start_position)
self.theory = True

def run(self):
Expand All @@ -50,47 +49,67 @@ def run(self):
elif self.bot_is_white != self.pos.side:
self.make_first_move()

# ponder_thread = threading.Thread(target=self.ponder)

# main game loop
for event in self.stream:
if event['type'] == 'gameState':
if event['status'] == 'started':
self.handle_state_change(event)
# self.play_random_fast(event)
if not event['moves'] == self.moves:
new_move = parse_move(self.pos, event['moves'][len(self.moves):].strip())
self.moves = event['moves']
self.pos = make_move(self.pos, new_move)
bot_turn = self.bot_is_white != self.pos.side

if bot_turn:
self.play(event)

# print("my turn")
# if ponder_thread.is_alive():
# assert threading.active_count() == 2
# print("i am killing it")
# self.bot.stopped = True
# s = time.perf_counter_ns()
# ponder_thread.join()
# print(f"killed in {(time.perf_counter_ns() - s) / 10**6:.0f} ms")
# # del ponder_thread
# assert threading.active_count() == 1
# self.play(event)

# else:
# ponder_thread = threading.Thread(target=self.ponder)
# print("opp turn")
# ponder_thread.start()

elif event['status'] in ('mate', 'resign', 'outoftime', 'aborted', 'draw'):
print(event['status'])
break
else:
print('NEW', event['status'])
break

def play_random_fast(self, game_state):
if game_state['moves'] == self.moves:
return
self.moves = game_state['moves']
new_move = parse_move(self.pos, self.moves.split()[-1])
self.pos = make_move(self.pos, new_move)

def play_random_fast(self):
move = random_move(self.pos)
client.bots.make_move(self.game_id, get_move_uci(move))

self.pos = make_move(self.pos, move)
self.moves += " " + get_move_uci(move)
def ponder(self, game_state):
print("i am pondering")

def handle_state_change(self, game_state):
if game_state['moves'] == self.moves:
return
self.moves = game_state['moves']
move_list = self.moves.split()
new_move = parse_move(self.pos, move_list[-1])
self.pos = make_move(self.pos, new_move)

# is it bot turn ?
bot_turn = self.bot_is_white != self.pos.side
if not bot_turn:
return
# set time limit
remaining_time = game_state[self.time_str].timestamp()
time_limit = remaining_time / 40 * 1000

start = time.perf_counter_ns()
depth, move, score = search(self.bot, self.pos, print_info=False, time_limit=time_limit)
time_spent_ms = (time.perf_counter_ns() - start) / 10 ** 6
print(f"pondering time: {time_spent_ms:.0f}")
print(f"pondering depth: {depth} - kns: {self.bot.nodes / time_spent_ms:.0f}")
print("-" * 40)

def play(self, game_state):
# Look in the books
if self.theory:
entry = self.look_in_da_book(move_list)
entry = self.look_in_da_book(self.moves.split())
if entry:
self.client.bots.make_move(game_id, entry.move)
print("still theory")
Expand All @@ -100,23 +119,21 @@ def handle_state_change(self, game_state):

# set time limit
remaining_time = game_state[self.time_str].timestamp()
time_limit = remaining_time / 30 * 1000
time_limit = remaining_time / 40 * 1000

# look for a move
start = time.time()
start = time.perf_counter_ns()
depth, move, score = search(self.bot, self.pos, print_info=True, time_limit=time_limit)
time_spent_ms = (time.time() - start) * 1000 + 0.0001
time_spent_ms = (time.perf_counter_ns() - start) / 10**6

try:
client.bots.make_move(self.game_id, get_move_uci(move))
except berserk.exceptions.ResponseError as e: # you flagged
print(e)
print('you flagged')
return

print(f"time: {time_spent_ms:.0f} - kns: {self.bot.nodes / time_spent_ms:.0f}")
print(f"time delta: {time_spent_ms - time_limit:.0f} ms")

# print(f"time delta: {time_spent_ms - time_limit:.0f} ms")
print("-" * 40)

def make_first_move(self):
Expand All @@ -131,11 +148,10 @@ def make_first_move(self):
print("end of theory")

# look for a move
print("playing 1st move")
depth, move, score = search(self.bot, self.pos, print_info=True)

client.bots.make_move(self.game_id, get_move_uci(move))
self.pos = make_move(self.pos, move)
self.moves += get_move_uci(move)

@staticmethod
def look_in_da_book(moves):
Expand All @@ -149,9 +165,9 @@ def look_in_da_book(moves):
print("id name black_numba")
print("id author Avo-k")
print("compiling...")
s = time.time()
compiling_time = time.time()
search(Black_numba(), parse_fen(start_position), print_info=False, depth_limit=1)
print(f"compiled in {time.time() - s:.2f} seconds")
print(f"compiled in {time.time() - compiling_time:.2f} seconds")

for event in client.bots.stream_incoming_events():
if event['type'] == 'challenge':
Expand Down
Loading

0 comments on commit d8dd01a

Please sign in to comment.