1 2import os 3from struct import Struct 4from collections import namedtuple 5 6from pychess.System import conf 7from pychess.Utils.lutils.lmove import parsePolyglot 8from pychess.System.Log import log 9 10path = conf.get("opening_file_entry") 11 12if os.path.isfile(path): 13 bookfile = True 14else: 15 bookfile = False 16 log.warning("Could not find %s" % path) 17 18# The book probing code is based on that of PolyGlot by Fabien Letouzey. 19# PolyGlot is available under the GNU GPL from http://wbec-ridderkerk.nl 20 21BookEntry = namedtuple('BookEntry', 'key move weight learn') 22# 'key' c_uint64 the position's hash 23# 'move' c_uint16 the candidate move 24# 'weight' c_uint16 proportional to prob. we should play it 25# The following terms are not always available: 26# 'learn' c_uint32 we use this NOT the polyglot way but as in 27# https://github.com/mcostalba/chess_db 28 29entrystruct = Struct(">QHHI") 30entrysize = entrystruct.size 31 32 33def getOpenings(board): 34 """ Return a tuple (move, weight, learn) for each opening move 35 in the given position. The weight is proportional to the probability 36 that a move should be played. By convention, games is the number of 37 times a move has been tried, and score the number of points it has 38 scored (with 2 per victory and 1 per draw). However, opening books 39 aren't required to keep this information. """ 40 41 openings = [] 42 if not bookfile: 43 return openings 44 45 with open(path, "rb") as bookFile: 46 key = board.hash 47 # Find the first entry whose key is >= the position's hash 48 bookFile.seek(0, os.SEEK_END) 49 low, high = 0, bookFile.tell() // 16 - 1 50 if high < 0: 51 return openings 52 while low < high: 53 mid = (low + high) // 2 54 bookFile.seek(mid * 16) 55 entry = bookFile.read(entrysize) 56 if len(entry) != entrysize: 57 return openings 58 entry = BookEntry._make(entrystruct.unpack(entry)) 59 if entry.key < key: 60 low = mid + 1 61 else: 62 high = mid 63 64 bookFile.seek(low * 16) 65 while True: 66 entry = bookFile.read(entrysize) 67 if len(entry) != entrysize: 68 return openings 69 entry = BookEntry._make(entrystruct.unpack(entry)) 70 if entry.key != key: 71 break 72 move = parsePolyglot(board, entry.move) 73 openings.append((move, entry.weight, entry.learn)) 74 return openings 75