-
Notifications
You must be signed in to change notification settings - Fork 4
/
adapt.py
executable file
·164 lines (138 loc) · 3.8 KB
/
adapt.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/bin/env python3
# Simple adaptive chess engine using Stockfish
import chess as c
import chess.polyglot
if c.__version__ < '0.26':
import chess.uci
else:
import chess.engine
import sys, math, time
from random import expovariate
# computer plays as Black by default
COMPC = c.BLACK
PLAYC = c.WHITE
NUMMOV = 20 # number of moves to consider for each position
MTIME = 3 # time in seconds per move
EV = 1 # target evaluation
ALIM = 2 # limit for adaptive playing
LAMBDA = 1 # blunder parameter
ENGINE = "stockfish" # name of chess engine binary to use
TRUEVAL = True # show true evaluation instead of evalution of chosen computer move?
USEBOOK = True # use opening book?
BOOKPATH = "Elo2400.bin" # path to Polyglot opening book
WAITBOOK = True # slow down book moves
b = c.Board()
def pm():
if COMPC == c.WHITE:
return 1
else:
return -1
def getmove(b, silent = False):
"Get move for board"
global COMPC, PLAYC
if b.turn == c.WHITE:
COMPC = c.WHITE
PLAYC = c.BLACK
else:
COMPC = c.BLACK
PLAYC = c.WHITE
if not silent:
print(b.unicode())
print("FEN:", b.fen())
target = (EV + expovariate(LAMBDA)) * -pm() # evaluation target value
start = time.time()
mov = []
# get a book move if available:
if USEBOOK:
with chess.polyglot.open_reader(BOOKPATH) as book:
try:
mv = book.weighted_choice(b)
except:
pass
else:
if WAITBOOK:
time.sleep(MTIME + 1)
if c.__version__ >= '0.28':
mm = mv.move.uci()
else:
mm = mv.move().uci()
print('info score book time %d pv %s' % (1000 * (time.time() - start), mm))
return 0, [mm]
if c.__version__ >= '0.26':
engine = chess.engine.SimpleEngine.popen_uci(ENGINE)
info = engine.analyse(b, chess.engine.Limit(time = MTIME), multipv = NUMMOV)
engine.quit()
resm = len(info)
for x in range(resm):
#print("# ", info[x]["score"].white().score(mate_score = 100000) / 100, info[x]["pv"][0])
mov.append((info[x]["score"].white().score(mate_score = 100000) / 100, info[x]["pv"][0]))
else:
engine = c.uci.popen_engine(ENGINE)
engine.uci()
engine.setoption({"MultiPV": NUMMOV})
engine.isready()
engine.position(b)
info_handler = chess.uci.InfoHandler()
engine.info_handlers.append(info_handler)
engine.go(movetime = 1000 * MTIME)
engine.quit()
pv = info_handler.info["pv"]
score = info_handler.info["score"]
resm = len(pv)
for x in range(1, resm + 1):
sc = score[x].cp
if sc == None:
sc = score[x].mate
if sc > 0:
sc = 1000 - sc
else:
sc = -1000 - sc
mov.append((pm() * sc / 100, pv[x][0]))
diff = 1e6
pos = 0
if COMPC == c.WHITE:
realpos = max([q[0] for q in mov])
else:
realpos = min([q[0] for q in mov])
if ALIM > 0:
# play best move if eval is outside bounds:
if (COMPC == c.WHITE and realpos > ALIM) or (COMPC == c.BLACK and realpos < -ALIM):
target = realpos
for x in range(resm):
if abs(mov[x][0] - target) < diff:
m = mov[x][1].uci()
diff = abs(mov[x][0] - target)
pos = mov[x][0]
if TRUEVAL:
pos = realpos
print('info score cp %d time %d pv %s' % (pm() * 100 * pos, 1000 * (time.time() - start), m))
return pos, [m]
if __name__ == '__main__':
while True: # game loop
while True:
print(b.unicode())
if sys.version < '3':
move = raw_input("Your move? ")
else:
move = input("Your move? ")
try:
try:
b.push_san(move)
except ValueError:
b.push_uci(move)
except:
print("Sorry? Try again. (Or type Control-C to quit.)")
else:
break
if b.result() != '*':
print("Game result:", b.result())
break
tt = time.time()
t, m = getmove(b)
print("My move: %u. %s ( calculation time spent: %u m %u s )" % (
b.fullmove_number, m[0],
(time.time() - tt) // 60, (time.time() - tt) % 60))
b.push(c.Move.from_uci(m[0]))
if b.result() != '*':
print("Game result:", b.result())
break