4 import time
, ctypes
, thread
, Queue
, threading
11 def updatePVCache(pv
):
12 for (a
, b
) in zip(pv
, pv
[1:]):
16 def alphaBetaInC(pos
, depth
,
17 alpha
, beta
, stopper
= None, childArray
= None):
18 counter
= ctypes
.c_long(1)
19 if childArray
is None:
20 childArray
= (Position
* (depth
* 32))()
22 value
= lib
.alphaBeta(ctypes
.byref(pos
), childArray
, depth
,
23 alpha
, beta
, ctypes
.byref(counter
), ctypes
.byref(stopper
))
28 for i
in range(depth
):
30 node
= node
.children()[pos
.getBranch(i
)]
34 return dict(value
= value
, pv
= pv
,
35 nodeCount
= counter
.value
)
37 def alphaBeta(pos
, depth
, alpha
= -99999, beta
= 99999, splits
= 0,
38 stopper
= None, top
= False, parentProc
= None):
42 pos
.offswitch
.value
= 0
43 stopper
= pos
.offswitch
46 result
= alphaBetaSequential(pos
, depth
, alpha
, beta
, stopper
)
48 result
= alphaBetaParallel(pos
, depth
, alpha
, beta
, splits
, stopper
, parentProc
)
52 updatePVCache(result
['pv'])
55 result
['time'] = int(b
- a
) + 1
59 def alphaBetaSequential(pos
, depth
, alpha
, beta
, stopper
):
60 if depth
== 0 or not (pos
.fen() in pvCache
):
61 return alphaBetaInC(pos
, depth
, alpha
, beta
, stopper
)
63 favorite
= pvCache
[pos
.fen()]
64 children
= pos
.children()
65 children
.remove(favorite
)
66 children
.insert(0, favorite
)
72 childArray
= (Position
* (32 * depth
))()
74 for i
, child
in enumerate(children
):
76 result
= alphaBetaSequential(child
, nextDepth
, -beta
, -alpha
,
79 result
= alphaBetaInC(child
, nextDepth
, -beta
, -alpha
, stopper
,
80 childArray
= childArray
)
82 value
= -result
['value']
83 nodeCount
+= result
['nodeCount']
89 bestPV
= [pos
] + result
['pv']
91 return dict(value
= alpha
, pv
= bestPV
, nodeCount
= nodeCount
)
97 def alphaBetaParallel(pos
, depth
, alpha
, beta
, splits
, stopper
, parentProc
= None):
99 gstopper
= ctypes
.c_int(0)
100 if depth
== 0 or len(kids
) == 0:
101 return alphaBeta(pos
, 0, alpha
, beta
, 0, gstopper
)
105 results
= Queue
.Queue()
106 for k
in kids
: k
.done
= False
112 if pos
.fen() in pvCache
:
113 favorite
= pvCache
[pos
.fen()]
114 kids
[kids
.index(favorite
)] = None
121 if k
is not None: q
.put(k
)
127 while rfq
< len(kids
):
128 if len(running
) < at_a_time
:
130 next
= q
.get_nowait().copy()
131 stopper
= ctypes
.c_int(0)
133 ret
= next
, proc
, alphaBeta(next
, depth
- 1, -beta
, -alpha
,
134 splits
- at_a_time
+ 1, stopper
, parentProc
)
135 if stopper
.value
== 0:
138 def stop(): stopper
.value
= 1
141 proc
= parentProc
.spawn(calc
, stop
)
143 proc
= spawn
.spawn(calc
, stop
)
153 resChild
, resProc
, result
= results
.get(True, .001)
154 if hasattr(resProc
, 'defunct'):
160 running
.remove(resProc
)
161 except ValueError: pass
165 value
= -result
['value']
166 nodeCount
+= result
['nodeCount']
169 if proc
.position
== resChild
:
179 bestPV
= [pos
] + result
['pv']
181 # evaluate other pos (if there is one) with this alpha
185 running.remove(proc)"""
187 # put that pos at the front of the queue
189 while not q
.empty(): newQ
.put(q
.get())
191 while not newQ
.empty(): q
.put(newQ
.get())
192 except KeyboardInterrupt:
193 for kid
in running
: kid
.stop()
196 for kid
in running
: kid
.stop()
197 return dict(value
= alpha
, nodeCount
= nodeCount
, pv
= bestPV
)