/usr/share/pyshared/pychess/Players/PyChess.py is in pychess 0.12~beta3-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | #!/usr/bin/pypy -u
if __name__ == "__main__":
print "feature done=0"
from pychess.Utils import const
const.STANDARD_LOGGING = True
from pychess.System.prefix import addDataPrefix
from pychess.Utils.book import getOpenings
from pychess.Utils.const import *
from pychess.Utils.lutils import lsearch
from pychess.Utils.lutils.ldata import MAXPLY
from pychess.Utils.lutils.lsearch import alphaBeta
from pychess.Utils.lutils.LBoard import LBoard
from pychess.Utils.lutils.lmove import listToSan, toSAN
from time import time
import gettext
import pychess
import random
import sys
gettext.install("pychess", localedir=addDataPrefix("lang"), unicode=1)
class PyChess:
def __init__ (self):
self.sd = MAXPLY
self.skipPruneChance = 0
self.clock = [0, 0]
self.increment = [0, 0]
self.movestogo = 0
self.searchtime = 0
self.scr = 0 # The current predicted score. Used when accepting draw offers
self.playingAs = WHITE
self.ponder = False # Currently unused
self.post = False
self.debug = True
def makeReady(self):
try:
import psyco
psyco.bind(alphaBeta)
except ImportError:
pass
#===========================================================================
# Play related
#===========================================================================
def __remainingMovesA (self):
# Based on regression of a 180k games pgn
x = self.board.plyCount
return -1.71086e-12*x**6 \
+1.69103e-9*x**5 \
-6.00801e-7*x**4 \
+8.17741e-5*x**3 \
+2.91858e-4*x**2 \
-0.94497*x \
+78.8979
def __remainingMovesB (self):
# We bet a game will be around 80 moves
x = self.board.plyCount
return max(80-x,4)
def __getBestOpening (self):
totalWeight = 0
choice = None
for move, weight, histGames, histScore in getOpenings(self.board):
totalWeight += weight
if totalWeight == 0:
break
if not move or random.randrange(totalWeight) < weight:
choice = move
return choice
def __go (self, ondone=None):
""" Finds and prints the best move from the current position """
mv = self.__getBestOpening()
if mv:
mvs = [mv]
if not mv:
lsearch.skipPruneChance = self.skipPruneChance
lsearch.searching = True
timed = self.basetime > 0
if self.searchtime > 0:
usetime = self.searchtime
else:
usetime = self.clock[self.playingAs] / self.__remainingMovesA()
if self.clock[self.playingAs] < 6*60+self.increment[self.playingAs]*40:
# If game is blitz, we assume 40 moves rather than 80
usetime *= 2
# The increment is a constant. We'll use this always
usetime += self.increment[self.playingAs]
if usetime < 0.5:
# We don't wan't to search for e.g. 0 secs
usetime = 0.5
prevtime = 0
starttime = time()
lsearch.endtime = starttime + usetime if timed else sys.maxint
if self.debug:
if timed:
print "# Time left: %3.2f s; Planing to think for %3.2f s" % (self.clock[self.playingAs], usetime)
else:
print "# Searching to depth %d without timelimit" % self.sd
for depth in range(1, self.sd+1):
# Heuristic time saving
# Don't waste time, if the estimated isn't enough to complete next depth
if timed and usetime <= prevtime*4 and usetime > 1:
break
lsearch.timecheck_counter = lsearch.TIMECHECK_FREQ
search_result = alphaBeta(self.board, depth)
if lsearch.searching:
mvs, self.scr = search_result
if time() > lsearch.endtime:
break
if self.post:
pv = " ".join(listToSan(self.board, mvs))
time_cs = int(100 * (time()-starttime))
print depth, self.scr, time_cs, lsearch.nodes, pv
else:
# We were interrupted
if depth == 1:
mvs, self.scr = search_result
break
prevtime = time()-starttime - prevtime
self.clock[self.playingAs] -= time() - starttime - self.increment[self.playingAs]
if not mvs:
if not lsearch.searching:
# We were interupted
lsearch.nodes = 0
return
# This should only happen in terminal mode
if self.scr == 0:
print "result %s" % reprResult[DRAW]
elif self.scr < 0:
if self.board.color == WHITE:
print "result %s" % reprResult[BLACKWON]
else: print "result %s" % reprResult[WHITEWON]
else:
if self.board.color == WHITE:
print "result %s" % reprResult[WHITEWON]
else: print "result %s" % reprResult[BLACKWON]
return
lsearch.nodes = 0
lsearch.searching = False
move = mvs[0]
sanmove = toSAN(self.board, move)
if ondone: ondone(sanmove)
return sanmove
def __analyze (self):
""" Searches, and prints info from, the position as stated in the cecp
protocol """
start = time()
lsearch.endtime = sys.maxint
lsearch.searching = True
for depth in xrange (1, self.sd):
if not lsearch.searching:
break
t = time()
mvs, scr = alphaBeta (self.board, depth)
pv = " ".join(listToSan(self.board, mvs))
time_cs = int(100 * (time() - start))
print depth, scr, time_cs, lsearch.nodes, pv
lsearch.nodes = 0
################################################################################
# main #
################################################################################
if __name__ == "__main__":
if len(sys.argv) == 1 or sys.argv[1:] == ["xboard"]:
from pychess.Players.PyChessCECP import PyChessCECP
pychess = PyChessCECP()
elif len(sys.argv) == 5 and sys.argv[1] == "fics":
from pychess.Players.PyChessFICS import PyChessFICS
pychess = PyChessFICS(*sys.argv[2:])
else:
print "Unknown argument(s):", repr(sys.argv)
sys.exit(0)
pychess.makeReady()
pychess.run()
|