diff --git a/Code/Configuracion.py b/Code/Configuracion.py
index 07e51ba..ed4f836 100644
--- a/Code/Configuracion.py
+++ b/Code/Configuracion.py
@@ -135,7 +135,7 @@ def __init__(self, user):
self.rivalInicial = "tarrasch"
self.rival = self.buscaRival(self.rivalInicial)
- self.tutorInicial = "deepfish"
+ self.tutorInicial = "mcbrain"
self.tutor = self.buscaRival(self.tutorInicial)
self.tutorMultiPV = 10 # 0: maximo
self.tutorDifPts = 0
diff --git a/Code/DBgames.py b/Code/DBgames.py
index 2c1e446..d275713 100644
--- a/Code/DBgames.py
+++ b/Code/DBgames.py
@@ -431,6 +431,9 @@ def __init__(self, nomFichero):
self.rowidReader = Util.RowidReader(self.nomFichero, self.tabla)
+ def reset_cache(self):
+ self.cache = {}
+
def addcache(self, rowid, reg):
if len(self.cache) > self.maxcache:
keys = self.cache.keys()
@@ -879,9 +882,18 @@ def leeAllRecno(self, recno):
self._cursor.execute("SELECT %s FROM %s WHERE rowid =%d" % (select, self.tabla, rowid))
return self._cursor.fetchone()
+ def leeRegAllRecno(self, recno):
+ raw = self.leeAllRecno(recno)
+ alm = Util.Almacen()
+ for campo in self.liCamposAll:
+ setattr(alm, campo, raw[campo])
+ return alm, raw
+
def leePartidaRecno(self, recno):
raw = self.leeAllRecno(recno)
+ return self.leePartidaRaw(raw)
+ def leePartidaRaw(self, raw):
p = Partida.PartidaCompleta()
xpgn = raw["PGN"]
rtags = None
@@ -1005,6 +1017,8 @@ def modifica(self, recno, partidaCompleta):
self.dbSTAT.append(pvAnt, resAnt, -1)
self.dbSTAT.append(pvNue, resNue, +1)
+ del self.cache[rowid]
+
return True
def inserta(self, partidaCompleta):
@@ -1038,3 +1052,74 @@ def inserta(self, partidaCompleta):
def guardaPartidaRecno(self, recno, partidaCompleta):
return self.inserta(partidaCompleta) if recno is None else self.modifica(recno, partidaCompleta)
+
+ def massive_change_tags(self, li_tags_change, liRegistros, remove, overwrite):
+ dtag = Util.SymbolDict({tag:val for tag, val in li_tags_change})
+
+ def work_tag(tag, alm):
+ if tag in dtag:
+ ant = getattr(alm, tag.upper())
+ if (ant and overwrite) or not ant:
+ setattr(alm, tag.upper(), dtag[tag])
+
+ if remove:
+ remove = remove.upper()
+
+ for recno in liRegistros:
+ alm, raw = self.leeRegAllRecno(recno)
+
+ work_tag("Event", alm)
+ work_tag("Site", alm)
+ work_tag("Date", alm)
+
+ p = self.leePartidaRaw(raw)
+ if remove:
+ for n, (tag, val) in enumerate(p.liTags):
+ if tag.upper() == remove:
+ del p.liTags[n]
+ break
+ setattr(alm, remove, "")
+
+ st_tag_ant_upper = set()
+ for n, (tag, val) in enumerate(p.liTags):
+ if overwrite:
+ if tag in dtag:
+ p.liTags[n] = [tag, dtag[tag]]
+ st_tag_ant_upper.add(tag.upper())
+ setattr(alm, tag.upper(), p.liTags[n][1])
+
+ for tag_new in dtag:
+ if tag_new.upper() not in st_tag_ant_upper:
+ p.liTags.append([tag_new, dtag[tag_new]])
+ setattr(alm, tag_new.upper(), dtag[tag_new])
+
+ rowid = self.liRowids[recno]
+ pgn = {"FULLGAME": p.save()}
+ xpgn = Util.var2blob(pgn)
+ sql = "UPDATE GAMES SET EVENT=?, SITE=?, DATE=?, WHITE=?, BLACK=?, RESULT=?, " \
+ "ECO=?, WHITEELO=?, BLACKELO=?, PGN=? WHERE ROWID = %d" % rowid
+ self._cursor.execute(sql, (alm.EVENT, alm.SITE, alm.DATE, alm.WHITE, alm.BLACK, alm.RESULT,
+ alm.ECO, alm.WHITEELO, alm.BLACKELO, xpgn))
+
+ self._conexion.commit()
+
+ self.reset_cache()
+
+ def insert_pks(self, path_pks):
+ f = open(path_pks, "rb")
+ txt = f.read()
+ f.close()
+ dic = Util.txt2dic(txt)
+ fen = dic.get("FEN")
+ if fen:
+ return _("This pks file is not a complete game")
+
+ liTags = dic.get("liPGN", [])
+
+ partidaCompleta = Partida.PartidaCompleta(liTags=liTags)
+ partidaCompleta.recuperaDeTexto(dic["PARTIDA"])
+
+ if not self.inserta(partidaCompleta):
+ return _("This game already exists.")
+
+ return None
diff --git a/Code/DBgamesFEN.py b/Code/DBgamesFEN.py
index 20c2b9a..45c14a9 100644
--- a/Code/DBgamesFEN.py
+++ b/Code/DBgamesFEN.py
@@ -45,7 +45,6 @@ def __init__(self, nomFichero):
self._conexion.text_factory = lambda x: unicode(x, "utf-8", "ignore")
self._conexion.row_factory = sqlite3.Row
self._cursor = self._conexion.cursor()
- self.tabla = "games"
self.select = ",".join(self.liCamposRead)
self.order = None
self.filter = None
@@ -62,17 +61,17 @@ def __init__(self, nomFichero):
atexit.register(self.close)
- self.rowidReader = Util.RowidReader(self.nomFichero, self.tabla)
+ def reset_cache(self):
+ self.cache = {}
def controlInicial(self):
cursor = self._conexion.cursor()
- cursor.execute("pragma table_info(%s)" % self.tabla)
+ cursor.execute("pragma table_info(GAMES)")
liCampos = cursor.fetchall()
cursor.close()
if not liCampos:
- sql = "CREATE TABLE %s (" % self.tabla
- sql += "FEN VARCHAR NOT NULL PRIMARY KEY,"
+ sql = "CREATE TABLE GAMES (FEN VARCHAR NOT NULL PRIMARY KEY,"
for field in self.liCamposBase:
if field != "FEN":
sql += "%s VARCHAR," % field
@@ -85,21 +84,26 @@ def controlInicial(self):
cursor.execute(sql)
cursor.close()
+ def lee_rowids(self):
+ sql = "SELECT ROWID FROM GAMES"
+ if self.filter:
+ sql += " WHERE %s" % self.filter
+ if self.order:
+ sql += " ORDER BY %s" % self.order
+ self._cursor.execute(sql)
+ self.liRowids = [ row[0] for row in self._cursor.fetchall()]
+
def close(self):
if self._conexion:
self._cursor.close()
self._conexion.close()
self._conexion = None
- if self.rowidReader:
- self.rowidReader.stopnow()
- self.rowidReader = None
def ponOrden(self, liOrden):
li = ["%s %s" % (campo, tipo) for campo, tipo in liOrden]
self.order = ",".join(li)
- self.liRowids = []
- self.rowidReader.run(self.liRowids, self.filter, self.order)
self.liOrden = liOrden
+ self.lee_rowids()
def dameOrden(self):
return self.liOrden
@@ -117,44 +121,23 @@ def addcache(self, rowid, reg):
def field(self, nfila, name):
rowid = self.liRowids[nfila]
if rowid not in self.cache:
- self._cursor.execute("SELECT %s FROM %s WHERE rowid =%d" % (self.select, self.tabla, rowid))
+ self._cursor.execute("SELECT %s FROM GAMES WHERE rowid =%d" % (self.select, rowid))
reg = self._cursor.fetchone()
self.addcache(rowid, reg)
return self.cache[rowid][name]
- def siFaltanRegistrosPorLeer(self):
- if not self.rowidReader:
- return False
- return not self.rowidReader.terminado()
-
def reccount(self):
- if not self.rowidReader:
- return 0
- n = self.rowidReader.reccount()
- # Si es cero y no ha terminado de leer, se le da tiempo para que devuelva algo
- while n == 0 and not self.rowidReader.terminado():
- time.sleep(0.05)
- n = self.rowidReader.reccount()
- return n
+ return len(self.liRowids)
def setFilter(self, condicion):
self.filter = condicion
-
- self.liRowids = []
- self.rowidReader.run(self.liRowids, condicion, self.order)
+ self.lee_rowids()
def dameFEN_PV(self, fila):
xpv = self.field(fila, "XPV")
fen = self.field(fila, "FEN")
return fen, xpv2pv(xpv)
- def all_reccount(self):
- self.liRowids = []
- self.rowidReader.run(self.liRowids, None, None)
- while not self.rowidReader.terminado():
- time.sleep(0.1)
- return self.reccount()
-
def rotulo(self):
rotulo = os.path.basename(self.nomFichero)[:-4]
if rotulo == "Positions Database":
@@ -172,17 +155,17 @@ def leerPGN(self, fichero, dlTmp):
sicodec = codec not in ("utf-8", "ascii")
liRegs = []
- stRegs = set()
nRegs = 0
conexion = self._conexion
cursor = self._cursor
- self.liCamposBase = ["FEN", "EVENT", "SITE", "DATE", "WHITE", "BLACK", "RESULT", "PLIES"]
- self.liCamposWork = ["XPV", ]
- self.liCamposBLOB = ["PGN", ]
+ cursor.execute("SELECT FEN FROM GAMES")
+ liRows = cursor.fetchall()
+ stRegs = set(row[0] for row in liRows)
+
- sql = "insert into games (FEN,EVENT,SITE,DATE,WHITE,BLACK,RESULT,XPV,PGN,PLIES) values (?,?,?,?,?,?,?,?,?,?);"
+ sql = "insert into GAMES (FEN,EVENT,SITE,DATE,WHITE,BLACK,RESULT,XPV,PGN,PLIES) values (?,?,?,?,?,?,?,?,?,?);"
liCabs = self.liCamposBase[:-1] # all except PLIES PGN, TAGS
liCabs.append("PLYCOUNT")
@@ -195,7 +178,7 @@ def leerPGN(self, fichero, dlTmp):
if fen in stRegs:
dup = True
else:
- cursor.execute("SELECT COUNT(*) FROM games WHERE FEN = ?", (fen,))
+ cursor.execute("SELECT COUNT(*) FROM GAMES WHERE FEN = ?", (fen,))
num = cursor.fetchone()[0]
dup = num > 0
if dup:
@@ -246,27 +229,38 @@ def leerPGN(self, fichero, dlTmp):
conexion.commit()
dlTmp.ponContinuar()
+ self.lee_rowids()
def leeAllRecno(self, recno):
rowid = self.liRowids[recno]
select = ",".join(self.liCamposAll)
- self._cursor.execute("SELECT %s FROM %s WHERE rowid =%d" % (select, self.tabla, rowid))
+ self._cursor.execute("SELECT %s FROM GAMES WHERE rowid =%d" % (select, rowid))
return self._cursor.fetchone()
+ def leeRegAllRecno(self, recno):
+ raw = self.leeAllRecno(recno)
+ alm = Util.Almacen()
+ for campo in self.liCamposAll:
+ setattr(alm, campo, raw[campo])
+ return alm, raw
+
def leePartidaRecno(self, recno):
raw = self.leeAllRecno(recno)
+ return self.leePartidaRaw(raw)
+ def leePartidaRaw(self, raw):
p = Partida.PartidaCompleta(fen=raw["FEN"])
xpgn = raw["PGN"]
- rtags = None
if xpgn:
xpgn = Util.blob2var(xpgn)
- if type(xpgn) == str: # Version -9
+ if type(xpgn) in (str, unicode): # Version -9
p.readPGN(VarGen.configuracion, xpgn)
return p
p.restore(xpgn["FULLGAME"])
return p
+ rtags = None
+
p.leerPV(xpv2pv(raw["XPV"]))
rots = ["Event", "Site", "Date", "Round", "White", "Black", "Result",
"WhiteTitle", "BlackTitle", "WhiteElo", "BlackElo", "WhiteUSCF", "BlackUSCF", "WhiteNA", "BlackNA",
@@ -287,9 +281,187 @@ def leePartidaRecno(self, recno):
return p
def borrarLista(self, lista):
- cSQL = "DELETE FROM %s WHERE rowid = ?" % self.tabla
+ cSQL = "DELETE FROM GAMES WHERE rowid = ?"
lista.sort(reverse=True)
for recno in lista:
self._cursor.execute(cSQL,(self.liRowids[recno],))
del self.liRowids[recno]
self._conexion.commit()
+
+ def modifica(self, recno, partidaCompleta):
+ reg_ant = self.leeAllRecno(recno)
+
+ pgn = {}
+ pgn["FULLGAME"] = partidaCompleta.save()
+ xpgn = Util.var2blob(pgn)
+
+ dTags = {}
+ for key, value in partidaCompleta.liTags:
+ dTags[key.upper()] = value
+ dTags["PLIES"] = partidaCompleta.numJugadas()
+
+ liFields = []
+ liData = []
+ for field in self.liCamposBase:
+ if reg_ant[field] != dTags.get(field):
+ liFields.append("%s=?"%field)
+ liData.append(dTags.get(field))
+ if xpgn != reg_ant["PGN"]:
+ liFields.append("PGN=?")
+ liData.append(xpgn)
+
+ pvNue = partidaCompleta.pv()
+ xpv = pv2xpv(pvNue)
+ liFields.append("XPV=?")
+ liData.append(xpv)
+
+ rowid = self.liRowids[recno]
+ if len(liFields) == 0:
+ return True
+ fields = ",".join(liFields)
+ sql = "UPDATE GAMES SET %s WHERE ROWID = %d" % (fields, rowid)
+ self._cursor.execute(sql, liData)
+ self._conexion.commit()
+
+ del self.cache[rowid]
+
+ return True
+
+ def si_existe_fen(self, fen):
+ self._cursor.execute("SELECT COUNT(*) FROM GAMES WHERE FEN = ?", (fen,))
+ num = self._cursor.fetchone()[0]
+ return num
+
+ def inserta(self, partidaCompleta):
+ pgn = {}
+ pgn["FULLGAME"] = partidaCompleta.save()
+ xpgn = Util.var2blob(pgn)
+
+ dTags = {}
+ for key, value in partidaCompleta.liTags:
+ dTags[key.upper()] = value
+ dTags["PLIES"] = partidaCompleta.numJugadas()
+
+ pv = partidaCompleta.pv()
+ xpv = pv2xpv(pv)
+ data = [xpv, xpgn]
+ for field in self.liCamposBase:
+ data.append(dTags.get(field, None))
+
+ sql = "insert into GAMES (XPV,PGN,FEN,EVENT,SITE,DATE,WHITE,BLACK,RESULT,PLIES)" \
+ " values (?,?,?,?,?,?,?,?,?,?);"
+ self._cursor.execute(sql, data)
+ lastrowid = self._cursor.lastrowid
+ self._conexion.commit()
+
+ self.liRowids.append(lastrowid)
+
+ return True
+
+ def guardaPartidaRecno(self, recno, partidaCompleta):
+ return self.inserta(partidaCompleta) if recno is None else self.modifica(recno, partidaCompleta)
+
+ def appendDB(self, db, liRecnos, dlTmp):
+ duplicados = importados = 0
+
+ conexion = self._conexion
+ cursor = self._cursor
+
+ sql = "insert into GAMES (FEN,EVENT,SITE,DATE,WHITE,BLACK,XPV,PGN,PLIES) values (?,?,?,?,?,?,?,?,?);"
+
+ for recno in liRecnos:
+ raw = db.leeAllRecno(recno)
+
+ fen = raw["FEN"]
+ cursor.execute("SELECT COUNT(*) FROM GAMES WHERE FEN = ?", (fen,))
+ num = cursor.fetchone()[0]
+ dup = num > 0
+ if dup:
+ duplicados += 1
+ else:
+ reg = (fen, raw["EVENT"], raw["SITE"], raw["DATE"], raw["WHITE"], raw["BLACK"], raw["XPV"], raw["PGN"],
+ raw["PLIES"])
+ importados += 1
+ cursor.execute(sql, reg)
+
+ if not dlTmp.actualiza(duplicados + importados, duplicados, importados):
+ break
+
+ dlTmp.actualiza(duplicados + importados, duplicados, importados)
+ dlTmp.ponSaving()
+
+ conexion.commit()
+
+ dlTmp.ponContinuar()
+ self.lee_rowids()
+
+ def massive_change_tags(self, li_tags_change, liRegistros, remove, overwrite):
+ dtag = Util.SymbolDict({tag:val for tag, val in li_tags_change})
+
+ def work_tag(tag, alm):
+ if tag in dtag:
+ ant = getattr(alm, tag.upper())
+ if (ant and overwrite) or not ant:
+ setattr(alm, tag.upper(), dtag[tag])
+
+ if remove:
+ remove = remove.upper()
+
+ for recno in liRegistros:
+ alm, raw = self.leeRegAllRecno(recno)
+
+ work_tag("Event", alm)
+ work_tag("Site", alm)
+ work_tag("Date", alm)
+
+ p = self.leePartidaRaw(raw)
+ if remove:
+ for n, (tag, val) in enumerate(p.liTags):
+ if tag.upper() == remove:
+ del p.liTags[n]
+ break
+ setattr(alm, remove, "")
+
+ st_tag_ant_upper = set()
+ for n, (tag, val) in enumerate(p.liTags):
+ if overwrite:
+ if tag in dtag:
+ p.liTags[n] = [tag, dtag[tag]]
+ st_tag_ant_upper.add(tag.upper())
+ setattr(alm, tag.upper(), p.liTags[n][1])
+
+ for tag_new in dtag:
+ if tag_new.upper() not in st_tag_ant_upper:
+ p.liTags.append([tag_new, dtag[tag_new]])
+ setattr(alm, tag_new.upper(), dtag[tag_new])
+
+ rowid = self.liRowids[recno]
+ pgn = {"FULLGAME": p.save()}
+ xpgn = Util.var2blob(pgn)
+ sql = "UPDATE GAMES SET EVENT=?, SITE=?, DATE=?, WHITE=?, BLACK=?, PGN=?, RESULT=? WHERE ROWID = %d" % rowid
+ self._cursor.execute(sql, (alm.EVENT, alm.SITE, alm.DATE, alm.WHITE, alm.BLACK, xpgn, alm.RESULT))
+
+ self._conexion.commit()
+
+ self.reset_cache()
+
+ def insert_pks(self, path_pks):
+ f = open(path_pks, "rb")
+ txt = f.read()
+ f.close()
+ dic = Util.txt2dic(txt)
+ fen = dic.get("FEN")
+ if not fen:
+ return _("This pks file is a complete game")
+
+ if self.si_existe_fen(fen):
+ return _("This position already exists.")
+
+ liTags = dic.get("liPGN", [])
+
+ partidaCompleta = Partida.PartidaCompleta(fen=fen, liTags=liTags)
+ partidaCompleta.recuperaDeTexto(dic["PARTIDA"])
+
+ self.inserta(partidaCompleta)
+
+ return None
diff --git a/Code/DGT.py b/Code/DGT.py
index 13779c2..6d26b23 100644
--- a/Code/DGT.py
+++ b/Code/DGT.py
@@ -68,9 +68,8 @@ def log(cad):
log.write(".6.[%s]\n%s\n" % (Util.hoy(), cad))
log.close()
-# CALLBACKS
-
+# CALLBACKS
def registerStatusFunc(dato):
envia("status", dato)
return 1
@@ -88,9 +87,8 @@ def registerWhiteMoveInputFunc(dato):
def registerBlackMoveInputFunc(dato):
return envia("blackMove", _dgt2pv(dato))
-# Activar/desactivar/reactivar
-
+# Activar/desactivar/reactivar
def activar():
dgt = None
for path in ("",
@@ -191,9 +189,8 @@ def writeClocks(wclock, bclock):
dgt = VarGen.dgt
dgt._DGTDLL_SetNRun(wclock, bclock, 0)
-# Utilidades para la trasferencia de datos
-
+# Utilidades para la trasferencia de datos
def _dgt2fen(dato):
n = 0
ndato = len(dato)
@@ -239,9 +236,8 @@ def _dgt2pv(dato):
return dato[1:3] + dato[4:6]
-# Lo mismo, de otra forma
-
+# Lo mismo, de otra forma
def xdgt2fen(xdgt):
liD = xdgt.split(" ")
dgt = liD[0]
diff --git a/Code/EnginesWindows.py b/Code/EnginesWindows.py
index 1502184..7eb9abf 100644
--- a/Code/EnginesWindows.py
+++ b/Code/EnginesWindows.py
@@ -240,14 +240,14 @@ def mas(cm):
cm.ponMultiPV(20, 500)
mas(cm)
- cm = ConfigMotor("deepfish", "Tord Romstad, Marco Costalba, Joona Kiiski, fork by Marco Zerbinati", "7 32bit", "https://github.com/Zerbinati/DeepFishMZ")
- cm.path = "windows/DeepFishMZ 32.exe"
- cm.path_64 = "windows/DeepFishMZ 64 BMI2.exe", "7 64bit bmi2"
+ cm = ConfigMotor("mcbrain", "Michael Byrne (based on stockfish)", "2.1a 32bit", "https://github.com/MichaelB7/Stockfish/releases")
+ cm.path = "McBrain_2017_v21a_x32_old.exe"
+ cm.path_64 = "McBrain_2017_v21a_x64_bmi2.exe", "2.1a 64bit bmi2"
cm.elo = 3200
- cm.ordenUCI("Ponder", "false")
+ cm.ordenUCI("Tactical", "8")
cm.ordenUCI("Hash", "64")
cm.ordenUCI("Threads", "1")
- cm.ponMultiPV(20, 500)
+ cm.ponMultiPV(20, 256)
mas(cm)
cm = ConfigMotor("gull", "Vadim Demichev", "3 32bit", "https://sourceforge.net/projects/gullchess/")
@@ -258,7 +258,7 @@ def mas(cm):
cm.ponMultiPV(20, 64)
mas(cm)
- cm = ConfigMotor("irina", "Lucas Monge", "0.15", "")
+ cm = ConfigMotor("irina", "Lucas Monge", "0.15", "https://github.com/lukasmonk/irina")
cm.path = "irina.exe"
cm.elo = 1200
mas(cm)
@@ -279,6 +279,7 @@ def dicMotoresFixedElo():
("rodent", 600, 2600),
("amyan", 1000, 2400),
("rhetoric", 1300, 2600),
+ ("mcbrain", 1200, 2800),
("cheng", 800, 2500),
("greko", 1600, 2400),
("hamsters", 1000, 2000),
diff --git a/Code/Entrenamientos.py b/Code/Entrenamientos.py
index 40af08e..06bfd07 100644
--- a/Code/Entrenamientos.py
+++ b/Code/Entrenamientos.py
@@ -639,7 +639,6 @@ def turn_on_lights(self, name):
title = _("Uwe Auerswald")
folder = "Trainings/Tactics by Uwe Auerswald"
icono = Iconos.Uwe()
- li_tam_blocks = (6, 10, 15, 30, 45, 90)
li_tam_blocks = (5, 10, 20, 40, 80)
resp = PantallaTurnOnLights.pantallaTurnOnLigths(self.procesador, name, title, icono, folder, li_tam_blocks)
diff --git a/Code/GestorEntMaq.py b/Code/GestorEntMaq.py
index dab40dc..5da50f6 100644
--- a/Code/GestorEntMaq.py
+++ b/Code/GestorEntMaq.py
@@ -77,7 +77,7 @@ def inicio(self, dic, aplazamiento=None, siPrimeraJugadaHecha=False):
self.book = dic.get("BOOK", None)
elo = getattr(self.cm, "elo", 0)
- self.maxMoveBook = elo / 200 if 0 <= elo <= 1700 else 9999
+ self.maxMoveBook = elo / 200 if 0 < elo <= 1700 else 9999
if self.book:
self.book.polyglot()
self.bookRR = dic.get("BOOKRR", "mp")
@@ -358,7 +358,7 @@ def reiniciar(self, siPregunta):
if siPregunta:
if not QTUtil2.pregunta(self.pantalla, _("Restart the game?")):
return
-
+ self.analizaTerminar()
self.partida.reset()
if self.siTiempo:
self.pantalla.paraReloj()
@@ -792,13 +792,14 @@ def mueveHumano(self, desde, hasta, coronacion=None):
if num:
rmTutor = self.mrmTutor.rmBest()
menu = QTVarios.LCMenu(self.pantalla)
- submenu = menu.submenu(_("There are %d best moves") % num, Iconos.Motor())
- submenu.opcion("tutor", "%s (%s)" % (_("Show tutor"), rmTutor.abrTextoBase()),
+ menu.opcion("None", _("There are %d best moves") % num, Iconos.Motor())
+ menu.separador()
+ menu.opcion("tutor", "&1. %s (%s)" % (_("Show tutor"), rmTutor.abrTextoBase()),
Iconos.Tutor())
- submenu.separador()
- submenu.opcion("try", _("Try again"), Iconos.Atras())
- submenu.separador()
- submenu.opcion("user", "%s (%s)" % (_("Select my move"), rmUser.abrTextoBase()),
+ menu.separador()
+ menu.opcion("try", "&2. %s" % _("Try again"), Iconos.Atras())
+ menu.separador()
+ menu.opcion("user", "&3. %s (%s)" % (_("Select my move"), rmUser.abrTextoBase()),
Iconos.Player())
self.pantalla.cursorFueraTablero()
resp = menu.lanza()
diff --git a/Code/GestorEverest.py b/Code/GestorEverest.py
index af61104..bcee87f 100644
--- a/Code/GestorEverest.py
+++ b/Code/GestorEverest.py
@@ -126,7 +126,7 @@ def restart(self, lost_points):
licoment.append(_("You have exceeded the limit of lost points."))
if change_game:
- licoment.append(_("You have also exceeded the limit of tries, then you falls to the previous game."))
+ licoment.append(_("You have exceeded the limit of tries, you will fall back to the previous."))
elif lost_points:
licoment.append(_("You must repeat the game from beginning."))
if licoment:
diff --git a/Code/GestorMateMap.py b/Code/GestorMateMap.py
index f09479e..2d9d324 100644
--- a/Code/GestorMateMap.py
+++ b/Code/GestorMateMap.py
@@ -241,7 +241,7 @@ def ponResultado(self, quien):
mensaje = _("Game ended")
if quien == kGanamos:
- mensaje = _("Congratulations you have win %s.") % self.workmap.nameAim()
+ mensaje = _("Congratulations you have won %s.") % self.workmap.nameAim()
self.workmap.winAim(self.partida.pv())
QTUtil2.mensaje(self.pantalla, mensaje)
diff --git a/Code/GestorPartida.py b/Code/GestorPartida.py
index 77e17d1..556ab69 100644
--- a/Code/GestorPartida.py
+++ b/Code/GestorPartida.py
@@ -57,8 +57,8 @@ def inicio(self, partidaCompleta, siCompleta):
self.siguienteJugada()
- def reiniciar(self,):
- if self.siCambios and not QTUtil2.pregunta(self.pantalla, _("You will lost all changes, are you sure?")):
+ def reiniciar(self):
+ if self.siCambios and not QTUtil2.pregunta(self.pantalla, _("You will loose all changes, are you sure?")):
return
p = Partida.PartidaCompleta()
p.restore(self.reinicio)
@@ -322,33 +322,11 @@ def configurarGS(self):
self.tablero.rotaTablero()
elif resp == "posicion":
- resp = Voyager.voyagerFEN(self.pantalla, self.fen)
- if resp is not None:
- self.fen = resp
- self.posicApertura = None
-
- if self.xpgn:
- siInicio = self.fen == ControlPosicion.FEN_INICIAL
- li = self.xpgn.split("\n")
- lin = []
- siFen = False
- for linea in li:
- if linea.startswith("["):
- if "FEN " in linea:
- siFen = True
- if siInicio:
- continue
- linea = '[FEN "%s"]' % self.fen
- lin.append(linea)
- else:
- break
- if not siFen:
- linea = '[FEN "%s"]' % self.fen
- lin.append(linea)
- self.liPGN = lin
- self.xpgn = "\n".join(lin) + "\n\n*"
-
- self.reiniciar()
+ ini_fen = self.partida.iniPosicion.fen()
+ cur_fen = Voyager.voyagerFEN(self.pantalla, ini_fen)
+ if cur_fen and cur_fen != ini_fen:
+ self.partida.resetFEN(cur_fen)
+ self.inicio(self.partida, self.siCompleta)
elif resp == "pasteposicion":
texto = QTUtil.traePortapapeles()
diff --git a/Code/GestorSolo.py b/Code/GestorSolo.py
index 72fa258..b14a7d7 100644
--- a/Code/GestorSolo.py
+++ b/Code/GestorSolo.py
@@ -201,7 +201,6 @@ def tituloVentanaPGN(self):
return "%s-%s (%s, %s,%s)" % (white, black, event, date, result)
def procesarAccion(self, clave):
-
if clave == k_mainmenu:
self.finPartida()
diff --git a/Code/Init.py b/Code/Init.py
index e45e367..ff38ab1 100644
--- a/Code/Init.py
+++ b/Code/Init.py
@@ -1,5 +1,5 @@
DEBUG = False
-VERSION = "10.11.9"
+VERSION = "10.12"
import os
import sys
diff --git a/Code/MotoresExternos.py b/Code/MotoresExternos.py
index 2372251..8cfd135 100644
--- a/Code/MotoresExternos.py
+++ b/Code/MotoresExternos.py
@@ -23,7 +23,7 @@ def leeTXT(self, txt):
self.max = int(li[5])
elif self.tipo == "check":
- self.default = self.default == "true"
+ self.default = self.default.lower() == "true"
self.valor = self.valor.lower() == "true"
elif self.tipo == "button":
diff --git a/Code/PGNreader.py b/Code/PGNreader.py
index f1bcc98..cbacb41 100644
--- a/Code/PGNreader.py
+++ b/Code/PGNreader.py
@@ -315,6 +315,10 @@ def readGames(pgnfile):
siCab = False
siMov = True
pgnMov = [linea, ]
+ else:
+ siCab = False
+ siMov = True
+ pgnMov = []
elif siMov:
if linea:
if linea[0] == '[' and linea.endswith("]"):
diff --git a/Code/Partida.py b/Code/Partida.py
index 3ca9cae..b1ca7d8 100644
--- a/Code/Partida.py
+++ b/Code/Partida.py
@@ -401,3 +401,14 @@ def pgn(self):
txt += "\n%s"%self.pgnBase()
return txt
+ def resetFEN(self, fen):
+ ok = False
+ for n, tag in enumerate(self.liTags):
+ if tag[0] == "FEN":
+ self.liTags[n] = ("FEN", fen)
+ ok = True
+ break
+ if not ok and fen != ControlPosicion.FEN_INICIAL:
+ self.liTags.append(("FEN", fen))
+ Partida.resetFEN(self, fen)
+
diff --git a/Code/Procesador.py b/Code/Procesador.py
index f574b1c..e061821 100644
--- a/Code/Procesador.py
+++ b/Code/Procesador.py
@@ -677,8 +677,8 @@ def tools(self):
menu1 = menu.submenu(_("Database"), Iconos.Database())
menu1.opcion("database", _("Complete games"), Iconos.DatabaseC())
- # menu1.separador()
- # menu1.opcion("databaseFEN", _("Positions"), Iconos.DatabaseF()) # TODO
+ menu1.separador()
+ menu1.opcion("databaseFEN", _("Positions"), Iconos.DatabaseF()) # TODO
menu.separador()
menu.opcion("manual_save", _("Save positions to FNS/PGN"), Iconos.ManualSave())
diff --git a/Code/QT/Controles.py b/Code/QT/Controles.py
index 9ba190e..108e343 100644
--- a/Code/QT/Controles.py
+++ b/Code/QT/Controles.py
@@ -193,6 +193,7 @@ def ponFuente(self, f):
def rehacer(self, liOpciones, valorInicial):
self.liOpciones = liOpciones
self.clear()
+ nindex = 0
for n, opcion in enumerate(liOpciones):
if len(opcion) == 2:
etiqueta, clave = opcion
@@ -201,7 +202,8 @@ def rehacer(self, liOpciones, valorInicial):
etiqueta, clave, icono = opcion
self.addItem(icono, etiqueta, clave)
if clave == valorInicial:
- self.setCurrentIndex(n)
+ nindex = n
+ self.setCurrentIndex(nindex)
def ponValor(self, valor):
for n, opcion in enumerate(self.liOpciones):
diff --git a/Code/QT/DatosNueva.py b/Code/QT/DatosNueva.py
index d2fb4e8..78e3598 100644
--- a/Code/QT/DatosNueva.py
+++ b/Code/QT/DatosNueva.py
@@ -107,8 +107,7 @@ def dameCategoria(wParent, configuracion, procesador):
titulo = _("Competition")
ancho, alto = QTUtil.tamEscritorio()
ancho = min(ancho, 700)
- txt = _(
- "
The aim is to obtain the highest possible score :
- The current point score is displayed in the title bar.
- To obtain points it is necessary to win on different levels in different categories.
- To overcome a level it is necessary to win against the engine with white and with black.
- The categories are ranked in the order of the following table:
- Beginner : 5
- Amateur : 10
- Candidate Master : 20
- Master : 40
- International Master : 80
- Grandmaster : 160
- The score for each game is calculated by multiplying the playing level with the score of the category.
- The engines are divided into groups.
- To be able to play with an opponent of a particular group a minimum point score is required. The required score is shown next to the group label.
")
+ txt = _("
The aim is to obtain the highest possible score :- The current point score is displayed in the title bar.
- To obtain points it is necessary to win on different levels in different categories.
- To overcome a level it is necessary to win against the engine with white and with black.
- The categories are ranked in the order of the following table:
- Beginner : 5
- Amateur : 10
- Candidate Master : 20
- Master : 40
- International Master : 80
- Grandmaster : 160
- The score for each game is calculated by multiplying the playing level with the score of the category.
- The engines are divided into groups.
- To be able to play with an opponent of a particular group a minimum point score is required. The required score is shown next to the group label.
")
Info.info(wParent, _("Lucas Chess"), titulo, txt, ancho, Iconos.pmAyudaGR())
return None
diff --git a/Code/QT/FormLayout.py b/Code/QT/FormLayout.py
index 8d126da..eb29f48 100644
--- a/Code/QT/FormLayout.py
+++ b/Code/QT/FormLayout.py
@@ -64,10 +64,12 @@ def __init__(self, label, minimo, maximo, ancho, chlabel):
class Combobox:
- def __init__(self, label, lista):
+ def __init__(self, label, lista, si_editable=False, tooltip=None):
self.tipo = COMBOBOX
self.lista = lista # (clave,titulo),....
self.label = label + ":"
+ self.si_editable = si_editable
+ self.tooltip = tooltip
class FontCombobox:
@@ -422,6 +424,11 @@ def setup(self, dispatch):
field.valueChanged.connect(dispatch)
elif tipo == COMBOBOX:
field = Controles.CB(self, config.lista, value)
+ if config.si_editable:
+ field.setEditable(True)
+ if config.tooltip:
+ field.setToolTip(config.tooltip)
+
field.lista = config.lista
if dispatch:
field.currentIndexChanged.connect(dispatch)
diff --git a/Code/QT/InfoBase.py b/Code/QT/InfoBase.py
index c7a9994..3497ce8 100644
--- a/Code/QT/InfoBase.py
+++ b/Code/QT/InfoBase.py
@@ -59,7 +59,7 @@ def listaMotores(self, bloque):
["Critter 1.6a 32bits", "Richard Vida", "http://www.vlasak.biz/critter/"],
["Texel 1.05", "Peter Österlund", "http://web.comhem.se/petero2home/javachess/index.html#texel"],
["Stockfish 8", "Tord Romstad, Marco Costalba, Joona Kiiski", "http://stockfishchess.org/"],
- ["Deepfish 4.1", "Tord Romstad, Marco Costalba, Joona Kiiski, fork by Marco Zerbinati", "https://github.com/Zerbinati/DeepFishMZ"],
+ ["McBrain 2.1a", "Michael Byrne (based on stockfish)", "https://github.com/MichaelB7/Stockfish/releases"],
["Gull 3", "Vadim Demichev", "https://sourceforge.net/projects/gullchess/"],
]
li.sort(key=lambda x: x[0])
@@ -110,7 +110,7 @@ def version(num, liBase, liResto):
return txt
# Version 10
- liBase = ["Remes", "Max Aloyau", "Alfonso Solbes", "tico-tico"]
+ liBase = ["Remes", "Max Aloyau", "Alfonso Solbes", "tico-tico", "Nils Andersson", "Bernhard"]
liResto = ["Immortalchess forum", ]
txt += version(10, liBase, liResto)
diff --git a/Code/QT/Pantalla.py b/Code/QT/Pantalla.py
index 49ff25d..378bb68 100644
--- a/Code/QT/Pantalla.py
+++ b/Code/QT/Pantalla.py
@@ -184,8 +184,11 @@ def changeEvent(self, event):
def muestraVariantes(self, titulo):
flags = QtCore.Qt.Dialog | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowMinimizeButtonHint | QtCore.Qt.WindowMaximizeButtonHint
+
self.setWindowFlags(flags)
+
self.setWindowTitle(titulo if titulo else "-")
+
return self.exec_()
def ajustaTam(self):
diff --git a/Code/QT/PantallaAnalisisParam.py b/Code/QT/PantallaAnalisisParam.py
index d429eb7..413d93f 100644
--- a/Code/QT/PantallaAnalisisParam.py
+++ b/Code/QT/PantallaAnalisisParam.py
@@ -181,7 +181,7 @@ def paramAnalisis(parent, configuracion, siModoAmpliado, siTodosMotores=False):
liGen.append((config, defecto))
liGen.append(SEPARADOR)
- liGen.append((_("To redo any existing prior analyses (if they exist)") + ":", alm.siBorrarPrevio))
+ liGen.append((_("Redo any existing prior analyses (if they exist)") + ":", alm.siBorrarPrevio))
liGen.append((_("Start from the end of the game") + ":", alm.desdeelfinal))
diff --git a/Code/QT/PantallaAperturas.py b/Code/QT/PantallaAperturas.py
index 9842b9c..5f71275 100644
--- a/Code/QT/PantallaAperturas.py
+++ b/Code/QT/PantallaAperturas.py
@@ -353,6 +353,8 @@ def nueva(self):
bloque = self.editar(None)
if bloque:
self.liBloques.append(bloque)
+ if not self.edNombre.texto().strip():
+ self.edNombre.ponTexto(bloque.trNombre)
self.grid.refresh()
self.grid.gobottom()
@@ -382,16 +384,19 @@ def borrar(self):
self.grid.refresh()
def aceptar(self):
- self.nombre = self.edNombre.texto().strip()
-
- if not self.nombre:
- QTUtil2.mensError(self, _("Not indicated the name of training"))
- return
-
if not self.liBloques:
QTUtil2.mensError(self, _("you have not indicated any opening"))
return
+ self.nombre = self.edNombre.texto().strip()
+ if not self.nombre:
+ if len(self.liBloques) == 1:
+ self.nombre = self.liBloques[0].trNombre
+ else:
+ QTUtil2.mensError(self, _("Not indicated the name of training"))
+ return
+
+
self.accept()
def cancelar(self):
diff --git a/Code/QT/PantallaEntMaq.py b/Code/QT/PantallaEntMaq.py
index 4c65ff7..5d056d1 100644
--- a/Code/QT/PantallaEntMaq.py
+++ b/Code/QT/PantallaEntMaq.py
@@ -357,7 +357,7 @@ def cambiadoDepth(self, num):
self.edRtiempo.setEnabled(num == 0)
def posicionEditar(self):
- resp = Voyager.voyagerFEN(self, self.fen)
+ resp = Voyager.voyagerFEN(self, self.fen, wownerowner=self.procesador.pantalla)
if resp is not None:
self.fen = resp
self.muestraPosicion()
diff --git a/Code/QT/PantallaManualSave.py b/Code/QT/PantallaManualSave.py
index e466e2b..9cc4390 100644
--- a/Code/QT/PantallaManualSave.py
+++ b/Code/QT/PantallaManualSave.py
@@ -91,7 +91,7 @@ def __init__(self, procesador):
self.bt_fns = Controles.PB(self, "", self.fns_select, plano=False).anchoMinimo(300)
bt_no_fns = Controles.PB(self, "", self.fns_unselect).ponIcono(Iconos.Delete()).anchoFijo(16)
## Codec
- lb_codec = Controles.LB(self, _("Write with the codec") + ": ")
+ lb_codec = Controles.LB(self, _("Encoding") + ": ")
liCodecs = [k for k in set(v for k, v in encodings.aliases.aliases.iteritems())]
liCodecs.sort()
liCodecs = [(k, k) for k in liCodecs]
@@ -366,7 +366,7 @@ def write_file(fich, f, txt, quien):
def change_position(self):
prev = self.analyzing
self.stop()
- fen = Voyager.voyagerFEN(self, self.posicion.fen())
+ fen = Voyager.voyagerFEN(self, self.posicion.fen(), wownerowner=self.procesador.pantalla)
if fen is not None:
self.em_solucion.ponTexto("")
self.posicion.leeFen(fen)
@@ -378,12 +378,13 @@ def change_position(self):
self.start()
def reset_motor(self):
+ clave = self.cb_engine.valor()
+ if not clave:
+ return
self.analyzing = False
if self.gestor_motor:
self.gestor_motor.terminar()
self.stop()
-
- clave = self.cb_engine.valor()
conf_motor = self.configuracion.buscaRivalExt(clave)
multipv = self.sb_multipv.valor()
@@ -396,7 +397,7 @@ def ext_engines(self):
valor = self.cb_engine.valor()
liMotores = self.configuracion.comboMotoresCompleto()
motor = self.configuracion.tutor.clave
- for clave, rotulo in liMotores:
+ for rotulo, clave in liMotores:
if clave == valor:
motor = valor
break
diff --git a/Code/QT/PantallaRoutes.py b/Code/QT/PantallaRoutes.py
index 5472e0b..c307b84 100644
--- a/Code/QT/PantallaRoutes.py
+++ b/Code/QT/PantallaRoutes.py
@@ -20,7 +20,8 @@ def __init__(self, procesador):
self.procesador = procesador
wsvg = QtSvg.QSvgWidget()
- wsvg.load(QtCore.QByteArray(self.route.get_txt()))
+ x = self.route.get_txt().encode("utf-8")
+ wsvg.load(QtCore.QByteArray(x))
wsvg.setFixedSize(762, 762.0 * 658.0 / 1148.0)
lySVG = Colocacion.H().relleno(1).control(wsvg).relleno(1)
diff --git a/Code/QT/PantallaSavePGN.py b/Code/QT/PantallaSavePGN.py
index 9290337..79df016 100644
--- a/Code/QT/PantallaSavePGN.py
+++ b/Code/QT/PantallaSavePGN.py
@@ -49,7 +49,7 @@ def __init__(self, owner, pgn, configuracion):
self.bt_file = Controles.PB(self, "", self.file_select, plano=False).anchoMinimo(300)
# Codec
- lb_codec = Controles.LB(self, _("Write with the codec") + ": ")
+ lb_codec = Controles.LB(self, _("Encoding") + ": ")
liCodecs = [k for k in set(v for k, v in encodings.aliases.aliases.iteritems())]
liCodecs.sort()
liCodecs = [(k, k) for k in liCodecs]
diff --git a/Code/QT/PantallaSolo.py b/Code/QT/PantallaSolo.py
index ca4386b..cca20fa 100644
--- a/Code/QT/PantallaSolo.py
+++ b/Code/QT/PantallaSolo.py
@@ -1,3 +1,5 @@
+from Code import TrListas
+
from Code.QT import Colocacion
from Code.QT import Columnas
from Code.QT import Controles
@@ -5,8 +7,8 @@
from Code.QT import Grid
from Code.QT import Iconos
from Code.QT import QTVarios
-from Code import TrListas
-from Code import Util
+from Code.QT import FormLayout
+
class WEtiquetasPGN(QTVarios.WDialogo):
@@ -45,17 +47,13 @@ def __init__(self, procesador, liPGN):
self.recuperarVideo()
def creaLista(self, liPGN):
- sd = Util.SymbolDict()
- for eti, val in liPGN:
- sd[eti] = val
+ st = {eti for eti, val in liPGN}
- li = []
+ li = liPGN[:]
listandard = ("Event", "Site", "Date", "Round", "White", "Black", "Result", "ECO", "WhiteElo", "BlackElo")
for eti in listandard:
- li.append([eti, sd.get(eti,"")])
- for eti, val in liPGN:
- if eti not in listandard:
- li.append([eti,val])
+ if eti not in st:
+ li.append([eti, ""])
while len(li) < 30:
li.append(["", ""])
self.liPGN = li
@@ -119,3 +117,127 @@ def editarEtiquetasPGN(procesador, liPGN):
return li
else:
return None
+
+
+def massive_change_tags(owner, configuracion, num_selected):
+ APPLY_ALL, APPLY_SELECTED = range(2)
+ SAVE_NOTHING, SAVE_LABELS, SAVE_LABELS_VALUES = range(3)
+ NUM_OTHERS = 4
+
+ dic = configuracion.leeVariables("MASSIVE_CHANGE_TAGS")
+ if not dic:
+ dic = {}
+
+ liBase = []
+ sep = (None, None)
+
+ def sepBase():
+ liBase.append(sep)
+
+ sepBase()
+
+ liBase.append((None, _("Basic tags")))
+ liBase.append(("%s:" % _("Event"), dic.get("EVENT", "")))
+ liBase.append(("%s:" % _("Site"), dic.get("SITE", "")))
+ liBase.append(("%s:" % _("Date"), dic.get("DATE", "")))
+
+ sepBase()
+
+ liBaseOther = ["Round", "White", "Black", "Result", "WhiteTitle", "BlackTitle", "WhiteElo", "BlackElo",
+ "WhiteUSCF", "BlackUSCF", "WhiteNA", "BlackNA", "WhiteType", "BlackType", "EventDate",
+ "EventSponsor", "Section", "Stage", "Board", "Opening", "Variation", "SubVariation",
+ "ECO", "Time", "UTCTime", "UTCDate", "TimeControl", "SetUp", "Termination"]
+ li0 = ["", "Event", "Site", "Date"]
+ li0.extend(liBaseOther)
+ li = [[uno, uno] for uno in li0]
+ combo = FormLayout.Combobox(_("Remove the tag (in English)"), li, si_editable=True)
+ liBase.append((combo, ""))
+
+ sepBase()
+
+ liBase.append((None, _("Configuration")))
+
+ liA = [(_("All read"), APPLY_ALL), ("%s [%d]"%(_("Only selected"), num_selected), APPLY_SELECTED)]
+ config = FormLayout.Combobox(_("Apply to"), liA)
+ liBase.append((config, dic.get("APPLY", APPLY_SELECTED if num_selected > 1 else APPLY_ALL)))
+ sepBase()
+
+ liBase.append((_("Overwrite"), dic.get("OVERWRITE", True)))
+ sepBase()
+
+ liS = [(_("Nothing"), SAVE_NOTHING),
+ (_("Labels"), SAVE_LABELS),
+ ("%s+%s" % (_("Labels"), _("Values")), SAVE_LABELS_VALUES)
+ ]
+ config = FormLayout.Combobox(_("Save as default"), liS)
+ liBase.append((config, dic.get("SAVE", SAVE_LABELS_VALUES)))
+
+
+ liOther = [sep]
+
+ for x in range(NUM_OTHERS):
+ li = [[uno, uno] for uno in liBaseOther]
+ previo = dic.get("OTHERS_TAG_%d" % x, "")
+ li.insert(0, [previo, previo])
+ if previo:
+ li.insert(0, ["", ""])
+
+ combo = FormLayout.Combobox("%s %d" % (_("Tag"), x + 1), li, si_editable=True)
+ liOther.append((combo, previo))
+ liOther.append(("%s %d:" % (_("Value"), x+1), dic.get("OTHERS_VALUE_%d" % x, "")))
+ liOther.append(sep)
+
+ liOther.append((None, "** %s" % _("All official tags must be indicated with their name in English.")))
+
+
+ lista = []
+ lista.append((liBase, _("Base"), ""))
+ lista.append((liOther, _("Others"), ""))
+
+ # Editamos
+ resultado = FormLayout.fedit(lista, title=_("Massive change of tags"), parent=owner, anchoMinimo=640, icon=Iconos.PGN())
+ if resultado:
+ accion, resp = resultado
+ liBase, liOther = resp
+
+ dic = {}
+ dic["EVENT"], dic["SITE"], dic["DATE"], dic["REMOVE"], dic["APPLY"], dic["OVERWRITE"], dic["SAVE"] = liBase
+
+ liTags = []
+ for tag in ("Event", "Site", "Date"):
+ tagu = tag.upper()
+ if dic[tagu]:
+ liTags.append((tag, dic[tagu]))
+
+ for x in range(0, NUM_OTHERS*2, 2):
+ tag = liOther[x]
+ if tag and tag.upper!= "FEN":
+ val = liOther[x + 1]
+ ntag = x / 2
+ dic["OTHERS_TAG_%d" % ntag] = tag
+ dic["OTHERS_VALUE_%d" % ntag] = val
+ if val:
+ liTags.append((tag, val))
+
+ save = dic["SAVE"]
+
+ if save == SAVE_NOTHING or save == SAVE_LABELS:
+ for x in ("EVENT", "SITE", "DATE"):
+ del dic[x]
+ for x in range(NUM_OTHERS):
+ key = "OTHERS_VALUE_%d" % x
+ if key in dic:
+ del dic[key]
+ if save == SAVE_NOTHING:
+ key = "OTHERS_TAG_%d" % x
+ if key in dic:
+ del dic[key]
+
+ configuracion.escVariables("MASSIVE_CHANGE_TAGS", dic)
+
+ if liTags or dic["REMOVE"]:
+ return (liTags, dic["REMOVE"], dic["OVERWRITE"], dic["APPLY"] == APPLY_ALL)
+
+ return None
+
+
diff --git a/Code/QT/PantallaTorneos.py b/Code/QT/PantallaTorneos.py
index 53aa27e..5a65efb 100644
--- a/Code/QT/PantallaTorneos.py
+++ b/Code/QT/PantallaTorneos.py
@@ -657,6 +657,9 @@ def gmCrear(self):
liGen.append((None, None))
liGen.append((_("Select all"), False))
+ liGen.append((None, None))
+ liGen.append((_("Random order"), True))
+
reg = Util.Almacen()
reg.form = None
@@ -695,6 +698,8 @@ def dispatch(valor):
if si:
liSel.append(en.huella())
+ rnd = liResp[-1]
+
self.configuracion.escVariables("crear_torneo", dicValores)
nSel = len(liSel)
@@ -707,7 +712,8 @@ def dispatch(valor):
for y in range(x + 1, nSel):
self.torneo.nuevoGame(liSel[x], liSel[y], minutos, segundos)
self.torneo.nuevoGame(liSel[y], liSel[x], minutos, segundos)
- self.torneo.randomize()
+ if rnd:
+ self.torneo.randomize()
self.gridGames.refresh()
self.gridGames.gobottom()
diff --git a/Code/QT/PantallaWashing.py b/Code/QT/PantallaWashing.py
index dc9bab8..38f55f7 100644
--- a/Code/QT/PantallaWashing.py
+++ b/Code/QT/PantallaWashing.py
@@ -206,7 +206,7 @@ def file(self):
menu.opcion(fich, fich, Iconos.PuntoRojo())
resp = menu.lanza()
if resp:
- if QTUtil2.pregunta(self, "%s\n%s" % ( _("Current data will be removed and overwrited."),
+ if QTUtil2.pregunta(self, "%s\n%s" % ( _("Current data will be removed and overwritten."),
_("Are you sure?")) ):
shutil.copy(os.path.join(self.configuracion.carpeta, resp+".wsm"), self.dbwashing.file)
self.wreload = True
@@ -214,7 +214,7 @@ def file(self):
self.accept()
elif resp.startswith("new_"):
tactic = resp[4:]
- if QTUtil2.pregunta(self, "%s\n%s" % ( _("Current data will be removed and overwrited."),
+ if QTUtil2.pregunta(self, "%s\n%s" % ( _("Current data will be removed and overwritten."),
_("Are you sure?")) ):
self.dbwashing.new(tactic)
self.wreload = True
diff --git a/Code/QT/PantallaWorkMap.py b/Code/QT/PantallaWorkMap.py
index f0d44fd..3123161 100644
--- a/Code/QT/PantallaWorkMap.py
+++ b/Code/QT/PantallaWorkMap.py
@@ -4,6 +4,7 @@
from Code import ControlPosicion
from Code import Jugada
from Code import Partida
+from Code import TrListas
from Code.QT import Colocacion
from Code.QT import Columnas
from Code.QT import Controles
@@ -19,9 +20,9 @@
class WMap(QTVarios.WDialogo):
def __init__(self, procesador, mapa):
-
self.workmap = WorkMap.WorkMap(mapa)
- titulo = _F(mapa)
+ dic = TrListas.maps()
+ titulo = dic[mapa]
icono = getattr(Iconos, mapa)()
QTVarios.WDialogo.__init__(self, procesador.pantalla, titulo, icono, mapa)
diff --git a/Code/QT/QTVarios.py b/Code/QT/QTVarios.py
index 88100c6..3e3faf9 100644
--- a/Code/QT/QTVarios.py
+++ b/Code/QT/QTVarios.py
@@ -1022,7 +1022,7 @@ def __init__(self, parent, titulo, siErroneos, icono):
self.lbRotDuplicados = Controles.LB(self, _("Duplicated") + ":").ponFuente(f)
self.lbDuplicados = Controles.LB(self, "0").ponFuente(f)
- lbRotImportados = Controles.LB(self, _("Imported") + ":").ponFuente(f)
+ self.lbRotImportados = lbRotImportados = Controles.LB(self, _("Imported") + ":").ponFuente(f)
self.lbImportados = Controles.LB(self, "0").ponFuente(f)
self.btCancelarSeguir = Controles.PB(self, _("Cancel"), self.cancelar, plano=False).ponIcono(Iconos.Delete())
@@ -1052,6 +1052,9 @@ def cancelar(self):
self.siCancelado = True
self.ponContinuar()
+ def ponExportados(self):
+ self.lbRotImportados.ponTexto(_("Exported") + ":")
+
def ponSaving(self):
self.btCancelarSeguir.setDisabled(True)
self.btCancelarSeguir.ponTexto(_("Saving..."))
diff --git a/Code/QT/Voyager.py b/Code/QT/Voyager.py
index 48ec282..54c448d 100644
--- a/Code/QT/Voyager.py
+++ b/Code/QT/Voyager.py
@@ -380,7 +380,7 @@ def scanner(self):
pos = QTUtil.escondeWindow(self.wparent)
seguir = True
if self.chb_scanner_ask.valor() and not QTUtil2.pregunta(None, _("Bring the window to scan to front"),
- etiSi=_("Capture"), etiNo=_("Cancel"), si_top=True):
+ etiSi=_("Accept"), etiNo=_("Cancel"), si_top=True):
seguir = False
if seguir:
fich_png = self.configuracion.ficheroTemporal("png")
@@ -800,13 +800,21 @@ def cancelar(self):
self.reject()
-def voyagerFEN(wowner, fen):
- pos = QTUtil.escondeWindow(wowner)
+def voyagerFEN(wowner, fen, si_esconde=True, wownerowner=None):
+ if si_esconde:
+ pos = QTUtil.escondeWindow(wowner)
+ if wownerowner:
+ pos_ownerowner = QTUtil.escondeWindow(wownerowner)
partida = Partida.Partida(fen=fen)
dlg = Voyager(wowner, False, partida)
resp = dlg.resultado if dlg.exec_() else None
- wowner.move(pos)
- wowner.show()
+ if si_esconde:
+ if wownerowner:
+ wownerowner.move(pos_ownerowner)
+ wownerowner.show()
+ wowner.move(pos)
+ wowner.show()
+
return resp
diff --git a/Code/QT/WBG_Games.py b/Code/QT/WBG_Games.py
index acc0e9e..2ca7192 100644
--- a/Code/QT/WBG_Games.py
+++ b/Code/QT/WBG_Games.py
@@ -5,6 +5,8 @@
from Code import Partida
from Code import DBgames
+from Code import TrListas
+from Code import Util
from Code.QT import Colocacion
from Code.QT import Columnas
from Code.QT import Controles
@@ -14,8 +16,7 @@
from Code.QT import PantallaPGN
from Code.QT import QTUtil2
from Code.QT import QTVarios
-from Code import TrListas
-from Code import Util
+from Code.QT import PantallaSolo
class WGames(QtGui.QWidget):
@@ -39,6 +40,8 @@ def __init__(self, procesador, winBookGuide, dbGames, wsummary, siMoves=True):
self.liFiltro = []
self.where = None
+ self.last_opening = None
+
# Grid
oColumnas = Columnas.ListaColumnas()
oColumnas.nueva("numero", _("N."), 70, siCentrado=True)
@@ -46,8 +49,7 @@ def __init__(self, procesador, winBookGuide, dbGames, wsummary, siMoves=True):
ancho = 70
for clave in liBasic:
rotulo = TrListas.pgnLabel(clave)
- siCentrado = clave != "EVENT"
- oColumnas.nueva(clave, rotulo, ancho, siCentrado=siCentrado)
+ oColumnas.nueva(clave, rotulo, ancho, siCentrado=True)
self.grid = Grid.Grid(self, oColumnas, siSelecFilas=True, siSeleccionMultiple=True, xid="wgames")
@@ -65,6 +67,7 @@ def __init__(self, procesador, winBookGuide, dbGames, wsummary, siMoves=True):
(_("Last"), Iconos.Final(), self.tw_gobottom), None,
(_("Filter"), Iconos.Filtrar(), self.tw_filtrar), None,
(_("Remove"), Iconos.Borrar(), self.tw_borrar),None,
+ (_("Utilities"), Iconos.Utilidades(), self.tw_utilities), None,
]
self.tbWork = Controles.TBrutina(self, liAccionesWork, tamIcon=24)
@@ -198,7 +201,7 @@ def actualiza(self, siObligatorio=False):
self.gridCambiadoRegistro(None, recno, None)
def gridCambiadoRegistro(self, grid, fila, oCol):
- if fila >= 0:
+ if self.gridNumDatos(grid) > fila >= 0:
pv = self.dbGames.damePV(fila)
p = Partida.Partida()
p.leerPV(pv)
@@ -220,6 +223,7 @@ def editar(self, recno, partidaCompleta):
QTUtil2.mensError(self, _("This game already exists."))
else:
self.actualiza(True)
+ self.grid.goto(recno, 0)
def tw_nuevo(self):
recno = None
@@ -263,10 +267,10 @@ def raw_sql():
def opening():
me = QTUtil2.unMomento(self)
import Code.QT.PantallaAperturas as PantallaAperturas
- w = PantallaAperturas.WAperturas(self, self.configuracion, "")
+ w = PantallaAperturas.WAperturas(self, self.configuracion, self.last_opening)
me.final()
if w.exec_():
- ap = w.resultado()
+ self.last_opening = ap = w.resultado()
pv = getattr(ap, "a1h8", "")
self.dbGames.filterPV(pv)
self.numJugada = pv.count(" ")
@@ -321,6 +325,8 @@ def tg_file(self):
submenu.opcion(self.tg_importar_PGN, _("A PGN file"), Iconos.FichPGN())
submenu.separador()
submenu.opcion(self.tg_importar_DB, _("Other database"), Iconos.DatabaseC())
+ submenu.separador()
+ submenu.opcion(self.tg_importar_pks, _("A PKS file"), Iconos.JuegaSolo())
menu.separador()
submenu = menu.submenu(_("Export to"), Iconos.DatabaseMas())
@@ -329,20 +335,57 @@ def tg_file(self):
submenu.opcion(self.tg_exportar_DB, _("Other database"), Iconos.DatabaseC())
menu.separador()
- submenu = menu.submenu(_("Utilities"), Iconos.Utilidades())
+ resp = menu.lanza()
+ if resp:
+ resp()
+
+ def tw_utilities(self):
+ menu = QTVarios.LCMenu(self)
ico = Iconos.PuntoAzul()
icoT = Iconos.Tacticas()
- menu1 = submenu.submenu(_("Polyglot book"), ico)
+ menu1 = menu.submenu(_("Polyglot book"), ico)
menu1.opcion(self.tw_uti_pcreate, _("Create a new book"), ico)
menu1.separador()
menu1.opcion(self.tw_uti_pmerge, _("Merge two books in one"), ico)
- submenu.separador()
- submenu.opcion(self.tw_uti_tactic, _("Create tactics training"), icoT)
-
+ menu.separador()
+ menu.opcion(self.tw_uti_tactic, _("Create tactics training"), icoT)
+ menu.separador()
+ menu.opcion(self.tw_massive_change_tags, _("Massive change of tags"), Iconos.PGN())
resp = menu.lanza()
if resp:
resp()
+ def tg_importar_pks(self):
+ path_pks = QTUtil2.leeFichero(self, self.configuracion.dirJS, "pks")
+ if path_pks:
+ direc = os.path.dirname(path_pks)
+ if direc != self.configuracion.dirJS:
+ self.configuracion.dirJS = direc
+ self.configuracion.graba()
+
+ mens_error = self.dbGames.insert_pks(path_pks)
+ if mens_error:
+ QTUtil2.mensError(self, mens_error)
+ return
+ self.actualiza(True)
+ self.grid.gobottom(0)
+
+ def tw_massive_change_tags(self):
+ resp = PantallaSolo.massive_change_tags(self, self.configuracion, len(self.grid.recnosSeleccionados()))
+ if resp:
+ recno = self.grid.recno()
+ liTags, remove, overwrite, si_all = resp
+ liRegistros = range(self.dbGames.reccount()) if si_all else self.grid.recnosSeleccionados()
+ nRegistros = len(liRegistros)
+ if (nRegistros == 1 or
+ ((nRegistros > 1) and
+ QTUtil2.pregunta(self, _("Are you sure do you want to change the %d registers?" % nRegistros)))):
+ um = QTUtil2.unMomento(self)
+ self.dbGames.massive_change_tags(liTags, liRegistros, remove, overwrite)
+ self.grid.refresh()
+ self.grid.goto(recno, 0)
+ um.final()
+
def tw_uti_pcreate(self):
PantallaBooks.polyglotCrear(self)
@@ -482,7 +525,7 @@ def tg_exportar_PGN(self):
try:
fpgn = codecs.open(pathPGN, modo, 'utf-8', 'ignore')
except:
- QTUtil2.mensError(self, "%s : %s\n" % (_("Unable to save"), pathPGN.replace("/", "\\")))
+ QTUtil2.mensError(self, "%s : %s\n" % (_("Unable to save"), pathPGN))
return
pb = QTUtil2.BarraProgreso1(self, _("Exporting..."))
@@ -502,7 +545,7 @@ def tg_exportar_PGN(self):
fpgn.close()
pb.cerrar()
- QTUtil2.mensaje(self, _X(_("Saved to %1"), pathPGN.replace("/", "\\")))
+ QTUtil2.mensaje(self, _X(_("Saved to %1"), pathPGN))
def tg_importar_PGN(self):
path = QTVarios.select_pgn(self)
@@ -530,18 +573,6 @@ def tg_importar_DB(self):
self.actualiza(True)
self.wsummary.reset()
- def tg_importarFEN(self):
- # Elegimos el fichero PGN
- path = QTVarios.select_pgn(self)
- if not path:
- return None
-
- dlTmp = QTVarios.ImportarFicheroPGN(self)
- dlTmp.show()
- self.dbGames.leerPGN(path, dlTmp)
-
- self.actualiza(True)
-
def changeDBgames(self, pathFich):
self.configuracion.ficheroDBgames = pathFich
self.configuracion.graba()
diff --git a/Code/QT/WBG_GamesFEN.py b/Code/QT/WBG_GamesFEN.py
index 4eea378..da70f6c 100644
--- a/Code/QT/WBG_GamesFEN.py
+++ b/Code/QT/WBG_GamesFEN.py
@@ -10,11 +10,11 @@
from Code.QT import Controles
from Code.QT import Grid
from Code.QT import Iconos
-from Code.QT import PantallaBooks
from Code.QT import PantallaPGN
from Code.QT import QTUtil2
from Code.QT import QTVarios
from Code.QT import Voyager
+from Code.QT import PantallaSolo
from Code import TrListas
from Code import Util
@@ -41,8 +41,6 @@ def __init__(self, procesador, winBookGuide, dbGamesFEN):
oColumnas.nueva("numero", _("N."), 70, siCentrado=True)
liBasic = dbGamesFEN.liCamposBase
for clave in liBasic:
- if clave == "FEN":
- continue
rotulo = TrListas.pgnLabel(clave)
siCentrado = clave != "EVENT"
@@ -65,6 +63,7 @@ def __init__(self, procesador, winBookGuide, dbGamesFEN):
(_("Last"), Iconos.Final(), self.tw_gobottom), None,
(_("Filter"), Iconos.Filtrar(), self.tw_filtrar), None,
(_("Remove"), Iconos.Borrar(), self.tw_borrar),None,
+ (_("Utilities"), Iconos.Utilidades(), self.tw_utilities), None,
]
self.tbWork = Controles.TBrutina(self, liAccionesWork, tamIcon=24)
@@ -80,6 +79,10 @@ def __init__(self, procesador, winBookGuide, dbGamesFEN):
self.setNameToolBar()
+ def reread(self):
+ self.dbGamesFEN.lee_rowids()
+ self.grid.refresh()
+
def limpiaColumnas(self):
for col in self.grid.oColumnas.liColumnas:
cab = col.cabecera
@@ -174,7 +177,7 @@ def tw_filtrar(self):
self.liFiltro = w.liFiltro
self.where = w.where()
- self.dbGames.filter(self.where)
+ self.dbGamesFEN.setFilter(self.where)
self.grid.refresh()
self.grid.gotop()
self.updateStatus()
@@ -187,16 +190,23 @@ def tw_gotop(self):
def tw_nuevo(self):
# Se genera un PGN
- fen = Voyager.voyagerFEN(self, "")
+ fen = Voyager.voyagerFEN(self, "", False)
if fen is not None:
- pgn = '[FEN "%s"]' % fen
+ if self.dbGamesFEN.si_existe_fen(fen):
+ QTUtil2.mensError(self, _("This position already exists."))
+ return
+ hoy = Util.hoy()
+ pgn = '[Date "%d.%02d.%02d"]\n[FEN "%s"]' % (hoy.year, hoy.month, hoy.day, fen)
nuevoPGN, pv, dicPGN = self.procesador.gestorUnPGN(self, pgn)
- if nuevoPGN:
- if not self.dbGamesFEN.cambiarUno(None, nuevoPGN, pv, dicPGN):
- QTUtil2.mensError(self, _("This position already exists."))
- else:
+ if dicPGN:
+ liTags = [(clave, valor) for clave, valor in dicPGN.iteritems()]
+ partida_completa = Partida.PartidaCompleta(fen=fen, liTags=liTags)
+ if pv:
+ partida_completa.leerPV(pv)
+ if self.dbGamesFEN.inserta(partida_completa):
self.actualiza()
+ self.grid.refresh()
self.grid.gobottom()
def tw_editar(self):
@@ -205,13 +215,19 @@ def tw_editar(self):
recno = li[0]
partidaCompleta = self.dbGamesFEN.leePartidaRecno(recno)
- partidaCompleta = self.procesador.gestorPartida(self, partidaCompleta, True)
- if partidaCompleta:
- if not self.dbGamesFEN.guardaPartidaRecno(recno, partidaCompleta):
- QTUtil2.mensError(self, _("This position already exists."))
- else:
- self.grid.refresh()
- self.updateStatus()
+ fen0 = partidaCompleta.iniPosicion.fen()
+ partidaCompleta = self.procesador.gestorPartida(self, partidaCompleta, False)
+ if partidaCompleta is not None:
+ fen1 = partidaCompleta.iniPosicion.fen()
+ if fen0 != fen1:
+ if self.dbGamesFEN.si_existe_fen(fen1):
+ QTUtil2.mensError(self, _("This position already exists."))
+ return
+
+ self.dbGamesFEN.guardaPartidaRecno(recno, partidaCompleta)
+ self.actualiza()
+ self.grid.refresh()
+ self.updateStatus()
def tw_borrar(self):
li = self.grid.recnosSeleccionados()
@@ -227,6 +243,13 @@ def tw_borrar(self):
um.final()
+ def tw_utilities(self):
+ menu = QTVarios.LCMenu(self)
+ menu.opcion(self.tg_massive_change_tags, _("Massive change of tags"), Iconos.PGN())
+ resp = menu.lanza()
+ if resp:
+ resp()
+
def tg_file(self):
menu = QTVarios.LCMenu(self)
@@ -239,6 +262,8 @@ def tg_file(self):
submenu.opcion(self.tg_importar_PGN, _("A PGN file"), Iconos.FichPGN())
submenu.separador()
submenu.opcion(self.tg_importar_DB, _("Other database"), Iconos.DatabaseC())
+ submenu.separador()
+ submenu.opcion(self.tg_importar_pks, _("A PKS file"), Iconos.JuegaSolo())
menu.separador()
submenu = menu.submenu(_("Export to"), Iconos.DatabaseMas())
@@ -251,28 +276,36 @@ def tg_file(self):
if resp:
resp()
- def tw_uti_pcreate(self):
- PantallaBooks.polyglotCrear(self)
-
- def tw_uti_pmerge(self):
- PantallaBooks.polyglotUnir(self)
-
- def tw_uti_tactic(self):
- dbf = self.dbGamesFEN.dbf
-
- def rutinaDatos(recno):
- dic = {}
- dbf.goto(recno)
- for clave in dbf.liCampos:
- dic[clave] = getattr(dbf.reg, clave)
- dic["PGN"] = Util.blob2var(dic["PGN"])
- return dic
+ def tg_importar_pks(self):
+ path_pks = QTUtil2.leeFichero(self, self.configuracion.dirJS, "pks")
+ if path_pks:
+ direc = os.path.dirname(path_pks)
+ if direc != self.configuracion.dirJS:
+ self.configuracion.dirJS = direc
+ self.configuracion.graba()
- liRegistros = self.grid.recnosSeleccionados()
- if len(liRegistros) < 2:
- liRegistros = range(dbf.reccount())
+ mens_error = self.dbGamesFEN.insert_pks(path_pks)
+ if mens_error:
+ QTUtil2.mensError(self, mens_error)
+ return
+ self.actualiza(True)
+ self.grid.gobottom(0)
- PantallaPGN.crearTactic(self.procesador, self, liRegistros, rutinaDatos)
+ def tg_massive_change_tags(self):
+ resp = PantallaSolo.massive_change_tags(self, self.configuracion, len(self.grid.recnosSeleccionados()))
+ if resp:
+ recno = self.grid.recno()
+ liTags, remove, overwrite, si_all = resp
+ liRegistros = range(self.dbGamesFEN.reccount()) if si_all else self.grid.recnosSeleccionados()
+ nRegistros = len(liRegistros)
+ if (nRegistros == 1 or
+ ((nRegistros > 1) and
+ QTUtil2.pregunta(self, _("Are you sure do you want to change the %d registers?" % nRegistros)))):
+ um = QTUtil2.unMomento(self)
+ self.dbGamesFEN.massive_change_tags(liTags, liRegistros, remove, overwrite)
+ self.reread()
+ self.grid.goto(recno, 0)
+ um.final()
def tg_change(self):
pathFich = QTUtil2.leeFichero(self, os.path.dirname(self.configuracion.ficheroDBgames), "lcf",
@@ -343,76 +376,44 @@ def tg_exportar_DB(self):
if modo == "w" and Util.existeFichero(path):
Util.borraFichero(path)
- Util.borraFichero(path+"_s1")
dlTmp = QTVarios.ImportarFicheroDB(self)
+ dlTmp.ponExportados()
dlTmp.show()
dbn = DBgamesFEN.DBgamesFEN(path)
dbn.appendDB(self.dbGamesFEN, li, dlTmp)
def tg_exportar_PGN(self):
- li = self.grid.recnosSeleccionados()
- if li:
- if len(li) > 1:
- menu = QTVarios.LCMenu(self)
- menu.opcion(True, _("All read"), Iconos.PuntoVerde())
- menu.separador()
- menu.opcion(False, _("Only selected"), Iconos.PuntoAzul())
- resp = menu.lanza()
- if resp is None:
- return
- siTodos = resp
- else:
- siTodos = True
-
- if siTodos:
- li = range(self.dbGamesFEN.reccount())
-
- # Fichero donde aadir
- pathPGN = QTUtil2.salvaFichero(self, _("Export"), self.configuracion.dirPGN,
- _("File") + " pgn (*.pgn)",
- False)
- if pathPGN:
- carpeta, nomf = os.path.split(pathPGN)
- if carpeta != self.configuracion.dirPGN:
- self.configuracion.dirPGN = carpeta
- self.configuracion.graba()
-
- # Grabamos
- modo = "w"
- if Util.existeFichero(pathPGN):
- yn = QTUtil2.preguntaCancelar(self,
- _X(_("The file %1 already exists, what do you want to do?"), pathPGN),
- si=_("Append"), no=_("Overwrite"))
- if yn is None:
- return
- if yn:
- modo = "a"
- try:
- fpgn = codecs.open(pathPGN, modo, 'utf-8', 'ignore')
- except:
- QTUtil2.mensError(self, "%s : %s\n" % (_("Unable to save"), pathPGN.replace("/", "\\")))
- return
-
- pb = QTUtil2.BarraProgreso1(self, _("Exporting..."))
- pb.mostrar()
- total = len(li)
- pb.ponTotal(total)
-
- if modo == "a":
- fpgn.write("\n\n")
- for n, recno in enumerate(li):
- pgn = self.dbGamesFEN.leePGNRecno(recno)
- pb.pon(n + 1)
- if pb.siCancelado():
- break
- fpgn.write(pgn)
- fpgn.write("\n\n")
-
- fpgn.close()
- pb.cerrar()
- QTUtil2.mensaje(self, _X(_("Saved to %1"), pathPGN.replace("/", "\\")))
+ resp = self.tg_exportar("pgn")
+ if not resp:
+ return
+ li, modo, path = resp
+
+ try:
+ fpgn = codecs.open(path, modo, 'utf-8', 'ignore')
+ except:
+ QTUtil2.mensError(self, "%s : %s\n" % (_("Unable to save"), path))
+ return
+
+ pb = QTUtil2.BarraProgreso1(self, _("Exporting..."))
+ pb.mostrar()
+ total = len(li)
+ pb.ponTotal(total)
+
+ if modo == "a":
+ fpgn.write("\n\n")
+ for n, recno in enumerate(li):
+ p = self.dbGamesFEN.leePartidaRecno(recno)
+ pb.pon(n + 1)
+ if pb.siCancelado():
+ break
+ fpgn.write(p.pgn())
+ fpgn.write("\n\n")
+
+ fpgn.close()
+ pb.cerrar()
+ QTUtil2.mensaje(self, _X(_("Saved to %1"), path))
def tg_importar_PGN(self):
path = QTVarios.select_pgn(self)
@@ -427,28 +428,16 @@ def tg_importar_PGN(self):
def tg_importar_DB(self):
path = QTVarios.select_ext(self, "lcf")
- if not path:
- return None
-
- dlTmp = QTVarios.ImportarFicheroDB(self)
- dlTmp.show()
-
- dbn = DBgamesFEN.DBgamesFEN(path)
- self.dbGamesFEN.appendDB(dbn, range(dbn.all_reccount()), dlTmp)
-
- self.actualiza(True)
-
- def tg_importarFEN(self):
- # Elegimos el fichero PGN
- path = QTVarios.select_pgn(self)
- if not path:
- return None
+ if path:
+ dlTmp = QTVarios.ImportarFicheroDB(self)
+ dlTmp.show()
- dlTmp = QTVarios.ImportarFicheroPGN(self)
- dlTmp.show()
- self.dbGamesFEN.leerPGN(path, dlTmp)
+ dbn = DBgamesFEN.DBgamesFEN(path)
+ dbn.lee_rowids()
+ liRecnos = range(dbn.reccount())
+ self.dbGamesFEN.appendDB(dbn, liRecnos, dlTmp)
- self.actualiza(True)
+ self.actualiza(True)
def changeDBgames(self, pathFich):
self.configuracion.ficheroDBgamesFEN = pathFich
diff --git a/Code/QT/WCapturas.py b/Code/QT/WCapturas.py
index f4888f0..72ed3c5 100644
--- a/Code/QT/WCapturas.py
+++ b/Code/QT/WCapturas.py
@@ -1,3 +1,5 @@
+DIVISOR = 12
+
from PyQt4 import QtCore, QtGui
from Code.QT import Colocacion
@@ -10,7 +12,7 @@ def __init__(self, wParent, tablero):
super(CapturaLista, self).__init__(wParent)
self.setFixedWidth(10)
- anchoPZ = int(tablero.ancho/12)
+ anchoPZ = int(tablero.ancho/DIVISOR)
self.pantalla = wParent.parent()
self.tipoMaterial = VarGen.configuracion.tipoMaterial
@@ -37,7 +39,7 @@ def mousePressEvent(self, event):
self.pantalla.activaCapturas(False)
def resetPZ(self, tablero):
- anchoPZ = int(tablero.ancho/12)
+ anchoPZ = int(tablero.ancho/DIVISOR)
for k, li in self.dic.iteritems():
for lb in li:
tablero.piezas.change_label(lb, anchoPZ)
diff --git a/Code/Routes.py b/Code/Routes.py
index adcc376..047682f 100644
--- a/Code/Routes.py
+++ b/Code/Routes.py
@@ -4,6 +4,7 @@
from Code import Partida
from Code import Util
+from Code import TrListas
class Reg:
@@ -37,7 +38,7 @@ def xpos(self):
@property
def name(self):
- return self._name
+ return _F(self._name)
class Line:
@@ -173,7 +174,11 @@ def read_level(self):
def read_svg(self, base):
with open(base % "svg", "rb") as f:
- return f.read()
+ x = f.read()
+ dic = TrListas.transsiberian()
+ for k, v in dic.iteritems():
+ x = x.replace(k, v)
+ return x
def read_dat(self, base):
lines = []
diff --git a/Code/Torneo.py b/Code/Torneo.py
index 8a8b14f..af9e3f1 100644
--- a/Code/Torneo.py
+++ b/Code/Torneo.py
@@ -259,7 +259,7 @@ def pgn(self, torneo):
base = self._partida.pgnBase()
- return cabecera + "\n" + base + " %s\n" % rs
+ return cabecera + "\n" + base + " %s\n\n" % rs
class Torneo:
@@ -456,16 +456,20 @@ def numGames(self):
def liGames(self):
return self._liGames
- def randomize(self, n=0):
- if n == 50:
- return
+ def randomize(self):
random.shuffle(self._liGames)
- prev = self._liGames[0]
- for gm in self._liGames[1:]:
- if gm.hwhite() == prev.hwhite() and gm.hblack() == prev.hblack():
- return self.randomize(n+1)
- prev = gm
- return
+ num_games = len(self._liGames)
+ for n in range(1, num_games-1):
+ gm1 = self._liGames[n]
+ gm0 = self._liGames[n-1]
+ if gm0.hwhite() == gm1.hwhite() or gm0.hblack() == gm1.hblack():
+ for pos in range(n+1, num_games):
+ gm2 = self._liGames[pos]
+ if not(gm2.hwhite() == gm1.hwhite() or gm2.hblack() == gm1.hblack()
+ or gm2.hwhite() == gm0.hwhite() or gm2.hblack() == gm0.hblack()):
+ self._liGames[pos] = gm1
+ self._liGames[n] = gm2
+ break
def delGames(self, lista):
li = []
diff --git a/Code/TrListas.py b/Code/TrListas.py
index 5f7c6dd..2580f59 100644
--- a/Code/TrListas.py
+++ b/Code/TrListas.py
@@ -2,29 +2,35 @@
def categoria(key):
- return {"PRINCIPIANTE": _("Beginner"),
+ return {
+ "FUTUROPRINCIPIANTE": _("Future beginner"),
+ "PRINCIPIANTE": _("Beginner"),
"AFICIONADO": _("Amateur"),
"CANDIDATOMAESTRO": _("Candidate Master"),
"MAESTRO": _("Master"),
"CANDIDATOGRANMAESTRO": _("International Master"),
"GRANMAESTRO": _("Grandmaster"),
- "ALUCINANTE": _("Mind-bending")
+ "ALUCINANTE": _("Mind-bending"),
}[key]
def pgnLabel(key):
- return {"EVENT": _("Event"),
- "SITE": _("Site"),
- "DATE": _("Date"),
- "ROUND": _("Round"),
- "WHITE": _("White"),
- "BLACK": _("Black"),
- "RESULT": _("Result"),
- "ECO": _("ECO"),
- "FEN": _("FEN"),
- "PLIES": _("Plies"),
- "WHITEELO": _("White elo"),
- "BLACKELO": _("Black elo")}.get(key, key)
+ if key:
+ return {"EVENT": _("Event"),
+ "SITE": _("Site"),
+ "DATE": _("Date"),
+ "ROUND": _("Round"),
+ "WHITE": _("White"),
+ "BLACK": _("Black"),
+ "RESULT": _("Result"),
+ "COMMENT": _("Comment"),
+ "ECO": _("ECO"),
+ "FEN": _("FEN"),
+ "PLIES": _("Plies"),
+ "WHITEELO": _("White elo"),
+ "BLACKELO": _("Black elo")}.get(key, _F(key))
+ else:
+ return ""
def dicNomPiezas():
@@ -2127,7 +2133,7 @@ def dicTraining():
"Tactics by UNED chess school": _("Tactics by UNED chess school"),
# "Decoy": _("Decoy"),
- "Interception-blocade": _("Interception - blocade"),
+ "Interception-blocade": _("Interception-blocade"),
# "Pawn promotion": _("Pawn promotion"),
"X-ray attack": _("X-ray attack"),
# "Pin": _("Pin"),
@@ -2194,4 +2200,167 @@ def MicElo():
_("very combative"),
_("very conservative"),
_("counterattacker"),
+ _("combative"),
+ _("extremely precise"),
+ _("wide repertoire"),
]
+
+
+def transsiberian():
+ return {
+ "Yaroslavl": _("Yaroslavl"),
+ "Kirov": _("Kirov"),
+ "Perm": _("Perm"),
+ "Ekaterinburg": _("Ekaterinburg"),
+ "MOSCOW": _("MOSCOW"),
+ "Tyumen": _("Tyumen"),
+ "Omsk": _("Omsk"),
+ "Novosibirsk": _("Novosibirsk"),
+ "Krasnoyarsk": _("Krasnoyarsk"),
+ "Tayshet": _("Tayshet"),
+ "Irkutsk": _("Irkutsk"),
+ "Ulan-Ude": _("Ulan-Ude"),
+ "Chita": _("Chita"),
+ "Skovrodino": _("Skovrodino"),
+ "Belogorsk": _("Belogorsk"),
+ "Khabarovsk": _("Khabarovsk"),
+ "Vladivostok": _("Vladivostok"),
+ "Moscow": _("Moscow"),
+ "Khotkovo": _("Khotkovo"),
+ "Sergiyev Posad": _("Sergiyev Posad"),
+ "Alexandrov": _("Alexandrov"),
+ "Balakirevo": _("Balakirevo"),
+ "Berendeevo": _("Berendeevo"),
+ "Petrovskoye": _("Petrovskoye"),
+ "Rostov Yaroslavsky": _("Rostov Yaroslavsky"),
+ "Danilov": _("Danilov"),
+ "Lyubim": _("Lyubim"),
+ "Bui": _("Bui"),
+ "Galich": _("Galich"),
+ "Manturovo": _("Manturovo"),
+ "Sharya": _("Sharya"),
+ "Svetcha": _("Svetcha"),
+ "Kotelnich": _("Kotelnich"),
+ "Pozdino": _("Pozdino"),
+ "Bum-Kombinat": _("Bum-Kombinat"),
+ "Zuevka": _("Zuevka"),
+ "Yar": _("Yar"),
+ "Glazov": _("Glazov"),
+ "Balyezino": _("Balyezino"),
+ "Chepsta": _("Chepsta"),
+ "Vereshchagino": _("Vereshchagino"),
+ "Mendeleevo": _("Mendeleevo"),
+ "Chaikovskaya": _("Chaikovskaya"),
+ "Overyata": _("Overyata"),
+ "Ferma": _("Ferma"),
+ "Kungur": _("Kungur"),
+ "Shalya": _("Shalya"),
+ "Kuzino": _("Kuzino"),
+ "Krylosovo": _("Krylosovo"),
+ "Pervouralsk": _("Pervouralsk"),
+ "Yekaterinburg": _("Yekaterinburg"),
+ "Bogdanovich": _("Bogdanovich"),
+ "Kamyshlov": _("Kamyshlov"),
+ "Talitsa": _("Talitsa"),
+ "Yushala": _("Yushala"),
+ "Yalutorovsk": _("Yalutorovsk"),
+ "Ishim": _("Ishim"),
+ "Nazyvayevsk": _("Nazyvayevsk"),
+ "Kalachinsk": _("Kalachinsk"),
+ "Tatarsk": _("Tatarsk"),
+ "Barabinsk": _("Barabinsk"),
+ "Chulym": _("Chulym"),
+ "Ob": _("Ob"),
+ "Bolotnaya": _("Bolotnaya"),
+ "Yurga": _("Yurga"),
+ "Tayga": _("Tayga"),
+ "Anzhero-Sudzhensk": _("Anzhero-Sudzhensk"),
+ "Mariinsk": _("Mariinsk"),
+ "Bogotol": _("Bogotol"),
+ "Achinsk": _("Achinsk"),
+ "Chernorechensk": _("Chernorechensk"),
+ "Uyar": _("Uyar"),
+ "Zaozyornaya": _("Zaozyornaya"),
+ "Kansk-Yeniseysky": _("Kansk-Yeniseysky"),
+ "Ilanskaya": _("Ilanskaya"),
+ "Taishet": _("Taishet"),
+ "Razgon": _("Razgon"),
+ "Kamyshet": _("Kamyshet"),
+ "Nizhneudinsk": _("Nizhneudinsk"),
+ "Tulun": _("Tulun"),
+ "Kuytun": _("Kuytun"),
+ "Zima": _("Zima"),
+ "Kutulik": _("Kutulik"),
+ "Cheremkhovo": _("Cheremkhovo"),
+ "Polovina": _("Polovina"),
+ "Usolye-Sibirskoye": _("Usolye-Sibirskoye"),
+ "Telma": _("Telma"),
+ "Angarsk": _("Angarsk"),
+ "Meget": _("Meget"),
+ "Irkutsk-Sort": _("Irkutsk-Sort"),
+ "Slyudyanka": _("Slyudyanka"),
+ "Baykalsk": _("Baykalsk"),
+ "Vydrino": _("Vydrino"),
+ "Tankhoi": _("Tankhoi"),
+ "Mysovaya": _("Mysovaya"),
+ "Posolskaya": _("Posolskaya"),
+ "Selenginsk": _("Selenginsk"),
+ "Ulan Ude": _("Ulan Ude"),
+ "Onokhoy": _("Onokhoy"),
+ "Novoilinski": _("Novoilinski"),
+ "Petrovsk-Zabaykalsky": _("Petrovsk-Zabaykalsky"),
+ "Bada": _("Bada"),
+ "Khilok": _("Khilok"),
+ "Mogzon": _("Mogzon"),
+ "Sokhondo": _("Sokhondo"),
+ "Yablonovaya": _("Yablonovaya"),
+ "Darasun": _("Darasun"),
+ "Karymskaya": _("Karymskaya"),
+ "Onon": _("Onon"),
+ "Shilka-Pass.": _("Shilka-Pass."),
+ "Priiskovaya": _("Priiskovaya"),
+ "Kuenga": _("Kuenga"),
+ "Chernyshevsk-Zabaykalsky": _("Chernyshevsk-Zabaykalsky"),
+ "Bushuley": _("Bushuley"),
+ "Zilovo": _("Zilovo"),
+ "Ksenevskaya": _("Ksenevskaya"),
+ "Mogocha": _("Mogocha"),
+ "Amazar": _("Amazar"),
+ "Yerofei Pavlovich": _("Yerofei Pavlovich"),
+ "Urusha": _("Urusha"),
+ "Takhtamigda": _("Takhtamigda"),
+ "Skovorodino": _("Skovorodino"),
+ "Bolshoy Never": _("Bolshoy Never"),
+ "Magdagachi": _("Magdagachi"),
+ "Ushumun": _("Ushumun"),
+ "Shimanovskaya": _("Shimanovskaya"),
+ "Ledyanaya": _("Ledyanaya"),
+ "Svobodny": _("Svobodny"),
+ "Zavitaya": _("Zavitaya"),
+ "Bureya": _("Bureya"),
+ "Arkhara": _("Arkhara"),
+ "Obluchye": _("Obluchye"),
+ "Izvestkovaya": _("Izvestkovaya"),
+ "Bira": _("Bira"),
+ "Birobidzhan": _("Birobidzhan"),
+ "Volochayevka": _("Volochayevka"),
+ "Priamurskaya": _("Priamurskaya"),
+ "Verino": _("Verino"),
+ "Khor": _("Khor"),
+ "Vyazemskaya": _("Vyazemskaya"),
+ "Bikin": _("Bikin"),
+ "Dalnerechensk": _("Dalnerechensk"),
+ "Lazo": _("Lazo"),
+ "Spassk-Dalny": _("Spassk-Dalny"),
+ "Sibirtsevo": _("Sibirtsevo"),
+ "Ussuriysk": _("Ussuriysk"),
+ "Uglovaya": _("Uglovaya"),
+ }
+
+
+def maps():
+ return {
+ "Africa":_("Africa map"),
+ "WorldMap": _("World map"),
+ }
+
diff --git a/Code/Traducir.py b/Code/Traducir.py
index 43f38df..39c07fc 100644
--- a/Code/Traducir.py
+++ b/Code/Traducir.py
@@ -4,10 +4,12 @@
def _F(txt):
- return _(txt)
+ return _(txt) if txt else ""
def _SP(clave):
+ if not clave:
+ return ""
clave = clave.strip()
t = _F(clave)
if t == clave:
@@ -21,6 +23,8 @@ def _SP(clave):
def _X(clave, op1, op2=None, op3=None):
+ if not clave:
+ return ""
resp = clave.replace("%1", op1)
if op2:
resp = resp.replace("%2", op2)
diff --git a/Code/Util.py b/Code/Util.py
index ab78b37..435a307 100644
--- a/Code/Util.py
+++ b/Code/Util.py
@@ -454,8 +454,7 @@ def __init__(self, dic=None):
self.__setitem__(k, v)
def __contains__(self, clave):
- clu = clave.upper()
- return clu in self._dic
+ return clave.upper() in self._dic
def __len__(self):
return len(self._keys)
diff --git a/Code/XMotorRespuesta.py b/Code/XMotorRespuesta.py
index eda240d..f7f8710 100644
--- a/Code/XMotorRespuesta.py
+++ b/Code/XMotorRespuesta.py
@@ -824,10 +824,25 @@ def mejorMovAjustadoNivel(self, nTipo):
if sel <= t:
return k
- def mejorMovAjustadoSuperior(self, nivel, mindifpuntos, maxmate, aterrizaje):
-
+ def mejorMovAjustadoBlundersNegativo(self, mindifpuntos, maxmate):
+ rm0 = self.liMultiPV[0]
if self.mejorMovDetectaBlunders(None, mindifpuntos, maxmate):
- return self.liMultiPV[0]
+ return rm0
+ if rm0.puntosABS() < -10:
+ li = []
+ for rm in self.liMultiPV:
+ if rm.puntosABS() == rm0.puntosABS():
+ li.append(rm)
+ if len(li) == 1:
+ return rm0
+ else:
+ return random.choice(li)
+ return None
+
+ def mejorMovAjustadoSuperior(self, nivel, mindifpuntos, maxmate, aterrizaje):
+ resp = self.mejorMovAjustadoBlundersNegativo(mindifpuntos, maxmate)
+ if resp:
+ return resp
# Buscamos una jugada positiva que no sea de mate
# Si no la hay, cogemos el ultimo
@@ -859,9 +874,9 @@ def mejorMovAjustadoSuperior(self, nivel, mindifpuntos, maxmate, aterrizaje):
return li[0] if nLi < nivel else li[-nivel]
def mejorMovAjustadoInferior(self, nivel, mindifpuntos, maxmate, aterrizaje):
-
- if self.mejorMovDetectaBlunders(None, mindifpuntos, maxmate):
- return self.liMultiPV[0]
+ resp = self.mejorMovAjustadoBlundersNegativo(mindifpuntos, maxmate)
+ if resp:
+ return resp
# Buscamos una jugada positiva que no sea de mate
# Si no la hay, cogemos el ultimo
@@ -891,9 +906,9 @@ def mejorMovAjustadoInferior(self, nivel, mindifpuntos, maxmate, aterrizaje):
return li[-1] if nLi < nivel else li[nivel - 1]
def mejorMovAjustadoSimilar(self, mindifpuntos, maxmate, aterrizaje):
-
- if self.mejorMovDetectaBlunders(None, mindifpuntos, maxmate):
- return self.liMultiPV[0]
+ resp = self.mejorMovAjustadoBlundersNegativo(mindifpuntos, maxmate)
+ if resp:
+ return resp
# Buscamos una jugada positiva que no sea de mate
# Si no la hay, cogemos el ultimo
@@ -925,7 +940,6 @@ def mejorMovAjustadoSimilar(self, mindifpuntos, maxmate, aterrizaje):
def mejorMovAjustado(self, nTipo):
if self.liMultiPV:
-
rmSel = None
aterrizaje = 50
siPersonalidad = nTipo >= 1000 # Necesario para grabar los puntos
diff --git a/Engines/Windows/deepfish/srcD/book.cpp b/Engines/Windows/deepfish/srcD/book.cpp
deleted file mode 100644
index a0e5865..0000000
--- a/Engines/Windows/deepfish/srcD/book.cpp
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
-
- Stockfish is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Stockfish is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-/*
- The code in this file is based on the opening book code in PolyGlot
- by Fabien Letouzey. PolyGlot is available under the GNU General
- Public License, and can be downloaded from http://wbec-ridderkerk.nl
-*/
-
-#include
-#include
-
-#include "book.h"
-#include "misc.h"
-#include "movegen.h"
-
-using namespace std;
-
-namespace {
-
- // A Polyglot book is a series of "entries" of 16 bytes. All integers are
- // stored in big-endian format, with the highest byte first (regardless of
- // size). The entries are ordered according to the key in ascending order.
- struct Entry {
- uint64_t key;
- uint16_t move;
- uint16_t count;
- uint32_t learn;
- };
-
- // Random numbers from PolyGlot, used to compute book hash keys
- const union {
- Key PolyGlotRandoms[781];
- struct {
- Key psq[12][64]; // [piece][square]
- Key castling[4]; // [castling flag]
- Key enpassant[8]; // [file]
- Key turn;
- } Zobrist;
- } PG = {{
- 0x9D39247E33776D41ULL, 0x2AF7398005AAA5C7ULL, 0x44DB015024623547ULL,
- 0x9C15F73E62A76AE2ULL, 0x75834465489C0C89ULL, 0x3290AC3A203001BFULL,
- 0x0FBBAD1F61042279ULL, 0xE83A908FF2FB60CAULL, 0x0D7E765D58755C10ULL,
- 0x1A083822CEAFE02DULL, 0x9605D5F0E25EC3B0ULL, 0xD021FF5CD13A2ED5ULL,
- 0x40BDF15D4A672E32ULL, 0x011355146FD56395ULL, 0x5DB4832046F3D9E5ULL,
- 0x239F8B2D7FF719CCULL, 0x05D1A1AE85B49AA1ULL, 0x679F848F6E8FC971ULL,
- 0x7449BBFF801FED0BULL, 0x7D11CDB1C3B7ADF0ULL, 0x82C7709E781EB7CCULL,
- 0xF3218F1C9510786CULL, 0x331478F3AF51BBE6ULL, 0x4BB38DE5E7219443ULL,
- 0xAA649C6EBCFD50FCULL, 0x8DBD98A352AFD40BULL, 0x87D2074B81D79217ULL,
- 0x19F3C751D3E92AE1ULL, 0xB4AB30F062B19ABFULL, 0x7B0500AC42047AC4ULL,
- 0xC9452CA81A09D85DULL, 0x24AA6C514DA27500ULL, 0x4C9F34427501B447ULL,
- 0x14A68FD73C910841ULL, 0xA71B9B83461CBD93ULL, 0x03488B95B0F1850FULL,
- 0x637B2B34FF93C040ULL, 0x09D1BC9A3DD90A94ULL, 0x3575668334A1DD3BULL,
- 0x735E2B97A4C45A23ULL, 0x18727070F1BD400BULL, 0x1FCBACD259BF02E7ULL,
- 0xD310A7C2CE9B6555ULL, 0xBF983FE0FE5D8244ULL, 0x9F74D14F7454A824ULL,
- 0x51EBDC4AB9BA3035ULL, 0x5C82C505DB9AB0FAULL, 0xFCF7FE8A3430B241ULL,
- 0x3253A729B9BA3DDEULL, 0x8C74C368081B3075ULL, 0xB9BC6C87167C33E7ULL,
- 0x7EF48F2B83024E20ULL, 0x11D505D4C351BD7FULL, 0x6568FCA92C76A243ULL,
- 0x4DE0B0F40F32A7B8ULL, 0x96D693460CC37E5DULL, 0x42E240CB63689F2FULL,
- 0x6D2BDCDAE2919661ULL, 0x42880B0236E4D951ULL, 0x5F0F4A5898171BB6ULL,
- 0x39F890F579F92F88ULL, 0x93C5B5F47356388BULL, 0x63DC359D8D231B78ULL,
- 0xEC16CA8AEA98AD76ULL, 0x5355F900C2A82DC7ULL, 0x07FB9F855A997142ULL,
- 0x5093417AA8A7ED5EULL, 0x7BCBC38DA25A7F3CULL, 0x19FC8A768CF4B6D4ULL,
- 0x637A7780DECFC0D9ULL, 0x8249A47AEE0E41F7ULL, 0x79AD695501E7D1E8ULL,
- 0x14ACBAF4777D5776ULL, 0xF145B6BECCDEA195ULL, 0xDABF2AC8201752FCULL,
- 0x24C3C94DF9C8D3F6ULL, 0xBB6E2924F03912EAULL, 0x0CE26C0B95C980D9ULL,
- 0xA49CD132BFBF7CC4ULL, 0xE99D662AF4243939ULL, 0x27E6AD7891165C3FULL,
- 0x8535F040B9744FF1ULL, 0x54B3F4FA5F40D873ULL, 0x72B12C32127FED2BULL,
- 0xEE954D3C7B411F47ULL, 0x9A85AC909A24EAA1ULL, 0x70AC4CD9F04F21F5ULL,
- 0xF9B89D3E99A075C2ULL, 0x87B3E2B2B5C907B1ULL, 0xA366E5B8C54F48B8ULL,
- 0xAE4A9346CC3F7CF2ULL, 0x1920C04D47267BBDULL, 0x87BF02C6B49E2AE9ULL,
- 0x092237AC237F3859ULL, 0xFF07F64EF8ED14D0ULL, 0x8DE8DCA9F03CC54EULL,
- 0x9C1633264DB49C89ULL, 0xB3F22C3D0B0B38EDULL, 0x390E5FB44D01144BULL,
- 0x5BFEA5B4712768E9ULL, 0x1E1032911FA78984ULL, 0x9A74ACB964E78CB3ULL,
- 0x4F80F7A035DAFB04ULL, 0x6304D09A0B3738C4ULL, 0x2171E64683023A08ULL,
- 0x5B9B63EB9CEFF80CULL, 0x506AACF489889342ULL, 0x1881AFC9A3A701D6ULL,
- 0x6503080440750644ULL, 0xDFD395339CDBF4A7ULL, 0xEF927DBCF00C20F2ULL,
- 0x7B32F7D1E03680ECULL, 0xB9FD7620E7316243ULL, 0x05A7E8A57DB91B77ULL,
- 0xB5889C6E15630A75ULL, 0x4A750A09CE9573F7ULL, 0xCF464CEC899A2F8AULL,
- 0xF538639CE705B824ULL, 0x3C79A0FF5580EF7FULL, 0xEDE6C87F8477609DULL,
- 0x799E81F05BC93F31ULL, 0x86536B8CF3428A8CULL, 0x97D7374C60087B73ULL,
- 0xA246637CFF328532ULL, 0x043FCAE60CC0EBA0ULL, 0x920E449535DD359EULL,
- 0x70EB093B15B290CCULL, 0x73A1921916591CBDULL, 0x56436C9FE1A1AA8DULL,
- 0xEFAC4B70633B8F81ULL, 0xBB215798D45DF7AFULL, 0x45F20042F24F1768ULL,
- 0x930F80F4E8EB7462ULL, 0xFF6712FFCFD75EA1ULL, 0xAE623FD67468AA70ULL,
- 0xDD2C5BC84BC8D8FCULL, 0x7EED120D54CF2DD9ULL, 0x22FE545401165F1CULL,
- 0xC91800E98FB99929ULL, 0x808BD68E6AC10365ULL, 0xDEC468145B7605F6ULL,
- 0x1BEDE3A3AEF53302ULL, 0x43539603D6C55602ULL, 0xAA969B5C691CCB7AULL,
- 0xA87832D392EFEE56ULL, 0x65942C7B3C7E11AEULL, 0xDED2D633CAD004F6ULL,
- 0x21F08570F420E565ULL, 0xB415938D7DA94E3CULL, 0x91B859E59ECB6350ULL,
- 0x10CFF333E0ED804AULL, 0x28AED140BE0BB7DDULL, 0xC5CC1D89724FA456ULL,
- 0x5648F680F11A2741ULL, 0x2D255069F0B7DAB3ULL, 0x9BC5A38EF729ABD4ULL,
- 0xEF2F054308F6A2BCULL, 0xAF2042F5CC5C2858ULL, 0x480412BAB7F5BE2AULL,
- 0xAEF3AF4A563DFE43ULL, 0x19AFE59AE451497FULL, 0x52593803DFF1E840ULL,
- 0xF4F076E65F2CE6F0ULL, 0x11379625747D5AF3ULL, 0xBCE5D2248682C115ULL,
- 0x9DA4243DE836994FULL, 0x066F70B33FE09017ULL, 0x4DC4DE189B671A1CULL,
- 0x51039AB7712457C3ULL, 0xC07A3F80C31FB4B4ULL, 0xB46EE9C5E64A6E7CULL,
- 0xB3819A42ABE61C87ULL, 0x21A007933A522A20ULL, 0x2DF16F761598AA4FULL,
- 0x763C4A1371B368FDULL, 0xF793C46702E086A0ULL, 0xD7288E012AEB8D31ULL,
- 0xDE336A2A4BC1C44BULL, 0x0BF692B38D079F23ULL, 0x2C604A7A177326B3ULL,
- 0x4850E73E03EB6064ULL, 0xCFC447F1E53C8E1BULL, 0xB05CA3F564268D99ULL,
- 0x9AE182C8BC9474E8ULL, 0xA4FC4BD4FC5558CAULL, 0xE755178D58FC4E76ULL,
- 0x69B97DB1A4C03DFEULL, 0xF9B5B7C4ACC67C96ULL, 0xFC6A82D64B8655FBULL,
- 0x9C684CB6C4D24417ULL, 0x8EC97D2917456ED0ULL, 0x6703DF9D2924E97EULL,
- 0xC547F57E42A7444EULL, 0x78E37644E7CAD29EULL, 0xFE9A44E9362F05FAULL,
- 0x08BD35CC38336615ULL, 0x9315E5EB3A129ACEULL, 0x94061B871E04DF75ULL,
- 0xDF1D9F9D784BA010ULL, 0x3BBA57B68871B59DULL, 0xD2B7ADEEDED1F73FULL,
- 0xF7A255D83BC373F8ULL, 0xD7F4F2448C0CEB81ULL, 0xD95BE88CD210FFA7ULL,
- 0x336F52F8FF4728E7ULL, 0xA74049DAC312AC71ULL, 0xA2F61BB6E437FDB5ULL,
- 0x4F2A5CB07F6A35B3ULL, 0x87D380BDA5BF7859ULL, 0x16B9F7E06C453A21ULL,
- 0x7BA2484C8A0FD54EULL, 0xF3A678CAD9A2E38CULL, 0x39B0BF7DDE437BA2ULL,
- 0xFCAF55C1BF8A4424ULL, 0x18FCF680573FA594ULL, 0x4C0563B89F495AC3ULL,
- 0x40E087931A00930DULL, 0x8CFFA9412EB642C1ULL, 0x68CA39053261169FULL,
- 0x7A1EE967D27579E2ULL, 0x9D1D60E5076F5B6FULL, 0x3810E399B6F65BA2ULL,
- 0x32095B6D4AB5F9B1ULL, 0x35CAB62109DD038AULL, 0xA90B24499FCFAFB1ULL,
- 0x77A225A07CC2C6BDULL, 0x513E5E634C70E331ULL, 0x4361C0CA3F692F12ULL,
- 0xD941ACA44B20A45BULL, 0x528F7C8602C5807BULL, 0x52AB92BEB9613989ULL,
- 0x9D1DFA2EFC557F73ULL, 0x722FF175F572C348ULL, 0x1D1260A51107FE97ULL,
- 0x7A249A57EC0C9BA2ULL, 0x04208FE9E8F7F2D6ULL, 0x5A110C6058B920A0ULL,
- 0x0CD9A497658A5698ULL, 0x56FD23C8F9715A4CULL, 0x284C847B9D887AAEULL,
- 0x04FEABFBBDB619CBULL, 0x742E1E651C60BA83ULL, 0x9A9632E65904AD3CULL,
- 0x881B82A13B51B9E2ULL, 0x506E6744CD974924ULL, 0xB0183DB56FFC6A79ULL,
- 0x0ED9B915C66ED37EULL, 0x5E11E86D5873D484ULL, 0xF678647E3519AC6EULL,
- 0x1B85D488D0F20CC5ULL, 0xDAB9FE6525D89021ULL, 0x0D151D86ADB73615ULL,
- 0xA865A54EDCC0F019ULL, 0x93C42566AEF98FFBULL, 0x99E7AFEABE000731ULL,
- 0x48CBFF086DDF285AULL, 0x7F9B6AF1EBF78BAFULL, 0x58627E1A149BBA21ULL,
- 0x2CD16E2ABD791E33ULL, 0xD363EFF5F0977996ULL, 0x0CE2A38C344A6EEDULL,
- 0x1A804AADB9CFA741ULL, 0x907F30421D78C5DEULL, 0x501F65EDB3034D07ULL,
- 0x37624AE5A48FA6E9ULL, 0x957BAF61700CFF4EULL, 0x3A6C27934E31188AULL,
- 0xD49503536ABCA345ULL, 0x088E049589C432E0ULL, 0xF943AEE7FEBF21B8ULL,
- 0x6C3B8E3E336139D3ULL, 0x364F6FFA464EE52EULL, 0xD60F6DCEDC314222ULL,
- 0x56963B0DCA418FC0ULL, 0x16F50EDF91E513AFULL, 0xEF1955914B609F93ULL,
- 0x565601C0364E3228ULL, 0xECB53939887E8175ULL, 0xBAC7A9A18531294BULL,
- 0xB344C470397BBA52ULL, 0x65D34954DAF3CEBDULL, 0xB4B81B3FA97511E2ULL,
- 0xB422061193D6F6A7ULL, 0x071582401C38434DULL, 0x7A13F18BBEDC4FF5ULL,
- 0xBC4097B116C524D2ULL, 0x59B97885E2F2EA28ULL, 0x99170A5DC3115544ULL,
- 0x6F423357E7C6A9F9ULL, 0x325928EE6E6F8794ULL, 0xD0E4366228B03343ULL,
- 0x565C31F7DE89EA27ULL, 0x30F5611484119414ULL, 0xD873DB391292ED4FULL,
- 0x7BD94E1D8E17DEBCULL, 0xC7D9F16864A76E94ULL, 0x947AE053EE56E63CULL,
- 0xC8C93882F9475F5FULL, 0x3A9BF55BA91F81CAULL, 0xD9A11FBB3D9808E4ULL,
- 0x0FD22063EDC29FCAULL, 0xB3F256D8ACA0B0B9ULL, 0xB03031A8B4516E84ULL,
- 0x35DD37D5871448AFULL, 0xE9F6082B05542E4EULL, 0xEBFAFA33D7254B59ULL,
- 0x9255ABB50D532280ULL, 0xB9AB4CE57F2D34F3ULL, 0x693501D628297551ULL,
- 0xC62C58F97DD949BFULL, 0xCD454F8F19C5126AULL, 0xBBE83F4ECC2BDECBULL,
- 0xDC842B7E2819E230ULL, 0xBA89142E007503B8ULL, 0xA3BC941D0A5061CBULL,
- 0xE9F6760E32CD8021ULL, 0x09C7E552BC76492FULL, 0x852F54934DA55CC9ULL,
- 0x8107FCCF064FCF56ULL, 0x098954D51FFF6580ULL, 0x23B70EDB1955C4BFULL,
- 0xC330DE426430F69DULL, 0x4715ED43E8A45C0AULL, 0xA8D7E4DAB780A08DULL,
- 0x0572B974F03CE0BBULL, 0xB57D2E985E1419C7ULL, 0xE8D9ECBE2CF3D73FULL,
- 0x2FE4B17170E59750ULL, 0x11317BA87905E790ULL, 0x7FBF21EC8A1F45ECULL,
- 0x1725CABFCB045B00ULL, 0x964E915CD5E2B207ULL, 0x3E2B8BCBF016D66DULL,
- 0xBE7444E39328A0ACULL, 0xF85B2B4FBCDE44B7ULL, 0x49353FEA39BA63B1ULL,
- 0x1DD01AAFCD53486AULL, 0x1FCA8A92FD719F85ULL, 0xFC7C95D827357AFAULL,
- 0x18A6A990C8B35EBDULL, 0xCCCB7005C6B9C28DULL, 0x3BDBB92C43B17F26ULL,
- 0xAA70B5B4F89695A2ULL, 0xE94C39A54A98307FULL, 0xB7A0B174CFF6F36EULL,
- 0xD4DBA84729AF48ADULL, 0x2E18BC1AD9704A68ULL, 0x2DE0966DAF2F8B1CULL,
- 0xB9C11D5B1E43A07EULL, 0x64972D68DEE33360ULL, 0x94628D38D0C20584ULL,
- 0xDBC0D2B6AB90A559ULL, 0xD2733C4335C6A72FULL, 0x7E75D99D94A70F4DULL,
- 0x6CED1983376FA72BULL, 0x97FCAACBF030BC24ULL, 0x7B77497B32503B12ULL,
- 0x8547EDDFB81CCB94ULL, 0x79999CDFF70902CBULL, 0xCFFE1939438E9B24ULL,
- 0x829626E3892D95D7ULL, 0x92FAE24291F2B3F1ULL, 0x63E22C147B9C3403ULL,
- 0xC678B6D860284A1CULL, 0x5873888850659AE7ULL, 0x0981DCD296A8736DULL,
- 0x9F65789A6509A440ULL, 0x9FF38FED72E9052FULL, 0xE479EE5B9930578CULL,
- 0xE7F28ECD2D49EECDULL, 0x56C074A581EA17FEULL, 0x5544F7D774B14AEFULL,
- 0x7B3F0195FC6F290FULL, 0x12153635B2C0CF57ULL, 0x7F5126DBBA5E0CA7ULL,
- 0x7A76956C3EAFB413ULL, 0x3D5774A11D31AB39ULL, 0x8A1B083821F40CB4ULL,
- 0x7B4A38E32537DF62ULL, 0x950113646D1D6E03ULL, 0x4DA8979A0041E8A9ULL,
- 0x3BC36E078F7515D7ULL, 0x5D0A12F27AD310D1ULL, 0x7F9D1A2E1EBE1327ULL,
- 0xDA3A361B1C5157B1ULL, 0xDCDD7D20903D0C25ULL, 0x36833336D068F707ULL,
- 0xCE68341F79893389ULL, 0xAB9090168DD05F34ULL, 0x43954B3252DC25E5ULL,
- 0xB438C2B67F98E5E9ULL, 0x10DCD78E3851A492ULL, 0xDBC27AB5447822BFULL,
- 0x9B3CDB65F82CA382ULL, 0xB67B7896167B4C84ULL, 0xBFCED1B0048EAC50ULL,
- 0xA9119B60369FFEBDULL, 0x1FFF7AC80904BF45ULL, 0xAC12FB171817EEE7ULL,
- 0xAF08DA9177DDA93DULL, 0x1B0CAB936E65C744ULL, 0xB559EB1D04E5E932ULL,
- 0xC37B45B3F8D6F2BAULL, 0xC3A9DC228CAAC9E9ULL, 0xF3B8B6675A6507FFULL,
- 0x9FC477DE4ED681DAULL, 0x67378D8ECCEF96CBULL, 0x6DD856D94D259236ULL,
- 0xA319CE15B0B4DB31ULL, 0x073973751F12DD5EULL, 0x8A8E849EB32781A5ULL,
- 0xE1925C71285279F5ULL, 0x74C04BF1790C0EFEULL, 0x4DDA48153C94938AULL,
- 0x9D266D6A1CC0542CULL, 0x7440FB816508C4FEULL, 0x13328503DF48229FULL,
- 0xD6BF7BAEE43CAC40ULL, 0x4838D65F6EF6748FULL, 0x1E152328F3318DEAULL,
- 0x8F8419A348F296BFULL, 0x72C8834A5957B511ULL, 0xD7A023A73260B45CULL,
- 0x94EBC8ABCFB56DAEULL, 0x9FC10D0F989993E0ULL, 0xDE68A2355B93CAE6ULL,
- 0xA44CFE79AE538BBEULL, 0x9D1D84FCCE371425ULL, 0x51D2B1AB2DDFB636ULL,
- 0x2FD7E4B9E72CD38CULL, 0x65CA5B96B7552210ULL, 0xDD69A0D8AB3B546DULL,
- 0x604D51B25FBF70E2ULL, 0x73AA8A564FB7AC9EULL, 0x1A8C1E992B941148ULL,
- 0xAAC40A2703D9BEA0ULL, 0x764DBEAE7FA4F3A6ULL, 0x1E99B96E70A9BE8BULL,
- 0x2C5E9DEB57EF4743ULL, 0x3A938FEE32D29981ULL, 0x26E6DB8FFDF5ADFEULL,
- 0x469356C504EC9F9DULL, 0xC8763C5B08D1908CULL, 0x3F6C6AF859D80055ULL,
- 0x7F7CC39420A3A545ULL, 0x9BFB227EBDF4C5CEULL, 0x89039D79D6FC5C5CULL,
- 0x8FE88B57305E2AB6ULL, 0xA09E8C8C35AB96DEULL, 0xFA7E393983325753ULL,
- 0xD6B6D0ECC617C699ULL, 0xDFEA21EA9E7557E3ULL, 0xB67C1FA481680AF8ULL,
- 0xCA1E3785A9E724E5ULL, 0x1CFC8BED0D681639ULL, 0xD18D8549D140CAEAULL,
- 0x4ED0FE7E9DC91335ULL, 0xE4DBF0634473F5D2ULL, 0x1761F93A44D5AEFEULL,
- 0x53898E4C3910DA55ULL, 0x734DE8181F6EC39AULL, 0x2680B122BAA28D97ULL,
- 0x298AF231C85BAFABULL, 0x7983EED3740847D5ULL, 0x66C1A2A1A60CD889ULL,
- 0x9E17E49642A3E4C1ULL, 0xEDB454E7BADC0805ULL, 0x50B704CAB602C329ULL,
- 0x4CC317FB9CDDD023ULL, 0x66B4835D9EAFEA22ULL, 0x219B97E26FFC81BDULL,
- 0x261E4E4C0A333A9DULL, 0x1FE2CCA76517DB90ULL, 0xD7504DFA8816EDBBULL,
- 0xB9571FA04DC089C8ULL, 0x1DDC0325259B27DEULL, 0xCF3F4688801EB9AAULL,
- 0xF4F5D05C10CAB243ULL, 0x38B6525C21A42B0EULL, 0x36F60E2BA4FA6800ULL,
- 0xEB3593803173E0CEULL, 0x9C4CD6257C5A3603ULL, 0xAF0C317D32ADAA8AULL,
- 0x258E5A80C7204C4BULL, 0x8B889D624D44885DULL, 0xF4D14597E660F855ULL,
- 0xD4347F66EC8941C3ULL, 0xE699ED85B0DFB40DULL, 0x2472F6207C2D0484ULL,
- 0xC2A1E7B5B459AEB5ULL, 0xAB4F6451CC1D45ECULL, 0x63767572AE3D6174ULL,
- 0xA59E0BD101731A28ULL, 0x116D0016CB948F09ULL, 0x2CF9C8CA052F6E9FULL,
- 0x0B090A7560A968E3ULL, 0xABEEDDB2DDE06FF1ULL, 0x58EFC10B06A2068DULL,
- 0xC6E57A78FBD986E0ULL, 0x2EAB8CA63CE802D7ULL, 0x14A195640116F336ULL,
- 0x7C0828DD624EC390ULL, 0xD74BBE77E6116AC7ULL, 0x804456AF10F5FB53ULL,
- 0xEBE9EA2ADF4321C7ULL, 0x03219A39EE587A30ULL, 0x49787FEF17AF9924ULL,
- 0xA1E9300CD8520548ULL, 0x5B45E522E4B1B4EFULL, 0xB49C3B3995091A36ULL,
- 0xD4490AD526F14431ULL, 0x12A8F216AF9418C2ULL, 0x001F837CC7350524ULL,
- 0x1877B51E57A764D5ULL, 0xA2853B80F17F58EEULL, 0x993E1DE72D36D310ULL,
- 0xB3598080CE64A656ULL, 0x252F59CF0D9F04BBULL, 0xD23C8E176D113600ULL,
- 0x1BDA0492E7E4586EULL, 0x21E0BD5026C619BFULL, 0x3B097ADAF088F94EULL,
- 0x8D14DEDB30BE846EULL, 0xF95CFFA23AF5F6F4ULL, 0x3871700761B3F743ULL,
- 0xCA672B91E9E4FA16ULL, 0x64C8E531BFF53B55ULL, 0x241260ED4AD1E87DULL,
- 0x106C09B972D2E822ULL, 0x7FBA195410E5CA30ULL, 0x7884D9BC6CB569D8ULL,
- 0x0647DFEDCD894A29ULL, 0x63573FF03E224774ULL, 0x4FC8E9560F91B123ULL,
- 0x1DB956E450275779ULL, 0xB8D91274B9E9D4FBULL, 0xA2EBEE47E2FBFCE1ULL,
- 0xD9F1F30CCD97FB09ULL, 0xEFED53D75FD64E6BULL, 0x2E6D02C36017F67FULL,
- 0xA9AA4D20DB084E9BULL, 0xB64BE8D8B25396C1ULL, 0x70CB6AF7C2D5BCF0ULL,
- 0x98F076A4F7A2322EULL, 0xBF84470805E69B5FULL, 0x94C3251F06F90CF3ULL,
- 0x3E003E616A6591E9ULL, 0xB925A6CD0421AFF3ULL, 0x61BDD1307C66E300ULL,
- 0xBF8D5108E27E0D48ULL, 0x240AB57A8B888B20ULL, 0xFC87614BAF287E07ULL,
- 0xEF02CDD06FFDB432ULL, 0xA1082C0466DF6C0AULL, 0x8215E577001332C8ULL,
- 0xD39BB9C3A48DB6CFULL, 0x2738259634305C14ULL, 0x61CF4F94C97DF93DULL,
- 0x1B6BACA2AE4E125BULL, 0x758F450C88572E0BULL, 0x959F587D507A8359ULL,
- 0xB063E962E045F54DULL, 0x60E8ED72C0DFF5D1ULL, 0x7B64978555326F9FULL,
- 0xFD080D236DA814BAULL, 0x8C90FD9B083F4558ULL, 0x106F72FE81E2C590ULL,
- 0x7976033A39F7D952ULL, 0xA4EC0132764CA04BULL, 0x733EA705FAE4FA77ULL,
- 0xB4D8F77BC3E56167ULL, 0x9E21F4F903B33FD9ULL, 0x9D765E419FB69F6DULL,
- 0xD30C088BA61EA5EFULL, 0x5D94337FBFAF7F5BULL, 0x1A4E4822EB4D7A59ULL,
- 0x6FFE73E81B637FB3ULL, 0xDDF957BC36D8B9CAULL, 0x64D0E29EEA8838B3ULL,
- 0x08DD9BDFD96B9F63ULL, 0x087E79E5A57D1D13ULL, 0xE328E230E3E2B3FBULL,
- 0x1C2559E30F0946BEULL, 0x720BF5F26F4D2EAAULL, 0xB0774D261CC609DBULL,
- 0x443F64EC5A371195ULL, 0x4112CF68649A260EULL, 0xD813F2FAB7F5C5CAULL,
- 0x660D3257380841EEULL, 0x59AC2C7873F910A3ULL, 0xE846963877671A17ULL,
- 0x93B633ABFA3469F8ULL, 0xC0C0F5A60EF4CDCFULL, 0xCAF21ECD4377B28CULL,
- 0x57277707199B8175ULL, 0x506C11B9D90E8B1DULL, 0xD83CC2687A19255FULL,
- 0x4A29C6465A314CD1ULL, 0xED2DF21216235097ULL, 0xB5635C95FF7296E2ULL,
- 0x22AF003AB672E811ULL, 0x52E762596BF68235ULL, 0x9AEBA33AC6ECC6B0ULL,
- 0x944F6DE09134DFB6ULL, 0x6C47BEC883A7DE39ULL, 0x6AD047C430A12104ULL,
- 0xA5B1CFDBA0AB4067ULL, 0x7C45D833AFF07862ULL, 0x5092EF950A16DA0BULL,
- 0x9338E69C052B8E7BULL, 0x455A4B4CFE30E3F5ULL, 0x6B02E63195AD0CF8ULL,
- 0x6B17B224BAD6BF27ULL, 0xD1E0CCD25BB9C169ULL, 0xDE0C89A556B9AE70ULL,
- 0x50065E535A213CF6ULL, 0x9C1169FA2777B874ULL, 0x78EDEFD694AF1EEDULL,
- 0x6DC93D9526A50E68ULL, 0xEE97F453F06791EDULL, 0x32AB0EDB696703D3ULL,
- 0x3A6853C7E70757A7ULL, 0x31865CED6120F37DULL, 0x67FEF95D92607890ULL,
- 0x1F2B1D1F15F6DC9CULL, 0xB69E38A8965C6B65ULL, 0xAA9119FF184CCCF4ULL,
- 0xF43C732873F24C13ULL, 0xFB4A3D794A9A80D2ULL, 0x3550C2321FD6109CULL,
- 0x371F77E76BB8417EULL, 0x6BFA9AAE5EC05779ULL, 0xCD04F3FF001A4778ULL,
- 0xE3273522064480CAULL, 0x9F91508BFFCFC14AULL, 0x049A7F41061A9E60ULL,
- 0xFCB6BE43A9F2FE9BULL, 0x08DE8A1C7797DA9BULL, 0x8F9887E6078735A1ULL,
- 0xB5B4071DBFC73A66ULL, 0x230E343DFBA08D33ULL, 0x43ED7F5A0FAE657DULL,
- 0x3A88A0FBBCB05C63ULL, 0x21874B8B4D2DBC4FULL, 0x1BDEA12E35F6A8C9ULL,
- 0x53C065C6C8E63528ULL, 0xE34A1D250E7A8D6BULL, 0xD6B04D3B7651DD7EULL,
- 0x5E90277E7CB39E2DULL, 0x2C046F22062DC67DULL, 0xB10BB459132D0A26ULL,
- 0x3FA9DDFB67E2F199ULL, 0x0E09B88E1914F7AFULL, 0x10E8B35AF3EEAB37ULL,
- 0x9EEDECA8E272B933ULL, 0xD4C718BC4AE8AE5FULL, 0x81536D601170FC20ULL,
- 0x91B534F885818A06ULL, 0xEC8177F83F900978ULL, 0x190E714FADA5156EULL,
- 0xB592BF39B0364963ULL, 0x89C350C893AE7DC1ULL, 0xAC042E70F8B383F2ULL,
- 0xB49B52E587A1EE60ULL, 0xFB152FE3FF26DA89ULL, 0x3E666E6F69AE2C15ULL,
- 0x3B544EBE544C19F9ULL, 0xE805A1E290CF2456ULL, 0x24B33C9D7ED25117ULL,
- 0xE74733427B72F0C1ULL, 0x0A804D18B7097475ULL, 0x57E3306D881EDB4FULL,
- 0x4AE7D6A36EB5DBCBULL, 0x2D8D5432157064C8ULL, 0xD1E649DE1E7F268BULL,
- 0x8A328A1CEDFE552CULL, 0x07A3AEC79624C7DAULL, 0x84547DDC3E203C94ULL,
- 0x990A98FD5071D263ULL, 0x1A4FF12616EEFC89ULL, 0xF6F7FD1431714200ULL,
- 0x30C05B1BA332F41CULL, 0x8D2636B81555A786ULL, 0x46C9FEB55D120902ULL,
- 0xCCEC0A73B49C9921ULL, 0x4E9D2827355FC492ULL, 0x19EBB029435DCB0FULL,
- 0x4659D2B743848A2CULL, 0x963EF2C96B33BE31ULL, 0x74F85198B05A2E7DULL,
- 0x5A0F544DD2B1FB18ULL, 0x03727073C2E134B1ULL, 0xC7F6AA2DE59AEA61ULL,
- 0x352787BAA0D7C22FULL, 0x9853EAB63B5E0B35ULL, 0xABBDCDD7ED5C0860ULL,
- 0xCF05DAF5AC8D77B0ULL, 0x49CAD48CEBF4A71EULL, 0x7A4C10EC2158C4A6ULL,
- 0xD9E92AA246BF719EULL, 0x13AE978D09FE5557ULL, 0x730499AF921549FFULL,
- 0x4E4B705B92903BA4ULL, 0xFF577222C14F0A3AULL, 0x55B6344CF97AAFAEULL,
- 0xB862225B055B6960ULL, 0xCAC09AFBDDD2CDB4ULL, 0xDAF8E9829FE96B5FULL,
- 0xB5FDFC5D3132C498ULL, 0x310CB380DB6F7503ULL, 0xE87FBB46217A360EULL,
- 0x2102AE466EBB1148ULL, 0xF8549E1A3AA5E00DULL, 0x07A69AFDCC42261AULL,
- 0xC4C118BFE78FEAAEULL, 0xF9F4892ED96BD438ULL, 0x1AF3DBE25D8F45DAULL,
- 0xF5B4B0B0D2DEEEB4ULL, 0x962ACEEFA82E1C84ULL, 0x046E3ECAAF453CE9ULL,
- 0xF05D129681949A4CULL, 0x964781CE734B3C84ULL, 0x9C2ED44081CE5FBDULL,
- 0x522E23F3925E319EULL, 0x177E00F9FC32F791ULL, 0x2BC60A63A6F3B3F2ULL,
- 0x222BBFAE61725606ULL, 0x486289DDCC3D6780ULL, 0x7DC7785B8EFDFC80ULL,
- 0x8AF38731C02BA980ULL, 0x1FAB64EA29A2DDF7ULL, 0xE4D9429322CD065AULL,
- 0x9DA058C67844F20CULL, 0x24C0E332B70019B0ULL, 0x233003B5A6CFE6ADULL,
- 0xD586BD01C5C217F6ULL, 0x5E5637885F29BC2BULL, 0x7EBA726D8C94094BULL,
- 0x0A56A5F0BFE39272ULL, 0xD79476A84EE20D06ULL, 0x9E4C1269BAA4BF37ULL,
- 0x17EFEE45B0DEE640ULL, 0x1D95B0A5FCF90BC6ULL, 0x93CBE0B699C2585DULL,
- 0x65FA4F227A2B6D79ULL, 0xD5F9E858292504D5ULL, 0xC2B5A03F71471A6FULL,
- 0x59300222B4561E00ULL, 0xCE2F8642CA0712DCULL, 0x7CA9723FBB2E8988ULL,
- 0x2785338347F2BA08ULL, 0xC61BB3A141E50E8CULL, 0x150F361DAB9DEC26ULL,
- 0x9F6A419D382595F4ULL, 0x64A53DC924FE7AC9ULL, 0x142DE49FFF7A7C3DULL,
- 0x0C335248857FA9E7ULL, 0x0A9C32D5EAE45305ULL, 0xE6C42178C4BBB92EULL,
- 0x71F1CE2490D20B07ULL, 0xF1BCC3D275AFE51AULL, 0xE728E8C83C334074ULL,
- 0x96FBF83A12884624ULL, 0x81A1549FD6573DA5ULL, 0x5FA7867CAF35E149ULL,
- 0x56986E2EF3ED091BULL, 0x917F1DD5F8886C61ULL, 0xD20D8C88C8FFE65FULL,
- 0x31D71DCE64B2C310ULL, 0xF165B587DF898190ULL, 0xA57E6339DD2CF3A0ULL,
- 0x1EF6E6DBB1961EC9ULL, 0x70CC73D90BC26E24ULL, 0xE21A6B35DF0C3AD7ULL,
- 0x003A93D8B2806962ULL, 0x1C99DED33CB890A1ULL, 0xCF3145DE0ADD4289ULL,
- 0xD0E4427A5514FB72ULL, 0x77C621CC9FB3A483ULL, 0x67A34DAC4356550BULL,
- 0xF8D626AAAF278509ULL
- }};
-
- // polyglot_key() returns the PolyGlot hash key of the given position
- Key polyglot_key(const Position& pos) {
-
- Key key = 0;
- Bitboard b = pos.pieces();
-
- while (b)
- {
- Square s = pop_lsb(&b);
- Piece pc = pos.piece_on(s);
-
- // PolyGlot pieces are: BP = 0, WP = 1, BN = 2, ... BK = 10, WK = 11
- key ^= PG.Zobrist.psq[2 * (type_of(pc) - 1) + (color_of(pc) == WHITE)][s];
- }
-
- b = pos.can_castle(ANY_CASTLING);
-
- while (b)
- key ^= PG.Zobrist.castling[pop_lsb(&b)];
-
- if (pos.ep_square() != SQ_NONE)
- key ^= PG.Zobrist.enpassant[file_of(pos.ep_square())];
-
- if (pos.side_to_move() == WHITE)
- key ^= PG.Zobrist.turn;
-
- return key;
- }
-
-} // namespace
-
-PolyglotBook::PolyglotBook() : rng(now() % 10000) {}
-
-PolyglotBook::~PolyglotBook() { if (is_open()) close(); }
-
-
-/// operator>>() reads sizeof(T) chars from the file's binary byte stream and
-/// converts them into a number of type T. A Polyglot book stores numbers in
-/// big-endian format.
-
-template PolyglotBook& PolyglotBook::operator>>(T& n) {
-
- n = 0;
- for (size_t i = 0; i < sizeof(T); ++i)
- n = T((n << 8) + ifstream::get());
-
- return *this;
-}
-
-template<> PolyglotBook& PolyglotBook::operator>>(Entry& e) {
- return *this >> e.key >> e.move >> e.count >> e.learn;
-}
-
-
-/// open() tries to open a book file with the given name after closing any
-/// existing one.
-
-bool PolyglotBook::open(const char* fName) {
-
- if (is_open()) // Cannot close an already closed file
- close();
-
- ifstream::open(fName, ifstream::in | ifstream::binary);
-
- fileName = is_open() ? fName : "";
- ifstream::clear(); // Reset any error flag to allow a retry ifstream::open()
- return !fileName.empty();
-}
-
-
-/// probe() tries to find a book move for the given position. If no move is
-/// found, it returns MOVE_NONE. If pickBest is true, then it always returns
-/// the highest-rated move, otherwise it randomly chooses one based on the
-/// move score.
-
-Move PolyglotBook::probe(const Position& pos, const string& fName, bool pickBest) {
-
- if (fileName != fName && !open(fName.c_str()))
- return MOVE_NONE;
-
- Entry e;
- uint16_t best = 0;
- unsigned sum = 0;
- Move move = MOVE_NONE;
- Key key = polyglot_key(pos);
-
- seekg(find_first(key) * sizeof(Entry), ios_base::beg);
-
- while (*this >> e, e.key == key && good())
- {
- best = max(best, e.count);
- sum += e.count;
-
- // Choose book move according to its score. If a move has a very high
- // score it has a higher probability of being choosen than a move with
- // a lower score. Note that first entry is always chosen.
- if ( (!pickBest && sum && rng.rand() % sum < e.count)
- || (pickBest && e.count == best))
- move = Move(e.move);
- }
-
- if (!move)
- return MOVE_NONE;
-
- // A PolyGlot book move is encoded as follows:
- //
- // bit 0- 5: destination square (from 0 to 63)
- // bit 6-11: origin square (from 0 to 63)
- // bit 12-14: promotion piece (from KNIGHT == 1 to QUEEN == 4)
- //
- // Castling moves follow the "king captures rook" representation. If a book
- // move is a promotion, we have to convert it to our representation and in
- // all other cases, we can directly compare with a Move after having masked
- // out the special Move flags (bit 14-15) that are not supported by PolyGlot.
- int pt = (move >> 12) & 7;
- if (pt)
- move = make(from_sq(move), to_sq(move), PieceType(pt + 1));
-
- // Add 'special move' flags and verify it is legal
- for (const auto& m : MoveList(pos))
- if (move == (m ^ type_of(m)))
- return m;
-
- return MOVE_NONE;
-}
-
-
-/// find_first() takes a book key as input, and does a binary search through
-/// the book file for the given key. Returns the index of the leftmost book
-/// entry with the same key as the input.
-
-size_t PolyglotBook::find_first(Key key) {
-
- seekg(0, ios::end); // Move pointer to end, so tellg() gets file's size
-
- size_t low = 0, mid, high = (size_t)tellg() / sizeof(Entry) - 1;
- Entry e;
-
- assert(low <= high);
-
- while (low < high && good())
- {
- mid = (low + high) / 2;
-
- assert(mid >= low && mid < high);
-
- seekg(mid * sizeof(Entry), ios_base::beg);
- *this >> e;
-
- if (key <= e.key)
- high = mid;
- else
- low = mid + 1;
- }
-
- assert(low == high);
-
- return low;
-}
diff --git a/Engines/Windows/deepfish/srcD/book.h b/Engines/Windows/deepfish/srcD/book.h
deleted file mode 100644
index 619bed3..0000000
--- a/Engines/Windows/deepfish/srcD/book.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
-
- Stockfish is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Stockfish is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-#ifndef BOOK_H_INCLUDED
-#define BOOK_H_INCLUDED
-
-#include
-#include
-
-#include "misc.h"
-#include "position.h"
-
-class PolyglotBook : private std::ifstream {
-public:
- PolyglotBook();
- ~PolyglotBook();
- Move probe(const Position& pos, const std::string& fName, bool pickBest);
-
-private:
- template PolyglotBook& operator>>(T& n);
-
- bool open(const char* fName);
- size_t find_first(Key key);
-
- PRNG rng;
- std::string fileName;
-};
-
-#endif // #ifndef BOOK_H_INCLUDED
diff --git a/Engines/Windows/deepfish/srcD/opt.cpp b/Engines/Windows/deepfish/srcD/opt.cpp
deleted file mode 100644
index b64557e..0000000
--- a/Engines/Windows/deepfish/srcD/opt.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright(C)2004-2008 Tord Romstad (Glaurung author)
- Copyright(C)2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
-
- Stockfish is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation,either version 3 of the License, or
- (at your option) any later version.
-
- Stockfish is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-#include
-
-#include "thread.h"
-#include "tt.h"
-
-using namespace std;
-
-#define TRUE 1
-#define FALSE 0
-
-#define MEMALIGN(a, b, c) a = _aligned_malloc (c, b)
-#define ALIGNED_FREE(x) _aligned_free (x)
-
-int large_use;
-
-#ifndef _WIN32 // Linux
-#include
-#include
-
-static int num;
-
-void SETUP_PRIVILEGES(){}
-
-void CREATE_MEM(void** A,int align,uint64_t size)
-{
- large_use=FALSE;
-
- num=shmget(IPC_PRIVATE,size,IPC_CREAT|SHM_R|SHM_W|SHM_HUGETLB);
- if(num==-1)
- {
- printf("info string LargePages FAILED %llu Mb\n",size>>20);
- MEMALIGN((*A),align,size);
- }
- else
- {
- (*A)=shmat(num,NULL,0x0);
- large_use=TRUE;
- printf("info string LargePages OK %llu Mb\n",size>>20);
- std::cout<<"info string HUGELTB "<<(size>>20)<>20);
- }
-}
-
-void FREE_MEM(void* A)
-{
- if(!A)
- return;
- if(!large_use)
- {
- ALIGNED_FREE(A);
- return;
- }
- shmdt(A);
- shmctl(num,IPC_RMID,NULL);
- large_use=FALSE;
-}
-
-void SETUP_PRIVILEGES(){}
-
-#else
-
-void CREATE_MEM(void** A,int align,uint64_t size)
-{
- large_use=FALSE;
- (*A)=VirtualAlloc(NULL,size,MEM_LARGE_PAGES|MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
- if((*A))
- {
- large_use=TRUE;
- printf("info string %llu Mb LargePages\n",size>>20);
- }
- else
- {
- printf("info string %llu Mb(no LargePages)\n",size>>20);
- MEMALIGN((*A),align,size);
- }
-}
-
-void CREATE_MEM2(void** A,uint64_t size)
-{
- large_use=FALSE;
- (*A)=VirtualAlloc(NULL,size,MEM_LARGE_PAGES|MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
- if((*A))
- {
- large_use=TRUE;
- printf("info string LargePages %llu Mb\n",size>>20);
- }
-}
-
-void FREE_MEM(void* A)
-{
- if(!A)
- return;
- if(!large_use)
- ALIGNED_FREE(A);
- else
- {
- VirtualFree(A,0,MEM_RELEASE);
- large_use=FALSE;
- }
-}
-
-void SETUP_PRIVILEGES()
-{
- HANDLE TH,PROC;
- TOKEN_PRIVILEGES tp;
-
- PROC=GetCurrentProcess();
- OpenProcessToken(PROC,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&TH);
- LookupPrivilegeValue(NULL,TEXT("SeLockMemoryPrivilege"),&tp.Privileges[0].Luid);
- tp.PrivilegeCount=1;
- tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
- AdjustTokenPrivileges(TH,FALSE,&tp,0,NULL,0);
- CloseHandle(TH);
-}
-#endif
diff --git a/Engines/Windows/deepfish/srcD/psqt.cpp b/Engines/Windows/deepfish/srcD/psqt.cpp
deleted file mode 100644
index 60180ad..0000000
--- a/Engines/Windows/deepfish/srcD/psqt.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
-
- Stockfish is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Stockfish is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-#include
-
-#include "types.h"
-
-Value PieceValue[PHASE_NB][PIECE_NB] = {
-{ VALUE_ZERO, PawnValueMg, KnightValueMg, BishopValueMg, RookValueMg, QueenValueMg },
-{ VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg } };
-
-namespace PSQT {
-
-#define S(mg, eg) make_score(mg, eg)
-
-// Bonus[PieceType][Square / 2] contains Piece-Square scores. For each piece
-// type on a given square a (middlegame, endgame) score pair is assigned. Table
-// is defined for files A..D and white side: it is symmetric for black side and
-// second half of the files.
-const Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
- { },
- { // Pawn
- { S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0) },
- { S(-16, 7), S( 1,-4), S( 7, 8), S( 3,-2) },
- { S(-23,-4), S( -7,-5), S( 19, 5), S(24, 4) },
- { S(-22, 3), S(-14, 3), S( 20,-8), S(35,-3) },
- { S(-11, 8), S( 0, 9), S( 3, 7), S(21,-6) },
- { S(-11, 8), S(-13,-5), S( -6, 2), S(-2, 4) },
- { S( -9, 3), S( 15,-9), S( -8, 1), S(-4,18) }
- },
- { // Knight
- { S(-143, -97), S(-96,-82), S(-80,-46), S(-73,-14) },
- { S( -83, -69), S(-43,-55), S(-21,-17), S(-10, 9) },
- { S( -71, -50), S(-22,-39), S( 0, -8), S( 9, 28) },
- { S( -25, -41), S( 18,-25), S( 43, 7), S( 47, 38) },
- { S( -26, -46), S( 16,-25), S( 38, 2), S( 50, 41) },
- { S( -11, -55), S( 37,-38), S( 56, -8), S( 71, 27) },
- { S( -62, -64), S(-17,-50), S( 5,-24), S( 14, 13) },
- { S(-195,-110), S(-66,-90), S(-42,-50), S(-29,-13) }
- },
- { // Bishop
- { S(-54,-68), S(-23,-40), S(-35,-46), S(-44,-28) },
- { S(-30,-43), S( 10,-17), S( 2,-23), S( -9, -5) },
- { S(-19,-32), S( 17, -9), S( 11,-13), S( 1, 8) },
- { S(-21,-36), S( 18,-13), S( 11,-15), S( 0, 7) },
- { S(-21,-36), S( 14,-14), S( 6,-17), S( -1, 3) },
- { S(-27,-35), S( 6,-13), S( 2,-10), S( -8, 1) },
- { S(-33,-44), S( 7,-21), S( -4,-22), S(-12, -4) },
- { S(-45,-65), S(-21,-42), S(-29,-46), S(-39,-27) }
- },
- { // Rook
- { S(-25, 0), S(-16, 0), S(-16, 0), S(-9, 0) },
- { S(-21, 0), S( -8, 0), S( -3, 0), S( 0, 0) },
- { S(-21, 0), S( -9, 0), S( -4, 0), S( 2, 0) },
- { S(-22, 0), S( -6, 0), S( -1, 0), S( 2, 0) },
- { S(-22, 0), S( -7, 0), S( 0, 0), S( 1, 0) },
- { S(-21, 0), S( -7, 0), S( 0, 0), S( 2, 0) },
- { S(-12, 0), S( 4, 0), S( 8, 0), S(12, 0) },
- { S(-23, 0), S(-15, 0), S(-11, 0), S(-5, 0) }
- },
- { // Queen
- { S( 0,-70), S(-3,-57), S(-4,-41), S(-1,-29) },
- { S(-4,-58), S( 6,-30), S( 9,-21), S( 8, -4) },
- { S(-2,-39), S( 6,-17), S( 9, -7), S( 9, 5) },
- { S(-1,-29), S( 8, -5), S(10, 9), S( 7, 17) },
- { S(-3,-27), S( 9, -5), S( 8, 10), S( 7, 23) },
- { S(-2,-40), S( 6,-16), S( 8,-11), S(10, 3) },
- { S(-2,-54), S( 7,-30), S( 7,-21), S( 6, -7) },
- { S(-1,-75), S(-4,-54), S(-1,-44), S( 0,-30) }
- },
- { // King
- { S(291, 28), S(344, 76), S(294,103), S(219,112) },
- { S(289, 70), S(329,119), S(263,170), S(205,159) },
- { S(226,109), S(271,164), S(202,195), S(136,191) },
- { S(204,131), S(212,194), S(175,194), S(137,204) },
- { S(177,132), S(205,187), S(143,224), S( 94,227) },
- { S(147,118), S(188,178), S(113,199), S( 70,197) },
- { S(116, 72), S(158,121), S( 93,142), S( 48,161) },
- { S( 94, 30), S(120, 76), S( 78,101), S( 31,111) }
- }
-};
-
-#undef S
-
-Score psq[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
-
-// init() initializes piece-square tables: the white halves of the tables are
-// copied from Bonus[] adding the piece value, then the black halves of the
-// tables are initialized by flipping and changing the sign of the white scores.
-void init() {
-
- for (PieceType pt = PAWN; pt <= KING; ++pt)
- {
- PieceValue[MG][make_piece(BLACK, pt)] = PieceValue[MG][pt];
- PieceValue[EG][make_piece(BLACK, pt)] = PieceValue[EG][pt];
-
- Score v = make_score(PieceValue[MG][pt], PieceValue[EG][pt]);
-
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
- {
- File f = std::min(file_of(s), FILE_H - file_of(s));
- psq[WHITE][pt][ s] = v + Bonus[pt][rank_of(s)][f];
- psq[BLACK][pt][~s] = -psq[WHITE][pt][s];
- }
- }
-}
-
-} // namespace PSQT
diff --git a/Engines/Windows/deepfish/srcD/syzygy/tbcore.cpp b/Engines/Windows/deepfish/srcD/syzygy/tbcore.cpp
deleted file mode 100644
index f45da95..0000000
--- a/Engines/Windows/deepfish/srcD/syzygy/tbcore.cpp
+++ /dev/null
@@ -1,1378 +0,0 @@
-/*
- Copyright (c) 2011-2013 Ronald de Man
- This file may be redistributed and/or modified without restrictions.
-
- tbcore.c contains engine-independent routines of the tablebase probing code.
- This file should not need too much adaptation to add tablebase probing to
- a particular engine, provided the engine is written in C or C++.
-*/
-
-#include
-#include
-#include
-#include
-#include
-#include
-#ifndef _WIN32
-#include
-#include
-#endif
-#include "tbcore.h"
-
-#define TBMAX_PIECE 254
-#define TBMAX_PAWN 256
-#define HSHMAX 5
-
-#define Swap(a,b) {int tmp=a;a=b;b=tmp;}
-
-#define TB_PAWN 1
-#define TB_KNIGHT 2
-#define TB_BISHOP 3
-#define TB_ROOK 4
-#define TB_QUEEN 5
-#define TB_KING 6
-
-#define TB_WPAWN TB_PAWN
-#define TB_BPAWN (TB_PAWN | 8)
-
-static LOCK_T TB_mutex;
-
-static bool initialized = false;
-static int num_paths = 0;
-static char *path_string = NULL;
-static char **paths = NULL;
-
-static int TBnum_piece, TBnum_pawn;
-static struct TBEntry_piece TB_piece[TBMAX_PIECE];
-static struct TBEntry_pawn TB_pawn[TBMAX_PAWN];
-
-static struct TBHashEntry TB_hash[1 << TBHASHBITS][HSHMAX];
-
-#define DTZ_ENTRIES 64
-
-static struct DTZTableEntry DTZ_table[DTZ_ENTRIES];
-
-static void init_indices(void);
-static uint64 calc_key_from_pcs(int *pcs, int mirror);
-static void free_wdl_entry(struct TBEntry *entry);
-static void free_dtz_entry(struct TBEntry *entry);
-
-static FD open_tb(const char *str, const char *suffix)
-{
- int i;
- FD fd;
- char file[256];
-
- for (i = 0; i < num_paths; i++) {
- strcpy(file, paths[i]);
- strcat(file, "/");
- strcat(file, str);
- strcat(file, suffix);
-#ifndef _WIN32
- fd = open(file, O_RDONLY);
-#else
- fd = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-#endif
- if (fd != FD_ERR) return fd;
- }
- return FD_ERR;
-}
-
-static void close_tb(FD fd)
-{
-#ifndef _WIN32
- close(fd);
-#else
- CloseHandle(fd);
-#endif
-}
-
-static char *map_file(const char *name, const char *suffix, uint64 *mapping)
-{
- FD fd = open_tb(name, suffix);
- if (fd == FD_ERR)
- return NULL;
-#ifndef _WIN32
- struct stat statbuf;
- fstat(fd, &statbuf);
- *mapping = statbuf.st_size;
- char *data = (char *)mmap(NULL, statbuf.st_size, PROT_READ,
- MAP_SHARED, fd, 0);
- if (data == (char *)(-1)) {
- printf("Could not mmap() %s.\n", name);
- exit(1);
- }
-#else
- DWORD size_low, size_high;
- size_low = GetFileSize(fd, &size_high);
-// *size = ((uint64)size_high) << 32 | ((uint64)size_low);
- HANDLE map = CreateFileMapping(fd, NULL, PAGE_READONLY, size_high, size_low,
- NULL);
- if (map == NULL) {
- printf("CreateFileMapping() failed.\n");
- exit(1);
- }
- *mapping = (uint64)map;
- char *data = (char *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
- if (data == NULL) {
- printf("MapViewOfFile() failed, name = %s%s, error = %lu.\n", name, suffix, GetLastError());
- exit(1);
- }
-#endif
- close_tb(fd);
- return data;
-}
-
-#ifndef _WIN32
-static void unmap_file(char *data, uint64 size)
-{
- if (!data) return;
- munmap(data, size);
-}
-#else
-static void unmap_file(char *data, uint64 mapping)
-{
- if (!data) return;
- UnmapViewOfFile(data);
- CloseHandle((HANDLE)mapping);
-}
-#endif
-
-static void add_to_hash(struct TBEntry *ptr, uint64 key)
-{
- int i, hshidx;
-
- hshidx = key >> (64 - TBHASHBITS);
- i = 0;
- while (i < HSHMAX && TB_hash[hshidx][i].ptr)
- i++;
- if (i == HSHMAX) {
- printf("HSHMAX too low!\n");
- exit(1);
- } else {
- TB_hash[hshidx][i].key = key;
- TB_hash[hshidx][i].ptr = ptr;
- }
-}
-
-static char pchr[] = {'K', 'Q', 'R', 'B', 'N', 'P'};
-
-static void init_tb(char *str)
-{
- FD fd;
- struct TBEntry *entry;
- int i, j, pcs[16];
- uint64 key, key2;
- int color;
- char *s;
-
- fd = open_tb(str, WDLSUFFIX);
- if (fd == FD_ERR) return;
- close_tb(fd);
-
- for (i = 0; i < 16; i++)
- pcs[i] = 0;
- color = 0;
- for (s = str; *s; s++)
- switch (*s) {
- case 'P':
- pcs[TB_PAWN | color]++;
- break;
- case 'N':
- pcs[TB_KNIGHT | color]++;
- break;
- case 'B':
- pcs[TB_BISHOP | color]++;
- break;
- case 'R':
- pcs[TB_ROOK | color]++;
- break;
- case 'Q':
- pcs[TB_QUEEN | color]++;
- break;
- case 'K':
- pcs[TB_KING | color]++;
- break;
- case 'v':
- color = 0x08;
- break;
- }
- for (i = 0; i < 8; i++)
- if (pcs[i] != pcs[i+8])
- break;
- key = calc_key_from_pcs(pcs, 0);
- key2 = calc_key_from_pcs(pcs, 1);
- if (pcs[TB_WPAWN] + pcs[TB_BPAWN] == 0) {
- if (TBnum_piece == TBMAX_PIECE) {
- printf("TBMAX_PIECE limit too low!\n");
- exit(1);
- }
- entry = (struct TBEntry *)&TB_piece[TBnum_piece++];
- } else {
- if (TBnum_pawn == TBMAX_PAWN) {
- printf("TBMAX_PAWN limit too low!\n");
- exit(1);
- }
- entry = (struct TBEntry *)&TB_pawn[TBnum_pawn++];
- }
- entry->key = key;
- entry->ready = 0;
- entry->num = 0;
- for (i = 0; i < 16; i++)
- entry->num += (ubyte)pcs[i];
- entry->symmetric = (key == key2);
- entry->has_pawns = (pcs[TB_WPAWN] + pcs[TB_BPAWN] > 0);
- if (entry->num > Tablebases::MaxCardinality)
- Tablebases::MaxCardinality = entry->num;
-
- if (entry->has_pawns) {
- struct TBEntry_pawn *ptr = (struct TBEntry_pawn *)entry;
- ptr->pawns[0] = (ubyte)pcs[TB_WPAWN];
- ptr->pawns[1] = (ubyte)pcs[TB_BPAWN];
- if (pcs[TB_BPAWN] > 0
- && (pcs[TB_WPAWN] == 0 || pcs[TB_BPAWN] < pcs[TB_WPAWN])) {
- ptr->pawns[0] = (ubyte)pcs[TB_BPAWN];
- ptr->pawns[1] = (ubyte)pcs[TB_WPAWN];
- }
- } else {
- struct TBEntry_piece *ptr = (struct TBEntry_piece *)entry;
- for (i = 0, j = 0; i < 16; i++)
- if (pcs[i] == 1) j++;
- if (j >= 3) ptr->enc_type = 0;
- else if (j == 2) ptr->enc_type = 2;
- else { /* only for suicide */
- j = 16;
- for (i = 0; i < 16; i++) {
- if (pcs[i] < j && pcs[i] > 1) j = pcs[i];
- ptr->enc_type = ubyte(1 + j);
- }
- }
- }
- add_to_hash(entry, key);
- if (key2 != key) add_to_hash(entry, key2);
-}
-
-void Tablebases::init(const std::string& path)
-{
- char str[16];
- int i, j, k, l;
-
- if (initialized) {
- free(path_string);
- free(paths);
- struct TBEntry *entry;
- for (i = 0; i < TBnum_piece; i++) {
- entry = (struct TBEntry *)&TB_piece[i];
- free_wdl_entry(entry);
- }
- for (i = 0; i < TBnum_pawn; i++) {
- entry = (struct TBEntry *)&TB_pawn[i];
- free_wdl_entry(entry);
- }
- for (i = 0; i < DTZ_ENTRIES; i++)
- if (DTZ_table[i].entry)
- free_dtz_entry(DTZ_table[i].entry);
- } else {
- init_indices();
- initialized = true;
- }
-
- const char *p = path.c_str();
- if (strlen(p) == 0 || !strcmp(p, "")) return;
- path_string = (char *)malloc(strlen(p) + 1);
- strcpy(path_string, p);
- num_paths = 0;
- for (i = 0;; i++) {
- if (path_string[i] != SEP_CHAR)
- num_paths++;
- while (path_string[i] && path_string[i] != SEP_CHAR)
- i++;
- if (!path_string[i]) break;
- path_string[i] = 0;
- }
- paths = (char **)malloc(num_paths * sizeof(char *));
- for (i = j = 0; i < num_paths; i++) {
- while (!path_string[j]) j++;
- paths[i] = &path_string[j];
- while (path_string[j]) j++;
- }
-
- LOCK_INIT(TB_mutex);
-
- TBnum_piece = TBnum_pawn = 0;
- MaxCardinality = 0;
-
- for (i = 0; i < (1 << TBHASHBITS); i++)
- for (j = 0; j < HSHMAX; j++) {
- TB_hash[i][j].key = 0ULL;
- TB_hash[i][j].ptr = NULL;
- }
-
- for (i = 0; i < DTZ_ENTRIES; i++)
- DTZ_table[i].entry = NULL;
-
- for (i = 1; i < 6; i++) {
- sprintf(str, "K%cvK", pchr[i]);
- init_tb(str);
- }
-
- for (i = 1; i < 6; i++)
- for (j = i; j < 6; j++) {
- sprintf(str, "K%cvK%c", pchr[i], pchr[j]);
- init_tb(str);
- }
-
- for (i = 1; i < 6; i++)
- for (j = i; j < 6; j++) {
- sprintf(str, "K%c%cvK", pchr[i], pchr[j]);
- init_tb(str);
- }
-
- for (i = 1; i < 6; i++)
- for (j = i; j < 6; j++)
- for (k = 1; k < 6; k++) {
- sprintf(str, "K%c%cvK%c", pchr[i], pchr[j], pchr[k]);
- init_tb(str);
- }
-
- for (i = 1; i < 6; i++)
- for (j = i; j < 6; j++)
- for (k = j; k < 6; k++) {
- sprintf(str, "K%c%c%cvK", pchr[i], pchr[j], pchr[k]);
- init_tb(str);
- }
-
- for (i = 1; i < 6; i++)
- for (j = i; j < 6; j++)
- for (k = i; k < 6; k++)
- for (l = (i == k) ? j : k; l < 6; l++) {
- sprintf(str, "K%c%cvK%c%c", pchr[i], pchr[j], pchr[k], pchr[l]);
- init_tb(str);
- }
-
- for (i = 1; i < 6; i++)
- for (j = i; j < 6; j++)
- for (k = j; k < 6; k++)
- for (l = 1; l < 6; l++) {
- sprintf(str, "K%c%c%cvK%c", pchr[i], pchr[j], pchr[k], pchr[l]);
- init_tb(str);
- }
-
- for (i = 1; i < 6; i++)
- for (j = i; j < 6; j++)
- for (k = j; k < 6; k++)
- for (l = k; l < 6; l++) {
- sprintf(str, "K%c%c%c%cvK", pchr[i], pchr[j], pchr[k], pchr[l]);
- init_tb(str);
- }
-
- printf("info string Found %d tablebases.\n", TBnum_piece + TBnum_pawn);
-}
-
-static const signed char offdiag[] = {
- 0,-1,-1,-1,-1,-1,-1,-1,
- 1, 0,-1,-1,-1,-1,-1,-1,
- 1, 1, 0,-1,-1,-1,-1,-1,
- 1, 1, 1, 0,-1,-1,-1,-1,
- 1, 1, 1, 1, 0,-1,-1,-1,
- 1, 1, 1, 1, 1, 0,-1,-1,
- 1, 1, 1, 1, 1, 1, 0,-1,
- 1, 1, 1, 1, 1, 1, 1, 0
-};
-
-static const ubyte triangle[] = {
- 6, 0, 1, 2, 2, 1, 0, 6,
- 0, 7, 3, 4, 4, 3, 7, 0,
- 1, 3, 8, 5, 5, 8, 3, 1,
- 2, 4, 5, 9, 9, 5, 4, 2,
- 2, 4, 5, 9, 9, 5, 4, 2,
- 1, 3, 8, 5, 5, 8, 3, 1,
- 0, 7, 3, 4, 4, 3, 7, 0,
- 6, 0, 1, 2, 2, 1, 0, 6
-};
-
-static const ubyte invtriangle[] = {
- 1, 2, 3, 10, 11, 19, 0, 9, 18, 27
-};
-
-static const ubyte invdiag[] = {
- 0, 9, 18, 27, 36, 45, 54, 63,
- 7, 14, 21, 28, 35, 42, 49, 56
-};
-
-static const ubyte flipdiag[] = {
- 0, 8, 16, 24, 32, 40, 48, 56,
- 1, 9, 17, 25, 33, 41, 49, 57,
- 2, 10, 18, 26, 34, 42, 50, 58,
- 3, 11, 19, 27, 35, 43, 51, 59,
- 4, 12, 20, 28, 36, 44, 52, 60,
- 5, 13, 21, 29, 37, 45, 53, 61,
- 6, 14, 22, 30, 38, 46, 54, 62,
- 7, 15, 23, 31, 39, 47, 55, 63
-};
-
-static const ubyte lower[] = {
- 28, 0, 1, 2, 3, 4, 5, 6,
- 0, 29, 7, 8, 9, 10, 11, 12,
- 1, 7, 30, 13, 14, 15, 16, 17,
- 2, 8, 13, 31, 18, 19, 20, 21,
- 3, 9, 14, 18, 32, 22, 23, 24,
- 4, 10, 15, 19, 22, 33, 25, 26,
- 5, 11, 16, 20, 23, 25, 34, 27,
- 6, 12, 17, 21, 24, 26, 27, 35
-};
-
-static const ubyte diag[] = {
- 0, 0, 0, 0, 0, 0, 0, 8,
- 0, 1, 0, 0, 0, 0, 9, 0,
- 0, 0, 2, 0, 0, 10, 0, 0,
- 0, 0, 0, 3, 11, 0, 0, 0,
- 0, 0, 0, 12, 4, 0, 0, 0,
- 0, 0, 13, 0, 0, 5, 0, 0,
- 0, 14, 0, 0, 0, 0, 6, 0,
- 15, 0, 0, 0, 0, 0, 0, 7
-};
-
-static const ubyte flap[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 6, 12, 18, 18, 12, 6, 0,
- 1, 7, 13, 19, 19, 13, 7, 1,
- 2, 8, 14, 20, 20, 14, 8, 2,
- 3, 9, 15, 21, 21, 15, 9, 3,
- 4, 10, 16, 22, 22, 16, 10, 4,
- 5, 11, 17, 23, 23, 17, 11, 5,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const ubyte ptwist[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 47, 35, 23, 11, 10, 22, 34, 46,
- 45, 33, 21, 9, 8, 20, 32, 44,
- 43, 31, 19, 7, 6, 18, 30, 42,
- 41, 29, 17, 5, 4, 16, 28, 40,
- 39, 27, 15, 3, 2, 14, 26, 38,
- 37, 25, 13, 1, 0, 12, 24, 36,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const ubyte invflap[] = {
- 8, 16, 24, 32, 40, 48,
- 9, 17, 25, 33, 41, 49,
- 10, 18, 26, 34, 42, 50,
- 11, 19, 27, 35, 43, 51
-};
-
-static const ubyte invptwist[] = {
- 52, 51, 44, 43, 36, 35, 28, 27, 20, 19, 12, 11,
- 53, 50, 45, 42, 37, 34, 29, 26, 21, 18, 13, 10,
- 54, 49, 46, 41, 38, 33, 30, 25, 22, 17, 14, 9,
- 55, 48, 47, 40, 39, 32, 31, 24, 23, 16, 15, 8
-};
-
-static const ubyte file_to_file[] = {
- 0, 1, 2, 3, 3, 2, 1, 0
-};
-
-static const short KK_idx[10][64] = {
- { -1, -1, -1, 0, 1, 2, 3, 4,
- -1, -1, -1, 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, -1, -1, -1, 59, 60, 61, 62,
- 63, -1, -1, -1, 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, -1, -1, -1,118,119,120,
- 121,122, -1, -1, -1,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, -1, -1, -1,175,176,177,178,
- 179, -1, -1, -1,180,181,182,183,
- 184, -1, -1, -1,185,186,187,188,
- 189,190,191,192,193,194,195,196,
- 197,198,199,200,201,202,203,204,
- 205,206,207,208,209,210,211,212,
- 213,214,215,216,217,218,219,220,
- 221,222,223,224,225,226,227,228 },
- {229,230, -1, -1, -1,231,232,233,
- 234,235, -1, -1, -1,236,237,238,
- 239,240, -1, -1, -1,241,242,243,
- 244,245,246,247,248,249,250,251,
- 252,253,254,255,256,257,258,259,
- 260,261,262,263,264,265,266,267,
- 268,269,270,271,272,273,274,275,
- 276,277,278,279,280,281,282,283 },
- {284,285,286,287,288,289,290,291,
- 292,293, -1, -1, -1,294,295,296,
- 297,298, -1, -1, -1,299,300,301,
- 302,303, -1, -1, -1,304,305,306,
- 307,308,309,310,311,312,313,314,
- 315,316,317,318,319,320,321,322,
- 323,324,325,326,327,328,329,330,
- 331,332,333,334,335,336,337,338 },
- { -1, -1,339,340,341,342,343,344,
- -1, -1,345,346,347,348,349,350,
- -1, -1,441,351,352,353,354,355,
- -1, -1, -1,442,356,357,358,359,
- -1, -1, -1, -1,443,360,361,362,
- -1, -1, -1, -1, -1,444,363,364,
- -1, -1, -1, -1, -1, -1,445,365,
- -1, -1, -1, -1, -1, -1, -1,446 },
- { -1, -1, -1,366,367,368,369,370,
- -1, -1, -1,371,372,373,374,375,
- -1, -1, -1,376,377,378,379,380,
- -1, -1, -1,447,381,382,383,384,
- -1, -1, -1, -1,448,385,386,387,
- -1, -1, -1, -1, -1,449,388,389,
- -1, -1, -1, -1, -1, -1,450,390,
- -1, -1, -1, -1, -1, -1, -1,451 },
- {452,391,392,393,394,395,396,397,
- -1, -1, -1, -1,398,399,400,401,
- -1, -1, -1, -1,402,403,404,405,
- -1, -1, -1, -1,406,407,408,409,
- -1, -1, -1, -1,453,410,411,412,
- -1, -1, -1, -1, -1,454,413,414,
- -1, -1, -1, -1, -1, -1,455,415,
- -1, -1, -1, -1, -1, -1, -1,456 },
- {457,416,417,418,419,420,421,422,
- -1,458,423,424,425,426,427,428,
- -1, -1, -1, -1, -1,429,430,431,
- -1, -1, -1, -1, -1,432,433,434,
- -1, -1, -1, -1, -1,435,436,437,
- -1, -1, -1, -1, -1,459,438,439,
- -1, -1, -1, -1, -1, -1,460,440,
- -1, -1, -1, -1, -1, -1, -1,461 }
-};
-
-static int binomial[5][64];
-static int pawnidx[5][24];
-static int pfactor[5][4];
-
-static void init_indices(void)
-{
- int i, j, k;
-
-// binomial[k-1][n] = Bin(n, k)
- for (i = 0; i < 5; i++)
- for (j = 0; j < 64; j++) {
- int f = j;
- int l = 1;
- for (k = 1; k <= i; k++) {
- f *= (j - k);
- l *= (k + 1);
- }
- binomial[i][j] = f / l;
- }
-
- for (i = 0; i < 5; i++) {
- int s = 0;
- for (j = 0; j < 6; j++) {
- pawnidx[i][j] = s;
- s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
- }
- pfactor[i][0] = s;
- s = 0;
- for (; j < 12; j++) {
- pawnidx[i][j] = s;
- s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
- }
- pfactor[i][1] = s;
- s = 0;
- for (; j < 18; j++) {
- pawnidx[i][j] = s;
- s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
- }
- pfactor[i][2] = s;
- s = 0;
- for (; j < 24; j++) {
- pawnidx[i][j] = s;
- s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
- }
- pfactor[i][3] = s;
- }
-}
-
-static uint64 encode_piece(struct TBEntry_piece *ptr, ubyte *norm, int *pos, int *factor)
-{
- uint64 idx;
- int i, j, k, m, l, p;
- int n = ptr->num;
-
- if (pos[0] & 0x04) {
- for (i = 0; i < n; i++)
- pos[i] ^= 0x07;
- }
- if (pos[0] & 0x20) {
- for (i = 0; i < n; i++)
- pos[i] ^= 0x38;
- }
-
- for (i = 0; i < n; i++)
- if (offdiag[pos[i]]) break;
- if (i < (ptr->enc_type == 0 ? 3 : 2) && offdiag[pos[i]] > 0)
- for (i = 0; i < n; i++)
- pos[i] = flipdiag[pos[i]];
-
- switch (ptr->enc_type) {
-
- case 0: /* 111 */
- i = (pos[1] > pos[0]);
- j = (pos[2] > pos[0]) + (pos[2] > pos[1]);
-
- if (offdiag[pos[0]])
- idx = triangle[pos[0]] * 63*62 + (pos[1] - i) * 62 + (pos[2] - j);
- else if (offdiag[pos[1]])
- idx = 6*63*62 + diag[pos[0]] * 28*62 + lower[pos[1]] * 62 + pos[2] - j;
- else if (offdiag[pos[2]])
- idx = 6*63*62 + 4*28*62 + (diag[pos[0]]) * 7*28 + (diag[pos[1]] - i) * 28 + lower[pos[2]];
- else
- idx = 6*63*62 + 4*28*62 + 4*7*28 + (diag[pos[0]] * 7*6) + (diag[pos[1]] - i) * 6 + (diag[pos[2]] - j);
- i = 3;
- break;
-
- case 1: /* K3 */
- j = (pos[2] > pos[0]) + (pos[2] > pos[1]);
-
- idx = KK_idx[triangle[pos[0]]][pos[1]];
- if (idx < 441)
- idx = idx + 441 * (pos[2] - j);
- else {
- idx = 441*62 + (idx - 441) + 21 * lower[pos[2]];
- if (!offdiag[pos[2]])
- idx -= j * 21;
- }
- i = 3;
- break;
-
- default: /* K2 */
- idx = KK_idx[triangle[pos[0]]][pos[1]];
- i = 2;
- break;
- }
- idx *= factor[0];
-
- for (; i < n;) {
- int t = norm[i];
- for (j = i; j < i + t; j++)
- for (k = j + 1; k < i + t; k++)
- if (pos[j] > pos[k]) Swap(pos[j], pos[k]);
- int s = 0;
- for (m = i; m < i + t; m++) {
- p = pos[m];
- for (l = 0, j = 0; l < i; l++)
- j += (p > pos[l]);
- s += binomial[m - i][p - j];
- }
- idx += ((uint64)s) * ((uint64)factor[i]);
- i += t;
- }
-
- return idx;
-}
-
-// determine file of leftmost pawn and sort pawns
-static int pawn_file(struct TBEntry_pawn *ptr, int *pos)
-{
- int i;
-
- for (i = 1; i < ptr->pawns[0]; i++)
- if (flap[pos[0]] > flap[pos[i]])
- Swap(pos[0], pos[i]);
-
- return file_to_file[pos[0] & 0x07];
-}
-
-static uint64 encode_pawn(struct TBEntry_pawn *ptr, ubyte *norm, int *pos, int *factor)
-{
- uint64 idx;
- int i, j, k, m, s, t;
- int n = ptr->num;
-
- if (pos[0] & 0x04)
- for (i = 0; i < n; i++)
- pos[i] ^= 0x07;
-
- for (i = 1; i < ptr->pawns[0]; i++)
- for (j = i + 1; j < ptr->pawns[0]; j++)
- if (ptwist[pos[i]] < ptwist[pos[j]])
- Swap(pos[i], pos[j]);
-
- t = ptr->pawns[0] - 1;
- idx = pawnidx[t][flap[pos[0]]];
- for (i = t; i > 0; i--)
- idx += binomial[t - i][ptwist[pos[i]]];
- idx *= factor[0];
-
-// remaining pawns
- i = ptr->pawns[0];
- t = i + ptr->pawns[1];
- if (t > i) {
- for (j = i; j < t; j++)
- for (k = j + 1; k < t; k++)
- if (pos[j] > pos[k]) Swap(pos[j], pos[k]);
- s = 0;
- for (m = i; m < t; m++) {
- int p = pos[m];
- for (k = 0, j = 0; k < i; k++)
- j += (p > pos[k]);
- s += binomial[m - i][p - j - 8];
- }
- idx += ((uint64)s) * ((uint64)factor[i]);
- i = t;
- }
-
- for (; i < n;) {
- t = norm[i];
- for (j = i; j < i + t; j++)
- for (k = j + 1; k < i + t; k++)
- if (pos[j] > pos[k]) Swap(pos[j], pos[k]);
- s = 0;
- for (m = i; m < i + t; m++) {
- int p = pos[m];
- for (k = 0, j = 0; k < i; k++)
- j += (p > pos[k]);
- s += binomial[m - i][p - j];
- }
- idx += ((uint64)s) * ((uint64)factor[i]);
- i += t;
- }
-
- return idx;
-}
-
-// place k like pieces on n squares
-static int subfactor(int k, int n)
-{
- int i, f, l;
-
- f = n;
- l = 1;
- for (i = 1; i < k; i++) {
- f *= n - i;
- l *= i + 1;
- }
-
- return f / l;
-}
-
-static uint64 calc_factors_piece(int *factor, int num, int order, ubyte *norm, ubyte enc_type)
-{
- int i, k, n;
- uint64 f;
- static int pivfac[] = { 31332, 28056, 462 };
-
- n = 64 - norm[0];
-
- f = 1;
- for (i = norm[0], k = 0; i < num || k == order; k++) {
- if (k == order) {
- factor[0] = static_cast(f);
- f *= pivfac[enc_type];
- } else {
- factor[i] = static_cast(f);
- f *= subfactor(norm[i], n);
- n -= norm[i];
- i += norm[i];
- }
- }
-
- return f;
-}
-
-static uint64 calc_factors_pawn(int *factor, int num, int order, int order2, ubyte *norm, int file)
-{
- int i, k, n;
- uint64 f;
-
- i = norm[0];
- if (order2 < 0x0f) i += norm[i];
- n = 64 - i;
-
- f = 1;
- for (k = 0; i < num || k == order || k == order2; k++) {
- if (k == order) {
- factor[0] = static_cast(f);
- f *= pfactor[norm[0] - 1][file];
- } else if (k == order2) {
- factor[norm[0]] = static_cast(f);
- f *= subfactor(norm[norm[0]], 48 - norm[0]);
- } else {
- factor[i] = static_cast(f);
- f *= subfactor(norm[i], n);
- n -= norm[i];
- i += norm[i];
- }
- }
-
- return f;
-}
-
-static void set_norm_piece(struct TBEntry_piece *ptr, ubyte *norm, ubyte *pieces)
-{
- int i, j;
-
- for (i = 0; i < ptr->num; i++)
- norm[i] = 0;
-
- switch (ptr->enc_type) {
- case 0:
- norm[0] = 3;
- break;
- case 2:
- norm[0] = 2;
- break;
- default:
- norm[0] = ubyte(ptr->enc_type - 1);
- break;
- }
-
- for (i = norm[0]; i < ptr->num; i += norm[i])
- for (j = i; j < ptr->num && pieces[j] == pieces[i]; j++)
- norm[i]++;
-}
-
-static void set_norm_pawn(struct TBEntry_pawn *ptr, ubyte *norm, ubyte *pieces)
-{
- int i, j;
-
- for (i = 0; i < ptr->num; i++)
- norm[i] = 0;
-
- norm[0] = ptr->pawns[0];
- if (ptr->pawns[1]) norm[ptr->pawns[0]] = ptr->pawns[1];
-
- for (i = ptr->pawns[0] + ptr->pawns[1]; i < ptr->num; i += norm[i])
- for (j = i; j < ptr->num && pieces[j] == pieces[i]; j++)
- norm[i]++;
-}
-
-static void setup_pieces_piece(struct TBEntry_piece *ptr, unsigned char *data, uint64 *tb_size)
-{
- int i;
- int order;
-
- for (i = 0; i < ptr->num; i++)
- ptr->pieces[0][i] = ubyte(data[i + 1] & 0x0f);
- order = data[0] & 0x0f;
- set_norm_piece(ptr, ptr->norm[0], ptr->pieces[0]);
- tb_size[0] = calc_factors_piece(ptr->factor[0], ptr->num, order, ptr->norm[0], ptr->enc_type);
-
- for (i = 0; i < ptr->num; i++)
- ptr->pieces[1][i] = ubyte(data[i + 1] >> 4);
- order = data[0] >> 4;
- set_norm_piece(ptr, ptr->norm[1], ptr->pieces[1]);
- tb_size[1] = calc_factors_piece(ptr->factor[1], ptr->num, order, ptr->norm[1], ptr->enc_type);
-}
-
-static void setup_pieces_piece_dtz(struct DTZEntry_piece *ptr, unsigned char *data, uint64 *tb_size)
-{
- int i;
- int order;
-
- for (i = 0; i < ptr->num; i++)
- ptr->pieces[i] = ubyte(data[i + 1] & 0x0f);
- order = data[0] & 0x0f;
- set_norm_piece((struct TBEntry_piece *)ptr, ptr->norm, ptr->pieces);
- tb_size[0] = calc_factors_piece(ptr->factor, ptr->num, order, ptr->norm, ptr->enc_type);
-}
-
-static void setup_pieces_pawn(struct TBEntry_pawn *ptr, unsigned char *data, uint64 *tb_size, int f)
-{
- int i, j;
- int order, order2;
-
- j = 1 + (ptr->pawns[1] > 0);
- order = data[0] & 0x0f;
- order2 = ptr->pawns[1] ? (data[1] & 0x0f) : 0x0f;
- for (i = 0; i < ptr->num; i++)
- ptr->file[f].pieces[0][i] = ubyte(data[i + j] & 0x0f);
- set_norm_pawn(ptr, ptr->file[f].norm[0], ptr->file[f].pieces[0]);
- tb_size[0] = calc_factors_pawn(ptr->file[f].factor[0], ptr->num, order, order2, ptr->file[f].norm[0], f);
-
- order = data[0] >> 4;
- order2 = ptr->pawns[1] ? (data[1] >> 4) : 0x0f;
- for (i = 0; i < ptr->num; i++)
- ptr->file[f].pieces[1][i] = ubyte(data[i + j] >> 4);
- set_norm_pawn(ptr, ptr->file[f].norm[1], ptr->file[f].pieces[1]);
- tb_size[1] = calc_factors_pawn(ptr->file[f].factor[1], ptr->num, order, order2, ptr->file[f].norm[1], f);
-}
-
-static void setup_pieces_pawn_dtz(struct DTZEntry_pawn *ptr, unsigned char *data, uint64 *tb_size, int f)
-{
- int i, j;
- int order, order2;
-
- j = 1 + (ptr->pawns[1] > 0);
- order = data[0] & 0x0f;
- order2 = ptr->pawns[1] ? (data[1] & 0x0f) : 0x0f;
- for (i = 0; i < ptr->num; i++)
- ptr->file[f].pieces[i] = ubyte(data[i + j] & 0x0f);
- set_norm_pawn((struct TBEntry_pawn *)ptr, ptr->file[f].norm, ptr->file[f].pieces);
- tb_size[0] = calc_factors_pawn(ptr->file[f].factor, ptr->num, order, order2, ptr->file[f].norm, f);
-}
-
-static void calc_symlen(struct PairsData *d, int s, char *tmp)
-{
- int s1, s2;
-
- ubyte* w = d->sympat + 3 * s;
- s2 = (w[2] << 4) | (w[1] >> 4);
- if (s2 == 0x0fff)
- d->symlen[s] = 0;
- else {
- s1 = ((w[1] & 0xf) << 8) | w[0];
- if (!tmp[s1]) calc_symlen(d, s1, tmp);
- if (!tmp[s2]) calc_symlen(d, s2, tmp);
- d->symlen[s] = ubyte(d->symlen[s1] + d->symlen[s2] + 1);
- }
- tmp[s] = 1;
-}
-
-ushort ReadUshort(ubyte* d) {
- return ushort(d[0] | (d[1] << 8));
-}
-
-uint32 ReadUint32(ubyte* d) {
- return d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
-}
-
-static struct PairsData *setup_pairs(unsigned char *data, uint64 tb_size, uint64 *size, unsigned char **next, ubyte *flags, int wdl)
-{
- struct PairsData *d;
- int i;
-
- *flags = data[0];
- if (data[0] & 0x80) {
- d = (struct PairsData *)malloc(sizeof(struct PairsData));
- d->idxbits = 0;
- if (wdl)
- d->min_len = data[1];
- else
- d->min_len = 0;
- *next = data + 2;
- size[0] = size[1] = size[2] = 0;
- return d;
- }
-
- int blocksize = data[1];
- int idxbits = data[2];
- int real_num_blocks = ReadUint32(&data[4]);
- int num_blocks = real_num_blocks + *(ubyte *)(&data[3]);
- int max_len = data[8];
- int min_len = data[9];
- int h = max_len - min_len + 1;
- int num_syms = ReadUshort(&data[10 + 2 * h]);
- d = (struct PairsData *)malloc(sizeof(struct PairsData) + (h - 1) * sizeof(base_t) + num_syms);
- d->blocksize = blocksize;
- d->idxbits = idxbits;
- d->offset = (ushort*)(&data[10]);
- d->symlen = ((ubyte *)d) + sizeof(struct PairsData) + (h - 1) * sizeof(base_t);
- d->sympat = &data[12 + 2 * h];
- d->min_len = min_len;
- *next = &data[12 + 2 * h + 3 * num_syms + (num_syms & 1)];
-
- uint64 num_indices = (tb_size + (1ULL << idxbits) - 1) >> idxbits;
- size[0] = 6ULL * num_indices;
- size[1] = 2ULL * num_blocks;
- size[2] = (1ULL << blocksize) * real_num_blocks;
-
- // char tmp[num_syms];
- char tmp[4096];
- for (i = 0; i < num_syms; i++)
- tmp[i] = 0;
- for (i = 0; i < num_syms; i++)
- if (!tmp[i])
- calc_symlen(d, i, tmp);
-
- d->base[h - 1] = 0;
- for (i = h - 2; i >= 0; i--)
- d->base[i] = (d->base[i + 1] + ReadUshort((ubyte*)(d->offset + i)) - ReadUshort((ubyte*)(d->offset + i + 1))) / 2;
- for (i = 0; i < h; i++)
- d->base[i] <<= 64 - (min_len + i);
-
- d->offset -= d->min_len;
-
- return d;
-}
-
-static int init_table_wdl(struct TBEntry *entry, char *str)
-{
- ubyte *next;
- int f, s;
- uint64 tb_size[8];
- uint64 size[8 * 3];
- ubyte flags;
-
- // first mmap the table into memory
-
- entry->data = map_file(str, WDLSUFFIX, &entry->mapping);
- if (!entry->data) {
- printf("Could not find %s" WDLSUFFIX, str);
- return 0;
- }
-
- ubyte *data = (ubyte *)entry->data;
- if (data[0] != WDL_MAGIC[0] ||
- data[1] != WDL_MAGIC[1] ||
- data[2] != WDL_MAGIC[2] ||
- data[3] != WDL_MAGIC[3]) {
- printf("Corrupted table.\n");
- unmap_file(entry->data, entry->mapping);
- entry->data = 0;
- return 0;
- }
-
- int split = data[4] & 0x01;
- int files = data[4] & 0x02 ? 4 : 1;
-
- data += 5;
-
- if (!entry->has_pawns) {
- struct TBEntry_piece *ptr = (struct TBEntry_piece *)entry;
- setup_pieces_piece(ptr, data, &tb_size[0]);
- data += ptr->num + 1;
- data += ((uintptr_t)data) & 0x01;
-
- ptr->precomp[0] = setup_pairs(data, tb_size[0], &size[0], &next, &flags, 1);
- data = next;
- if (split) {
- ptr->precomp[1] = setup_pairs(data, tb_size[1], &size[3], &next, &flags, 1);
- data = next;
- } else
- ptr->precomp[1] = NULL;
-
- ptr->precomp[0]->indextable = (char *)data;
- data += size[0];
- if (split) {
- ptr->precomp[1]->indextable = (char *)data;
- data += size[3];
- }
-
- ptr->precomp[0]->sizetable = (ushort *)data;
- data += size[1];
- if (split) {
- ptr->precomp[1]->sizetable = (ushort *)data;
- data += size[4];
- }
-
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
- ptr->precomp[0]->data = data;
- data += size[2];
- if (split) {
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
- ptr->precomp[1]->data = data;
- }
- } else {
- struct TBEntry_pawn *ptr = (struct TBEntry_pawn *)entry;
- s = 1 + (ptr->pawns[1] > 0);
- for (f = 0; f < 4; f++) {
- setup_pieces_pawn((struct TBEntry_pawn *)ptr, data, &tb_size[2 * f], f);
- data += ptr->num + s;
- }
- data += ((uintptr_t)data) & 0x01;
-
- for (f = 0; f < files; f++) {
- ptr->file[f].precomp[0] = setup_pairs(data, tb_size[2 * f], &size[6 * f], &next, &flags, 1);
- data = next;
- if (split) {
- ptr->file[f].precomp[1] = setup_pairs(data, tb_size[2 * f + 1], &size[6 * f + 3], &next, &flags, 1);
- data = next;
- } else
- ptr->file[f].precomp[1] = NULL;
- }
-
- for (f = 0; f < files; f++) {
- ptr->file[f].precomp[0]->indextable = (char *)data;
- data += size[6 * f];
- if (split) {
- ptr->file[f].precomp[1]->indextable = (char *)data;
- data += size[6 * f + 3];
- }
- }
-
- for (f = 0; f < files; f++) {
- ptr->file[f].precomp[0]->sizetable = (ushort *)data;
- data += size[6 * f + 1];
- if (split) {
- ptr->file[f].precomp[1]->sizetable = (ushort *)data;
- data += size[6 * f + 4];
- }
- }
-
- for (f = 0; f < files; f++) {
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
- ptr->file[f].precomp[0]->data = data;
- data += size[6 * f + 2];
- if (split) {
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
- ptr->file[f].precomp[1]->data = data;
- data += size[6 * f + 5];
- }
- }
- }
-
- return 1;
-}
-
-static int init_table_dtz(struct TBEntry *entry)
-{
- ubyte *data = (ubyte *)entry->data;
- ubyte *next;
- int f, s;
- uint64 tb_size[4];
- uint64 size[4 * 3];
-
- if (!data)
- return 0;
-
- if (data[0] != DTZ_MAGIC[0] ||
- data[1] != DTZ_MAGIC[1] ||
- data[2] != DTZ_MAGIC[2] ||
- data[3] != DTZ_MAGIC[3]) {
- printf("Corrupted table.\n");
- return 0;
- }
-
- int files = data[4] & 0x02 ? 4 : 1;
-
- data += 5;
-
- if (!entry->has_pawns) {
- struct DTZEntry_piece *ptr = (struct DTZEntry_piece *)entry;
- setup_pieces_piece_dtz(ptr, data, &tb_size[0]);
- data += ptr->num + 1;
- data += ((uintptr_t)data) & 0x01;
-
- ptr->precomp = setup_pairs(data, tb_size[0], &size[0], &next, &(ptr->flags), 0);
- data = next;
-
- ptr->map = data;
- if (ptr->flags & 2) {
- int i;
- for (i = 0; i < 4; i++) {
- ptr->map_idx[i] = static_cast(data + 1 - ptr->map);
- data += 1 + data[0];
- }
- data += ((uintptr_t)data) & 0x01;
- }
-
- ptr->precomp->indextable = (char *)data;
- data += size[0];
-
- ptr->precomp->sizetable = (ushort *)data;
- data += size[1];
-
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
- ptr->precomp->data = data;
- data += size[2];
- } else {
- struct DTZEntry_pawn *ptr = (struct DTZEntry_pawn *)entry;
- s = 1 + (ptr->pawns[1] > 0);
- for (f = 0; f < 4; f++) {
- setup_pieces_pawn_dtz(ptr, data, &tb_size[f], f);
- data += ptr->num + s;
- }
- data += ((uintptr_t)data) & 0x01;
-
- for (f = 0; f < files; f++) {
- ptr->file[f].precomp = setup_pairs(data, tb_size[f], &size[3 * f], &next, &(ptr->flags[f]), 0);
- data = next;
- }
-
- ptr->map = data;
- for (f = 0; f < files; f++) {
- if (ptr->flags[f] & 2) {
- int i;
- for (i = 0; i < 4; i++) {
- ptr->map_idx[f][i] = static_cast(data + 1 - ptr->map);
- data += 1 + data[0];
- }
- }
- }
- data += ((uintptr_t)data) & 0x01;
-
- for (f = 0; f < files; f++) {
- ptr->file[f].precomp->indextable = (char *)data;
- data += size[3 * f];
- }
-
- for (f = 0; f < files; f++) {
- ptr->file[f].precomp->sizetable = (ushort *)data;
- data += size[3 * f + 1];
- }
-
- for (f = 0; f < files; f++) {
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
- ptr->file[f].precomp->data = data;
- data += size[3 * f + 2];
- }
- }
-
- return 1;
-}
-
-template
-static ubyte decompress_pairs(struct PairsData *d, uint64 idx)
-{
- if (!d->idxbits)
- return ubyte(d->min_len);
-
- uint32 mainidx = static_cast(idx >> d->idxbits);
- int litidx = (idx & ((1ULL << d->idxbits) - 1)) - (1ULL << (d->idxbits - 1));
- uint32 block = *(uint32 *)(d->indextable + 6 * mainidx);
- if (!LittleEndian)
- block = BSWAP32(block);
-
- ushort idxOffset = *(ushort *)(d->indextable + 6 * mainidx + 4);
- if (!LittleEndian)
- idxOffset = ushort((idxOffset << 8) | (idxOffset >> 8));
- litidx += idxOffset;
-
- if (litidx < 0) {
- do {
- litidx += d->sizetable[--block] + 1;
- } while (litidx < 0);
- } else {
- while (litidx > d->sizetable[block])
- litidx -= d->sizetable[block++] + 1;
- }
-
- uint32 *ptr = (uint32 *)(d->data + (block << d->blocksize));
-
- int m = d->min_len;
- ushort *offset = d->offset;
- base_t *base = d->base - m;
- ubyte *symlen = d->symlen;
- int sym, bitcnt;
-
- uint64 code = *((uint64 *)ptr);
- if (LittleEndian)
- code = BSWAP64(code);
-
- ptr += 2;
- bitcnt = 0; // number of "empty bits" in code
- for (;;) {
- int l = m;
- while (code < base[l]) l++;
- sym = offset[l];
- if (!LittleEndian)
- sym = ((sym & 0xff) << 8) | (sym >> 8);
- sym += static_cast((code - base[l]) >> (64 - l));
- if (litidx < (int)symlen[sym] + 1) break;
- litidx -= (int)symlen[sym] + 1;
- code <<= l;
- bitcnt += l;
- if (bitcnt >= 32) {
- bitcnt -= 32;
- uint32 tmp = *ptr++;
- if (LittleEndian)
- tmp = BSWAP32(tmp);
- code |= ((uint64)tmp) << bitcnt;
- }
- }
-
- ubyte *sympat = d->sympat;
- while (symlen[sym] != 0) {
- ubyte* w = sympat + (3 * sym);
- int s1 = ((w[1] & 0xf) << 8) | w[0];
- if (litidx < (int)symlen[s1] + 1)
- sym = s1;
- else {
- litidx -= (int)symlen[s1] + 1;
- sym = (w[2] << 4) | (w[1] >> 4);
- }
- }
-
- return sympat[3 * sym];
-}
-
-void load_dtz_table(char *str, uint64 key1, uint64 key2)
-{
- int i;
- struct TBEntry *ptr, *ptr3;
- struct TBHashEntry *ptr2;
-
- DTZ_table[0].key1 = key1;
- DTZ_table[0].key2 = key2;
- DTZ_table[0].entry = NULL;
-
- // find corresponding WDL entry
- ptr2 = TB_hash[key1 >> (64 - TBHASHBITS)];
- for (i = 0; i < HSHMAX; i++)
- if (ptr2[i].key == key1) break;
- if (i == HSHMAX) return;
- ptr = ptr2[i].ptr;
-
- ptr3 = (struct TBEntry *)malloc(ptr->has_pawns
- ? sizeof(struct DTZEntry_pawn)
- : sizeof(struct DTZEntry_piece));
-
- ptr3->data = map_file(str, DTZSUFFIX, &ptr3->mapping);
- ptr3->key = ptr->key;
- ptr3->num = ptr->num;
- ptr3->symmetric = ptr->symmetric;
- ptr3->has_pawns = ptr->has_pawns;
- if (ptr3->has_pawns) {
- struct DTZEntry_pawn *entry = (struct DTZEntry_pawn *)ptr3;
- entry->pawns[0] = ((struct TBEntry_pawn *)ptr)->pawns[0];
- entry->pawns[1] = ((struct TBEntry_pawn *)ptr)->pawns[1];
- } else {
- struct DTZEntry_piece *entry = (struct DTZEntry_piece *)ptr3;
- entry->enc_type = ((struct TBEntry_piece *)ptr)->enc_type;
- }
- if (!init_table_dtz(ptr3))
- free(ptr3);
- else
- DTZ_table[0].entry = ptr3;
-}
-
-static void free_wdl_entry(struct TBEntry *entry)
-{
- unmap_file(entry->data, entry->mapping);
- if (!entry->has_pawns) {
- struct TBEntry_piece *ptr = (struct TBEntry_piece *)entry;
- free(ptr->precomp[0]);
- if (ptr->precomp[1])
- free(ptr->precomp[1]);
- } else {
- struct TBEntry_pawn *ptr = (struct TBEntry_pawn *)entry;
- int f;
- for (f = 0; f < 4; f++) {
- free(ptr->file[f].precomp[0]);
- if (ptr->file[f].precomp[1])
- free(ptr->file[f].precomp[1]);
- }
- }
-}
-
-static void free_dtz_entry(struct TBEntry *entry)
-{
- unmap_file(entry->data, entry->mapping);
- if (!entry->has_pawns) {
- struct DTZEntry_piece *ptr = (struct DTZEntry_piece *)entry;
- free(ptr->precomp);
- } else {
- struct DTZEntry_pawn *ptr = (struct DTZEntry_pawn *)entry;
- int f;
- for (f = 0; f < 4; f++)
- free(ptr->file[f].precomp);
- }
- free(entry);
-}
-
-static int wdl_to_map[5] = { 1, 3, 0, 2, 0 };
-static ubyte pa_flags[5] = { 8, 0, 0, 0, 4 };
-
diff --git a/Engines/Windows/deepfish/srcD/syzygy/tbcore.h b/Engines/Windows/deepfish/srcD/syzygy/tbcore.h
deleted file mode 100644
index cdaf2ac..0000000
--- a/Engines/Windows/deepfish/srcD/syzygy/tbcore.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- Copyright (c) 2011-2013 Ronald de Man
-*/
-
-#ifndef TBCORE_H
-#define TBCORE_H
-
-#ifndef _WIN32
-#include
-#define SEP_CHAR ':'
-#define FD int
-#define FD_ERR -1
-#else
-#include
-#define SEP_CHAR ';'
-#define FD HANDLE
-#define FD_ERR INVALID_HANDLE_VALUE
-#endif
-
-#ifndef _WIN32
-#define LOCK_T pthread_mutex_t
-#define LOCK_INIT(x) pthread_mutex_init(&(x), NULL)
-#define LOCK(x) pthread_mutex_lock(&(x))
-#define UNLOCK(x) pthread_mutex_unlock(&(x))
-#else
-#define LOCK_T HANDLE
-#define LOCK_INIT(x) do { x = CreateMutex(NULL, FALSE, NULL); } while (0)
-#define LOCK(x) WaitForSingleObject(x, INFINITE)
-#define UNLOCK(x) ReleaseMutex(x)
-#endif
-
-#ifndef _MSC_VER
-#define BSWAP32(v) __builtin_bswap32(v)
-#define BSWAP64(v) __builtin_bswap64(v)
-#else
-#define BSWAP32(v) _byteswap_ulong(v)
-#define BSWAP64(v) _byteswap_uint64(v)
-#endif
-
-#define WDLSUFFIX ".rtbw"
-#define DTZSUFFIX ".rtbz"
-#define WDLDIR "RTBWDIR"
-#define DTZDIR "RTBZDIR"
-#define TBPIECES 6
-
-typedef unsigned long long uint64;
-typedef unsigned int uint32;
-typedef unsigned char ubyte;
-typedef unsigned short ushort;
-
-const ubyte WDL_MAGIC[4] = { 0x71, 0xe8, 0x23, 0x5d };
-const ubyte DTZ_MAGIC[4] = { 0xd7, 0x66, 0x0c, 0xa5 };
-
-#define TBHASHBITS 10
-
-struct TBHashEntry;
-
-typedef uint64 base_t;
-
-struct PairsData {
- char *indextable;
- ushort *sizetable;
- ubyte *data;
- ushort *offset;
- ubyte *symlen;
- ubyte *sympat;
- int blocksize;
- int idxbits;
- int min_len;
- base_t base[1]; // C++ complains about base[]...
-};
-
-struct TBEntry {
- char *data;
- uint64 key;
- uint64 mapping;
- ubyte ready;
- ubyte num;
- ubyte symmetric;
- ubyte has_pawns;
-}
-#ifndef _WIN32
-__attribute__((__may_alias__))
-#endif
-;
-
-struct TBEntry_piece {
- char *data;
- uint64 key;
- uint64 mapping;
- ubyte ready;
- ubyte num;
- ubyte symmetric;
- ubyte has_pawns;
- ubyte enc_type;
- struct PairsData *precomp[2];
- int factor[2][TBPIECES];
- ubyte pieces[2][TBPIECES];
- ubyte norm[2][TBPIECES];
-};
-
-struct TBEntry_pawn {
- char *data;
- uint64 key;
- uint64 mapping;
- ubyte ready;
- ubyte num;
- ubyte symmetric;
- ubyte has_pawns;
- ubyte pawns[2];
- struct {
- struct PairsData *precomp[2];
- int factor[2][TBPIECES];
- ubyte pieces[2][TBPIECES];
- ubyte norm[2][TBPIECES];
- } file[4];
-};
-
-struct DTZEntry_piece {
- char *data;
- uint64 key;
- uint64 mapping;
- ubyte ready;
- ubyte num;
- ubyte symmetric;
- ubyte has_pawns;
- ubyte enc_type;
- struct PairsData *precomp;
- int factor[TBPIECES];
- ubyte pieces[TBPIECES];
- ubyte norm[TBPIECES];
- ubyte flags; // accurate, mapped, side
- ushort map_idx[4];
- ubyte *map;
-};
-
-struct DTZEntry_pawn {
- char *data;
- uint64 key;
- uint64 mapping;
- ubyte ready;
- ubyte num;
- ubyte symmetric;
- ubyte has_pawns;
- ubyte pawns[2];
- struct {
- struct PairsData *precomp;
- int factor[TBPIECES];
- ubyte pieces[TBPIECES];
- ubyte norm[TBPIECES];
- } file[4];
- ubyte flags[4];
- ushort map_idx[4][4];
- ubyte *map;
-};
-
-struct TBHashEntry {
- uint64 key;
- struct TBEntry *ptr;
-};
-
-struct DTZTableEntry {
- uint64 key1;
- uint64 key2;
- struct TBEntry *entry;
-};
-
-#endif
-
diff --git a/Engines/Windows/deepfish/srcD/syzygy/tbprobe.cpp b/Engines/Windows/deepfish/srcD/syzygy/tbprobe.cpp
deleted file mode 100644
index 6f6627a..0000000
--- a/Engines/Windows/deepfish/srcD/syzygy/tbprobe.cpp
+++ /dev/null
@@ -1,824 +0,0 @@
-/*
- Copyright (c) 2013 Ronald de Man
- This file may be redistributed and/or modified without restrictions.
-
- tbprobe.cpp contains the Stockfish-specific routines of the
- tablebase probing code. It should be relatively easy to adapt
- this code to other chess engines.
-*/
-
-#define NOMINMAX
-
-#include
-
-#include "../position.h"
-#include "../movegen.h"
-#include "../bitboard.h"
-#include "../search.h"
-
-#include "tbprobe.h"
-#include "tbcore.h"
-
-#include "tbcore.cpp"
-
-namespace Zobrist {
- extern Key psq[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
-}
-
-int Tablebases::MaxCardinality = 0;
-
-// Given a position with 6 or fewer pieces, produce a text string
-// of the form KQPvKRP, where "KQP" represents the white pieces if
-// mirror == 0 and the black pieces if mirror == 1.
-static void prt_str(Position& pos, char *str, int mirror)
-{
- Color color;
- PieceType pt;
- int i;
-
- color = !mirror ? WHITE : BLACK;
- for (pt = KING; pt >= PAWN; --pt)
- for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
- *str++ = pchr[6 - pt];
- *str++ = 'v';
- color = ~color;
- for (pt = KING; pt >= PAWN; --pt)
- for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
- *str++ = pchr[6 - pt];
- *str++ = 0;
-}
-
-// Given a position, produce a 64-bit material signature key.
-// If the engine supports such a key, it should equal the engine's key.
-static uint64 calc_key(Position& pos, int mirror)
-{
- Color color;
- PieceType pt;
- int i;
- uint64 key = 0;
-
- color = !mirror ? WHITE : BLACK;
- for (pt = PAWN; pt <= KING; ++pt)
- for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
- key ^= Zobrist::psq[WHITE][pt][i - 1];
- color = ~color;
- for (pt = PAWN; pt <= KING; ++pt)
- for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
- key ^= Zobrist::psq[BLACK][pt][i - 1];
-
- return key;
-}
-
-// Produce a 64-bit material key corresponding to the material combination
-// defined by pcs[16], where pcs[1], ..., pcs[6] is the number of white
-// pawns, ..., kings and pcs[9], ..., pcs[14] is the number of black
-// pawns, ..., kings.
-static uint64 calc_key_from_pcs(int *pcs, int mirror)
-{
- int color;
- PieceType pt;
- int i;
- uint64 key = 0;
-
- color = !mirror ? 0 : 8;
- for (pt = PAWN; pt <= KING; ++pt)
- for (i = 0; i < pcs[color + pt]; i++)
- key ^= Zobrist::psq[WHITE][pt][i];
- color ^= 8;
- for (pt = PAWN; pt <= KING; ++pt)
- for (i = 0; i < pcs[color + pt]; i++)
- key ^= Zobrist::psq[BLACK][pt][i];
-
- return key;
-}
-
-bool is_little_endian() {
- union {
- int i;
- char c[sizeof(int)];
- } x;
- x.i = 1;
- return x.c[0] == 1;
-}
-
-static ubyte decompress_pairs(struct PairsData *d, uint64 idx)
-{
- static const bool isLittleEndian = is_little_endian();
- return isLittleEndian ? decompress_pairs(d, idx)
- : decompress_pairs(d, idx);
-}
-
-// probe_wdl_table and probe_dtz_table require similar adaptations.
-static int probe_wdl_table(Position& pos, int *success)
-{
- struct TBEntry *ptr;
- struct TBHashEntry *ptr2;
- uint64 idx;
- uint64 key;
- int i;
- ubyte res;
- int p[TBPIECES];
-
- // Obtain the position's material signature key.
- key = pos.material_key();
-
- // Test for KvK.
- if (key == (Zobrist::psq[WHITE][KING][0] ^ Zobrist::psq[BLACK][KING][0]))
- return 0;
-
- ptr2 = TB_hash[key >> (64 - TBHASHBITS)];
- for (i = 0; i < HSHMAX; i++)
- if (ptr2[i].key == key) break;
- if (i == HSHMAX) {
- *success = 0;
- return 0;
- }
-
- ptr = ptr2[i].ptr;
- if (!ptr->ready) {
- LOCK(TB_mutex);
- if (!ptr->ready) {
- char str[16];
- prt_str(pos, str, ptr->key != key);
- if (!init_table_wdl(ptr, str)) {
- ptr2[i].key = 0ULL;
- *success = 0;
- UNLOCK(TB_mutex);
- return 0;
- }
- // Memory barrier to ensure ptr->ready = 1 is not reordered.
-#ifdef _MSC_VER
- _ReadWriteBarrier();
-#else
- __asm__ __volatile__ ("" ::: "memory");
-#endif
- ptr->ready = 1;
- }
- UNLOCK(TB_mutex);
- }
-
- int bside, mirror, cmirror;
- if (!ptr->symmetric) {
- if (key != ptr->key) {
- cmirror = 8;
- mirror = 0x38;
- bside = (pos.side_to_move() == WHITE);
- } else {
- cmirror = mirror = 0;
- bside = !(pos.side_to_move() == WHITE);
- }
- } else {
- cmirror = pos.side_to_move() == WHITE ? 0 : 8;
- mirror = pos.side_to_move() == WHITE ? 0 : 0x38;
- bside = 0;
- }
-
- // p[i] is to contain the square 0-63 (A1-H8) for a piece of type
- // pc[i] ^ cmirror, where 1 = white pawn, ..., 14 = black king.
- // Pieces of the same type are guaranteed to be consecutive.
- if (!ptr->has_pawns) {
- struct TBEntry_piece *entry = (struct TBEntry_piece *)ptr;
- ubyte *pc = entry->pieces[bside];
- for (i = 0; i < entry->num;) {
- Bitboard bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
- (PieceType)(pc[i] & 0x07));
- do {
- p[i++] = pop_lsb(&bb);
- } while (bb);
- }
- idx = encode_piece(entry, entry->norm[bside], p, entry->factor[bside]);
- res = decompress_pairs(entry->precomp[bside], idx);
- } else {
- struct TBEntry_pawn *entry = (struct TBEntry_pawn *)ptr;
- int k = entry->file[0].pieces[0][0] ^ cmirror;
- Bitboard bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 0x07));
- i = 0;
- do {
- p[i++] = pop_lsb(&bb) ^ mirror;
- } while (bb);
- int f = pawn_file(entry, p);
- ubyte *pc = entry->file[f].pieces[bside];
- for (; i < entry->num;) {
- bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
- (PieceType)(pc[i] & 0x07));
- do {
- p[i++] = pop_lsb(&bb) ^ mirror;
- } while (bb);
- }
- idx = encode_pawn(entry, entry->file[f].norm[bside], p, entry->file[f].factor[bside]);
- res = decompress_pairs(entry->file[f].precomp[bside], idx);
- }
-
- return ((int)res) - 2;
-}
-
-static int probe_dtz_table(Position& pos, int wdl, int *success)
-{
- struct TBEntry *ptr;
- uint64 idx;
- int i, res;
- int p[TBPIECES];
-
- // Obtain the position's material signature key.
- uint64 key = pos.material_key();
-
- if (DTZ_table[0].key1 != key && DTZ_table[0].key2 != key) {
- for (i = 1; i < DTZ_ENTRIES; i++)
- if (DTZ_table[i].key1 == key) break;
- if (i < DTZ_ENTRIES) {
- struct DTZTableEntry table_entry = DTZ_table[i];
- for (; i > 0; i--)
- DTZ_table[i] = DTZ_table[i - 1];
- DTZ_table[0] = table_entry;
- } else {
- struct TBHashEntry *ptr2 = TB_hash[key >> (64 - TBHASHBITS)];
- for (i = 0; i < HSHMAX; i++)
- if (ptr2[i].key == key) break;
- if (i == HSHMAX) {
- *success = 0;
- return 0;
- }
- ptr = ptr2[i].ptr;
- char str[16];
- int mirror = (ptr->key != key);
- prt_str(pos, str, mirror);
- if (DTZ_table[DTZ_ENTRIES - 1].entry)
- free_dtz_entry(DTZ_table[DTZ_ENTRIES-1].entry);
- for (i = DTZ_ENTRIES - 1; i > 0; i--)
- DTZ_table[i] = DTZ_table[i - 1];
- load_dtz_table(str, calc_key(pos, mirror), calc_key(pos, !mirror));
- }
- }
-
- ptr = DTZ_table[0].entry;
- if (!ptr) {
- *success = 0;
- return 0;
- }
-
- int bside, mirror, cmirror;
- if (!ptr->symmetric) {
- if (key != ptr->key) {
- cmirror = 8;
- mirror = 0x38;
- bside = (pos.side_to_move() == WHITE);
- } else {
- cmirror = mirror = 0;
- bside = !(pos.side_to_move() == WHITE);
- }
- } else {
- cmirror = pos.side_to_move() == WHITE ? 0 : 8;
- mirror = pos.side_to_move() == WHITE ? 0 : 0x38;
- bside = 0;
- }
-
- if (!ptr->has_pawns) {
- struct DTZEntry_piece *entry = (struct DTZEntry_piece *)ptr;
- if ((entry->flags & 1) != bside && !entry->symmetric) {
- *success = -1;
- return 0;
- }
- ubyte *pc = entry->pieces;
- for (i = 0; i < entry->num;) {
- Bitboard bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
- (PieceType)(pc[i] & 0x07));
- do {
- p[i++] = pop_lsb(&bb);
- } while (bb);
- }
- idx = encode_piece((struct TBEntry_piece *)entry, entry->norm, p, entry->factor);
- res = decompress_pairs(entry->precomp, idx);
-
- if (entry->flags & 2)
- res = entry->map[entry->map_idx[wdl_to_map[wdl + 2]] + res];
-
- if (!(entry->flags & pa_flags[wdl + 2]) || (wdl & 1))
- res *= 2;
- } else {
- struct DTZEntry_pawn *entry = (struct DTZEntry_pawn *)ptr;
- int k = entry->file[0].pieces[0] ^ cmirror;
- Bitboard bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 0x07));
- i = 0;
- do {
- p[i++] = pop_lsb(&bb) ^ mirror;
- } while (bb);
- int f = pawn_file((struct TBEntry_pawn *)entry, p);
- if ((entry->flags[f] & 1) != bside) {
- *success = -1;
- return 0;
- }
- ubyte *pc = entry->file[f].pieces;
- for (; i < entry->num;) {
- bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
- (PieceType)(pc[i] & 0x07));
- do {
- p[i++] = pop_lsb(&bb) ^ mirror;
- } while (bb);
- }
- idx = encode_pawn((struct TBEntry_pawn *)entry, entry->file[f].norm, p, entry->file[f].factor);
- res = decompress_pairs(entry->file[f].precomp, idx);
-
- if (entry->flags[f] & 2)
- res = entry->map[entry->map_idx[f][wdl_to_map[wdl + 2]] + res];
-
- if (!(entry->flags[f] & pa_flags[wdl + 2]) || (wdl & 1))
- res *= 2;
- }
-
- return res;
-}
-
-// Add underpromotion captures to list of captures.
-static ExtMove *add_underprom_caps(Position& pos, ExtMove *stack, ExtMove *end)
-{
- ExtMove *moves, *extra = end;
-
- for (moves = stack; moves < end; moves++) {
- Move move = moves->move;
- if (type_of(move) == PROMOTION && !pos.empty(to_sq(move))) {
- (*extra++).move = (Move)(move - (1 << 12));
- (*extra++).move = (Move)(move - (2 << 12));
- (*extra++).move = (Move)(move - (3 << 12));
- }
- }
-
- return extra;
-}
-
-static int probe_ab(Position& pos, int alpha, int beta, int *success)
-{
- int v;
- ExtMove stack[64];
- ExtMove *moves, *end;
- StateInfo st;
-
- // Generate (at least) all legal non-ep captures including (under)promotions.
- // It is OK to generate more, as long as they are filtered out below.
- if (!pos.checkers()) {
- end = generate(pos, stack);
- // Since underpromotion captures are not included, we need to add them.
- end = add_underprom_caps(pos, stack, end);
- } else
- end = generate(pos, stack);
-
- for (moves = stack; moves < end; moves++) {
- Move capture = moves->move;
- if (!pos.capture(capture) || type_of(capture) == ENPASSANT
- || !pos.legal(capture))
- continue;
- pos.do_move(capture, st, pos.gives_check(capture));
- v = -probe_ab(pos, -beta, -alpha, success);
- pos.undo_move(capture);
- if (*success == 0) return 0;
- if (v > alpha) {
- if (v >= beta) {
- *success = 2;
- return v;
- }
- alpha = v;
- }
- }
-
- v = probe_wdl_table(pos, success);
- if (*success == 0) return 0;
- if (alpha >= v) {
- *success = 1 + (alpha > 0);
- return alpha;
- } else {
- *success = 1;
- return v;
- }
-}
-
-// Probe the WDL table for a particular position.
-// If *success != 0, the probe was successful.
-// The return value is from the point of view of the side to move:
-// -2 : loss
-// -1 : loss, but draw under 50-move rule
-// 0 : draw
-// 1 : win, but draw under 50-move rule
-// 2 : win
-int Tablebases::probe_wdl(Position& pos, int *success)
-{
- int v;
-
- *success = 1;
- v = probe_ab(pos, -2, 2, success);
-
- // If en passant is not possible, we are done.
- if (pos.ep_square() == SQ_NONE)
- return v;
- if (!(*success)) return 0;
-
- // Now handle en passant.
- int v1 = -3;
- // Generate (at least) all legal en passant captures.
- ExtMove stack[192];
- ExtMove *moves, *end;
- StateInfo st;
-
- if (!pos.checkers())
- end = generate(pos, stack);
- else
- end = generate(pos, stack);
-
- for (moves = stack; moves < end; moves++) {
- Move capture = moves->move;
- if (type_of(capture) != ENPASSANT
- || !pos.legal(capture))
- continue;
- pos.do_move(capture, st, pos.gives_check(capture));
- int v0 = -probe_ab(pos, -2, 2, success);
- pos.undo_move(capture);
- if (*success == 0) return 0;
- if (v0 > v1) v1 = v0;
- }
- if (v1 > -3) {
- if (v1 >= v) v = v1;
- else if (v == 0) {
- // Check whether there is at least one legal non-ep move.
- for (moves = stack; moves < end; moves++) {
- Move capture = moves->move;
- if (type_of(capture) == ENPASSANT) continue;
- if (pos.legal(capture)) break;
- }
- if (moves == end && !pos.checkers()) {
- end = generate(pos, end);
- for (; moves < end; moves++) {
- Move move = moves->move;
- if (pos.legal(move))
- break;
- }
- }
- // If not, then we are forced to play the losing ep capture.
- if (moves == end)
- v = v1;
- }
- }
-
- return v;
-}
-
-// This routine treats a position with en passant captures as one without.
-static int probe_dtz_no_ep(Position& pos, int *success)
-{
- int wdl, dtz;
-
- wdl = probe_ab(pos, -2, 2, success);
- if (*success == 0) return 0;
-
- if (wdl == 0) return 0;
-
- if (*success == 2)
- return wdl == 2 ? 1 : 101;
-
- ExtMove stack[192];
- ExtMove *moves, *end = NULL;
- StateInfo st;
-
- if (wdl > 0) {
- // Generate at least all legal non-capturing pawn moves
- // including non-capturing promotions.
- if (!pos.checkers())
- end = generate(pos, stack);
- else
- end = generate(pos, stack);
-
- for (moves = stack; moves < end; moves++) {
- Move move = moves->move;
- if (type_of(pos.moved_piece(move)) != PAWN || pos.capture(move)
- || !pos.legal(move))
- continue;
- pos.do_move(move, st, pos.gives_check(move));
- int v = -Tablebases::probe_wdl(pos, success);
- pos.undo_move(move);
- if (*success == 0) return 0;
- if (v == wdl)
- return v == 2 ? 1 : 101;
- }
- }
-
- dtz = 1 + probe_dtz_table(pos, wdl, success);
- if (*success >= 0) {
- if (wdl & 1) dtz += 100;
- return wdl >= 0 ? dtz : -dtz;
- }
-
- if (wdl > 0) {
- int best = 0xffff;
- for (moves = stack; moves < end; moves++) {
- Move move = moves->move;
- if (pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN
- || !pos.legal(move))
- continue;
- pos.do_move(move, st, pos.gives_check(move));
- int v = -Tablebases::probe_dtz(pos, success);
- pos.undo_move(move);
- if (*success == 0) return 0;
- if (v > 0 && v + 1 < best)
- best = v + 1;
- }
- return best;
- } else {
- int best = -1;
- if (!pos.checkers())
- end = generate(pos, stack);
- else
- end = generate(pos, stack);
- for (moves = stack; moves < end; moves++) {
- int v;
- Move move = moves->move;
- if (!pos.legal(move))
- continue;
- pos.do_move(move, st, pos.gives_check(move));
- if (st.rule50 == 0) {
- if (wdl == -2) v = -1;
- else {
- v = probe_ab(pos, 1, 2, success);
- v = (v == 2) ? 0 : -101;
- }
- } else {
- v = -Tablebases::probe_dtz(pos, success) - 1;
- }
- pos.undo_move(move);
- if (*success == 0) return 0;
- if (v < best)
- best = v;
- }
- return best;
- }
-}
-
-static int wdl_to_dtz[] = {
- -1, -101, 0, 101, 1
-};
-
-// Probe the DTZ table for a particular position.
-// If *success != 0, the probe was successful.
-// The return value is from the point of view of the side to move:
-// n < -100 : loss, but draw under 50-move rule
-// -100 <= n < -1 : loss in n ply (assuming 50-move counter == 0)
-// 0 : draw
-// 1 < n <= 100 : win in n ply (assuming 50-move counter == 0)
-// 100 < n : win, but draw under 50-move rule
-//
-// The return value n can be off by 1: a return value -n can mean a loss
-// in n+1 ply and a return value +n can mean a win in n+1 ply. This
-// cannot happen for tables with positions exactly on the "edge" of
-// the 50-move rule.
-//
-// This implies that if dtz > 0 is returned, the position is certainly
-// a win if dtz + 50-move-counter <= 99. Care must be taken that the engine
-// picks moves that preserve dtz + 50-move-counter <= 99.
-//
-// If n = 100 immediately after a capture or pawn move, then the position
-// is also certainly a win, and during the whole phase until the next
-// capture or pawn move, the inequality to be preserved is
-// dtz + 50-movecounter <= 100.
-//
-// In short, if a move is available resulting in dtz + 50-move-counter <= 99,
-// then do not accept moves leading to dtz + 50-move-counter == 100.
-//
-int Tablebases::probe_dtz(Position& pos, int *success)
-{
- *success = 1;
- int v = probe_dtz_no_ep(pos, success);
-
- if (pos.ep_square() == SQ_NONE)
- return v;
- if (*success == 0) return 0;
-
- // Now handle en passant.
- int v1 = -3;
-
- ExtMove stack[192];
- ExtMove *moves, *end;
- StateInfo st;
-
- if (!pos.checkers())
- end = generate(pos, stack);
- else
- end = generate(pos, stack);
-
- for (moves = stack; moves < end; moves++) {
- Move capture = moves->move;
- if (type_of(capture) != ENPASSANT
- || !pos.legal(capture))
- continue;
- pos.do_move(capture, st, pos.gives_check(capture));
- int v0 = -probe_ab(pos, -2, 2, success);
- pos.undo_move(capture);
- if (*success == 0) return 0;
- if (v0 > v1) v1 = v0;
- }
- if (v1 > -3) {
- v1 = wdl_to_dtz[v1 + 2];
- if (v < -100) {
- if (v1 >= 0)
- v = v1;
- } else if (v < 0) {
- if (v1 >= 0 || v1 < -100)
- v = v1;
- } else if (v > 100) {
- if (v1 > 0)
- v = v1;
- } else if (v > 0) {
- if (v1 == 1)
- v = v1;
- } else if (v1 >= 0) {
- v = v1;
- } else {
- for (moves = stack; moves < end; moves++) {
- Move move = moves->move;
- if (type_of(move) == ENPASSANT) continue;
- if (pos.legal(move)) break;
- }
- if (moves == end && !pos.checkers()) {
- end = generate(pos, end);
- for (; moves < end; moves++) {
- Move move = moves->move;
- if (pos.legal(move))
- break;
- }
- }
- if (moves == end)
- v = v1;
- }
- }
-
- return v;
-}
-
-// Check whether there has been at least one repetition of positions
-// since the last capture or pawn move.
-static int has_repeated(StateInfo *st)
-{
- while (1) {
- int i = 4, e = std::min(st->rule50, st->pliesFromNull);
- if (e < i)
- return 0;
- StateInfo *stp = st->previous->previous;
- do {
- stp = stp->previous->previous;
- if (stp->key == st->key)
- return 1;
- i += 2;
- } while (i <= e);
- st = st->previous;
- }
-}
-
-static Value wdl_to_Value[5] = {
- -VALUE_MATE + MAX_PLY + 1,
- VALUE_DRAW - 2,
- VALUE_DRAW,
- VALUE_DRAW + 2,
- VALUE_MATE - MAX_PLY - 1
-};
-
-// Use the DTZ tables to filter out moves that don't preserve the win or draw.
-// If the position is lost, but DTZ is fairly high, only keep moves that
-// maximise DTZ.
-//
-// A return value false indicates that not all probes were successful and that
-// no moves were filtered out.
-bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score)
-{
- int success;
-
- int dtz = probe_dtz(pos, &success);
- if (!success) return false;
-
- StateInfo st;
-
- // Probe each move.
- for (size_t i = 0; i < rootMoves.size(); i++) {
- Move move = rootMoves[i].pv[0];
- pos.do_move(move, st, pos.gives_check(move));
- int v = 0;
- if (pos.checkers() && dtz > 0) {
- ExtMove s[192];
- if (generate(pos, s) == s)
- v = 1;
- }
- if (!v) {
- if (st.rule50 != 0) {
- v = -Tablebases::probe_dtz(pos, &success);
- if (v > 0) v++;
- else if (v < 0) v--;
- } else {
- v = -Tablebases::probe_wdl(pos, &success);
- v = wdl_to_dtz[v + 2];
- }
- }
- pos.undo_move(move);
- if (!success) return false;
- rootMoves[i].score = (Value)v;
- }
-
- // Obtain 50-move counter for the root position.
- // In Stockfish there seems to be no clean way, so we do it like this:
- int cnt50 = st.previous->rule50;
-
- // Use 50-move counter to determine whether the root position is
- // won, lost or drawn.
- int wdl = 0;
- if (dtz > 0)
- wdl = (dtz + cnt50 <= 100) ? 2 : 1;
- else if (dtz < 0)
- wdl = (-dtz + cnt50 <= 100) ? -2 : -1;
-
- // Determine the score to report to the user.
- score = wdl_to_Value[wdl + 2];
- // If the position is winning or losing, but too few moves left, adjust the
- // score to show how close it is to winning or losing.
- // NOTE: int(PawnValueEg) is used as scaling factor in score_to_uci().
- if (wdl == 1 && dtz <= 100)
- score = (Value)(((200 - dtz - cnt50) * int(PawnValueEg)) / 200);
- else if (wdl == -1 && dtz >= -100)
- score = -(Value)(((200 + dtz - cnt50) * int(PawnValueEg)) / 200);
-
- // Now be a bit smart about filtering out moves.
- size_t j = 0;
- if (dtz > 0) { // winning (or 50-move rule draw)
- int best = 0xffff;
- for (size_t i = 0; i < rootMoves.size(); i++) {
- int v = rootMoves[i].score;
- if (v > 0 && v < best)
- best = v;
- }
- int max = best;
- // If the current phase has not seen repetitions, then try all moves
- // that stay safely within the 50-move budget, if there are any.
- if (!has_repeated(st.previous) && best + cnt50 <= 99)
- max = 99 - cnt50;
- for (size_t i = 0; i < rootMoves.size(); i++) {
- int v = rootMoves[i].score;
- if (v > 0 && v <= max)
- rootMoves[j++] = rootMoves[i];
- }
- } else if (dtz < 0) { // losing (or 50-move rule draw)
- int best = 0;
- for (size_t i = 0; i < rootMoves.size(); i++) {
- int v = rootMoves[i].score;
- if (v < best)
- best = v;
- }
- // Try all moves, unless we approach or have a 50-move rule draw.
- if (-best * 2 + cnt50 < 100)
- return true;
- for (size_t i = 0; i < rootMoves.size(); i++) {
- if (rootMoves[i].score == best)
- rootMoves[j++] = rootMoves[i];
- }
- } else { // drawing
- // Try all moves that preserve the draw.
- for (size_t i = 0; i < rootMoves.size(); i++) {
- if (rootMoves[i].score == 0)
- rootMoves[j++] = rootMoves[i];
- }
- }
- rootMoves.resize(j, Search::RootMove(MOVE_NONE));
-
- return true;
-}
-
-// Use the WDL tables to filter out moves that don't preserve the win or draw.
-// This is a fallback for the case that some or all DTZ tables are missing.
-//
-// A return value false indicates that not all probes were successful and that
-// no moves were filtered out.
-bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Value& score)
-{
- int success;
-
- int wdl = Tablebases::probe_wdl(pos, &success);
- if (!success) return false;
- score = wdl_to_Value[wdl + 2];
-
- StateInfo st;
-
- int best = -2;
-
- // Probe each move.
- for (size_t i = 0; i < rootMoves.size(); i++) {
- Move move = rootMoves[i].pv[0];
- pos.do_move(move, st, pos.gives_check(move));
- int v = -Tablebases::probe_wdl(pos, &success);
- pos.undo_move(move);
- if (!success) return false;
- rootMoves[i].score = (Value)v;
- if (v > best)
- best = v;
- }
-
- size_t j = 0;
- for (size_t i = 0; i < rootMoves.size(); i++) {
- if (rootMoves[i].score == best)
- rootMoves[j++] = rootMoves[i];
- }
- rootMoves.resize(j, Search::RootMove(MOVE_NONE));
-
- return true;
-}
-
diff --git a/Engines/Windows/deepfish/srcD/syzygy/tbprobe.h b/Engines/Windows/deepfish/srcD/syzygy/tbprobe.h
deleted file mode 100644
index b23fdf6..0000000
--- a/Engines/Windows/deepfish/srcD/syzygy/tbprobe.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef TBPROBE_H
-#define TBPROBE_H
-
-#include "../search.h"
-
-namespace Tablebases {
-
-extern int MaxCardinality;
-
-void init(const std::string& path);
-int probe_wdl(Position& pos, int *success);
-int probe_dtz(Position& pos, int *success);
-bool root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score);
-bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Value& score);
-void filter_root_moves(Position& pos, Search::RootMoves& rootMoves);
-
-}
-
-#endif
diff --git a/Engines/Windows/deepfish/windows/DeepFishMZ 32.exe b/Engines/Windows/deepfish/windows/DeepFishMZ 32.exe
deleted file mode 100644
index 3b7a232..0000000
Binary files a/Engines/Windows/deepfish/windows/DeepFishMZ 32.exe and /dev/null differ
diff --git a/Engines/Windows/deepfish/windows/DeepFishMZ 64 BMI2.exe b/Engines/Windows/deepfish/windows/DeepFishMZ 64 BMI2.exe
deleted file mode 100644
index db60142..0000000
Binary files a/Engines/Windows/deepfish/windows/DeepFishMZ 64 BMI2.exe and /dev/null differ
diff --git a/Engines/Windows/mcbrain/AUTHORS b/Engines/Windows/mcbrain/AUTHORS
new file mode 100644
index 0000000..9b91b93
--- /dev/null
+++ b/Engines/Windows/mcbrain/AUTHORS
@@ -0,0 +1,98 @@
+# Generated with 'git shortlog -sn | cut -c8-', which sorts by commits, manually ordered the first four authors, merged duplicates
+
+Tord Romstad
+Marco Costalba (mcostalba)
+Joona Kiiski (zamar)
+Gary Linscott (glinscott)
+Lucas Braesch (lucasart)
+Bill Henry (VoyagerOne)
+mstembera
+Stéphane Nicolet (Stephane Nicolet, snicolet)
+Stefan Geschwentner
+Alain SAVARD (Rocky640)
+Jörg Oster (Joerg Oster, joergoster)
+Reuven Peleg
+Chris Caino (Chris Cain, ceebo)
+Jean-Francois Romang
+homoSapiensSapiens
+Leonid Pechenik
+Stefano Cardanobile (Stefano80)
+Arjun Temurnikar
+Uri Blass (uriblass)
+jundery
+Ajith (ajithcj)
+hxim
+Ralph Stößer (Ralph Stoesser)
+Guenther Demetz
+Jonathan Calovski (Mysseno)
+Tom Vijlbrief
+mbootsector
+Daylen Yang
+ElbertoOne
+Henri Wiechers
+loco-loco
+Joost VandeVondele (Joost Vandevondele)
+Ronald de Man (syzygy)
+DU-jdto
+David Zar
+Eelco de Groot
+Jerry Donald
+NicklasPersson
+Ryan Schmitt
+Alexander Kure
+Dan Schmidt
+H. Felix Wittmann
+Jacques
+Joseph R. Prostko
+Justin Blanchard
+Linus Arver
+Luca Brivio
+Lyudmil Antonov
+Rodrigo Exterckötter Tjäder
+Ron Britvich
+RyanTaker
+Vince Negri
+erbsenzaehler
+Joseph Hellis (jhellis3)
+shane31
+Andrew Grant
+Andy Duplain
+Auguste Pop
+Balint Pfliegel
+Dariusz Orzechowski
+DiscanX
+Ernesto Gatti
+Gregor Cramer
+Hiraoka Takuya (HiraokaTakuya)
+Hongzhi Cheng
+IIvec
+Kelly Wilson
+Ken T Takusagawa
+Kojirion
+Krgp
+Matt Sullivan
+Matthew Lai
+Matthew Sullivan
+Michel Van den Bergh
+Niklas Fiekas
+Oskar Werkelin Ahlin
+Pablo Vazquez
+Pascal Romaret
+Raminder Singh
+Richard Lloyd
+Ryan Takker
+Thanar2
+absimaldata
+atumanian
+braich
+fanon
+gamander
+gguliash
+kinderchocolate
+pellanda
+ppigazzini
+renouve
+sf-x
+thaspel
+unknown
+
diff --git a/Engines/Windows/deepfish/Copying.txt b/Engines/Windows/mcbrain/Copying.txt
similarity index 100%
rename from Engines/Windows/deepfish/Copying.txt
rename to Engines/Windows/mcbrain/Copying.txt
diff --git a/Engines/Windows/mcbrain/McBrain_2017_v21a_x32_old.exe b/Engines/Windows/mcbrain/McBrain_2017_v21a_x32_old.exe
new file mode 100644
index 0000000..a273b44
Binary files /dev/null and b/Engines/Windows/mcbrain/McBrain_2017_v21a_x32_old.exe differ
diff --git a/Engines/Windows/mcbrain/McBrain_2017_v21a_x64_bmi2.exe b/Engines/Windows/mcbrain/McBrain_2017_v21a_x64_bmi2.exe
new file mode 100644
index 0000000..7c61e38
Binary files /dev/null and b/Engines/Windows/mcbrain/McBrain_2017_v21a_x64_bmi2.exe differ
diff --git a/Engines/Windows/deepfish/README.md b/Engines/Windows/mcbrain/Readme.md
similarity index 93%
rename from Engines/Windows/deepfish/README.md
rename to Engines/Windows/mcbrain/Readme.md
index 319bca8..29ebf59 100644
--- a/Engines/Windows/deepfish/README.md
+++ b/Engines/Windows/mcbrain/Readme.md
@@ -1,5 +1,8 @@
### Overview
+[![Build Status](https://travis-ci.org/official-stockfish/Stockfish.svg?branch=master)](https://travis-ci.org/official-stockfish/Stockfish)
+[![Build Status](https://ci.appveyor.com/api/projects/status/github/official-stockfish/Stockfish?svg=true)](https://ci.appveyor.com/project/mcostalba/stockfish)
+
Stockfish is a free UCI chess engine derived from Glaurung 2.1. It is
not a complete chess program and requires some UCI-compatible GUI
(e.g. XBoard with PolyGlot, eboard, Arena, Sigma Chess, Shredder, Chess
@@ -54,7 +57,7 @@ for correspondence games (because of tablebase adjudication).
The "SyzygyProbeLimit" option should normally be left at its default value.
-**What to expect**
+**What to expect**
If the engine is searching a position that is not in the tablebases (e.g.
a position with 7 pieces), it will access the tablebases during the search.
If the engine reports a very large score (typically 123.xx), this means
@@ -109,4 +112,4 @@ to where the source code can be found. If you make any changes to the
source code, these changes must also be made available under the GPL.
For full details, read the copy of the GPL found in the file named
-*Copying.txt*
+*Copying.txt*.
diff --git a/Engines/Windows/mcbrain/Top CPU Contributors.txt b/Engines/Windows/mcbrain/Top CPU Contributors.txt
new file mode 100644
index 0000000..0bb2a92
--- /dev/null
+++ b/Engines/Windows/mcbrain/Top CPU Contributors.txt
@@ -0,0 +1,93 @@
+Contributors with >10,000 CPU hours as of November 3, 2016
+Thank you!
+
+Username CPU Hours Games played
+cw 220301 16924200
+glinscott 186639 13936027
+fastgm 184045 14608140
+mibere 165859 13563572
+crunchy 160974 14091929
+spams 143806 10956698
+bking_US 136938 10558137
+dsmith 103332 7622414
+BrunoBanani 100008 7448565
+ctoks 99216 7989224
+JojoM 96528 8138437
+vdbergh 88372 6322455
+drabel 75214 6034715
+velislav 71485 5483953
+sqrt2 70825 5471595
+BRAVONE 66265 5356681
+malala 57618 4480635
+psk 54292 4337164
+leszek 52415 4254611
+marrco 51573 4132787
+Freja 48348 3773248
+Thanar 47723 4062940
+Fisherman 46361 3865994
+renouve 46003 3544864
+CSU_Dynasty 45136 4096148
+rap 44619 3219490
+dv8silencer 44175 3961325
+tinker 43975 3261777
+tvijlbrief 42291 2965762
+sunu 41289 3172937
+mhunt 38278 2697512
+Antihistamine 37735 2795761
+finfish 36001 2734928
+brabos 32630 2566008
+jromang 32044 2166097
+robnjr 31781 2726352
+CoffeeOne 29940 2597953
+sterni1971 28924 2737221
+EthanOConnor 28429 2143255
+Pyafue 27266 1986098
+jkiiski 27009 1925255
+biffhero 26557 2033420
+nssy 25231 2037166
+mgrabiak 24000 1974653
+slakovv 23548 2031279
+Sharaf_DG 22175 1790697
+homyur 21415 1705644
+team-oh 20347 1653708
+Zirie 20204 1493227
+nabildanial 19538 1586321
+nesoneg 19306 1493435
+cuistot 19105 1387031
+Patrick_G 19027 1406466
+mhoram 18304 1396701
+rkl 17566 1409460
+ville 17541 1540130
+oryx 17480 1578240
+rstoesser 17264 1335177
+xor12 16786 1492708
+jundery 16786 1115855
+bigpen0r 16700 1287118
+iisiraider 16366 1089410
+davar 16266 1328093
+vdv 16072 1629971
+VoyagerOne 16049 1485459
+Bobo1239 15837 1550883
+DragonLord 15791 1251348
+purplefishies 15602 1106850
+Isidor 14598 1317485
+speedycpu 14215 874201
+OssumOpossum 14078 1029265
+enedene 13378 935618
+bpfliegel 12944 886523
+AdrianSA 12921 924980
+JanErik 12782 1106788
+dju 12600 901552
+jpulman 12015 854815
+ttruscott 11929 976348
+fatmurphy 11726 901134
+ElbertoOne 11641 1082697
+j3corre 11638 973654
+chris 11450 1228430
+pb00067 11248 1021031
+modolief 11185 926456
+Dark_wizzie 10933 1017910
+SC 10637 925516
+Thomas A. 10485 736094
+mschmidt 10354 818594
+infinity 10020 746397
diff --git a/Engines/Windows/deepfish/srcD/Makefile b/Engines/Windows/mcbrain/src/Makefile
similarity index 81%
rename from Engines/Windows/deepfish/srcD/Makefile
rename to Engines/Windows/mcbrain/src/Makefile
index 90d5c6a..20286a8 100644
--- a/Engines/Windows/deepfish/srcD/Makefile
+++ b/Engines/Windows/mcbrain/src/Makefile
@@ -22,22 +22,25 @@
### ==========================================================================
### Establish the operating system name
-UNAME = $(shell uname)
+KERNEL = $(shell uname -s)
+ifeq ($(KERNEL),Linux)
+ OS = $(shell uname -o)
+endif
### Executable name
-EXE = stockfish
+EXE = McBrain_2017
### Installation dir definitions
PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
### Built-in benchmark for pgo-builds
-PGOBENCH = ./$(EXE) bench 16 1 1000 default time
+PGOBENCH = ./$(EXE) bench
### Object files
OBJS = benchmark.o bitbase.o bitboard.o endgame.o evaluate.o main.o \
- material.o misc.o movegen.o movepick.o opt.o pawns.o position.o psqt.o \
- search.o thread.o timeman.o tt.o uci.o ucioption.o syzygy/tbprobe.o
+ material.o misc.o movegen.o movepick.o pawns.o position.o psqt.o \
+ search.o thread.o timeman.o tt.o tzbook.o uci.o ucioption.o syzygy/tbprobe.o
### ==========================================================================
### Section 2. High-level Configuration
@@ -47,6 +50,7 @@ OBJS = benchmark.o bitbase.o bitboard.o endgame.o evaluate.o main.o \
# ----------------------------------------------------------------------------
#
# debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode
+# sanitize = yes/no --- (-fsanitize ) --- enable undefined behavior checks
# optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations
# arch = (name) --- (-arch) --- Target architecture
# bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system
@@ -62,6 +66,7 @@ OBJS = benchmark.o bitbase.o bitboard.o endgame.o evaluate.o main.o \
### 2.1. General and architecture defaults
optimize = yes
debug = no
+sanitize = no
bits = 32
prefetch = no
popcnt = no
@@ -145,8 +150,17 @@ endif
ifeq ($(COMP),gcc)
comp=gcc
CXX=g++
- CXXFLAGS += -pedantic -Wextra -Wshadow -m$(bits)
- ifneq ($(UNAME),Darwin)
+ CXXFLAGS += -pedantic -Wextra -Wshadow
+
+ ifeq ($(ARCH),armv7)
+ ifeq ($(OS),Android)
+ CXXFLAGS += -m$(bits)
+ endif
+ else
+ CXXFLAGS += -m$(bits)
+ endif
+
+ ifneq ($(KERNEL),Darwin)
LDFLAGS += -Wl,--no-as-needed
endif
endif
@@ -154,7 +168,7 @@ endif
ifeq ($(COMP),mingw)
comp=mingw
- ifeq ($(UNAME),Linux)
+ ifeq ($(KERNEL),Linux)
ifeq ($(bits),64)
ifeq ($(shell which x86_64-w64-mingw32-c++-posix),)
CXX=x86_64-w64-mingw32-c++
@@ -185,27 +199,33 @@ endif
ifeq ($(COMP),clang)
comp=clang
CXX=clang++
- CXXFLAGS += -pedantic -Wextra -Wshadow -m$(bits)
- LDFLAGS += -m$(bits)
- ifeq ($(UNAME),Darwin)
- CXXFLAGS += -stdlib=libc++
- DEPENDFLAGS += -stdlib=libc++
+ CXXFLAGS += -pedantic -Wextra -Wshadow
+
+ ifeq ($(ARCH),armv7)
+ ifeq ($(OS),Android)
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+ else
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
endif
endif
ifeq ($(comp),icc)
- profile_prepare = icc-profile-prepare
profile_make = icc-profile-make
profile_use = icc-profile-use
- profile_clean = icc-profile-clean
else
- profile_prepare = gcc-profile-prepare
+ifeq ($(comp),clang)
+ profile_make = clang-profile-make
+ profile_use = clang-profile-use
+else
profile_make = gcc-profile-make
profile_use = gcc-profile-use
- profile_clean = gcc-profile-clean
+endif
endif
-ifeq ($(UNAME),Darwin)
+ifeq ($(KERNEL),Darwin)
CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.9
LDFLAGS += -arch $(arch) -mmacosx-version-min=10.9
endif
@@ -223,21 +243,27 @@ endif
### On mingw use Windows threads, otherwise POSIX
ifneq ($(comp),mingw)
# On Android Bionic's C library comes with its own pthread implementation bundled in
- ifneq ($(arch),armv7)
+ ifneq ($(OS),Android)
# Haiku has pthreads in its libroot, so only link it in on other platforms
- ifneq ($(UNAME),Haiku)
+ ifneq ($(KERNEL),Haiku)
LDFLAGS += -lpthread
endif
endif
endif
-### 3.2 Debugging
+### 3.2.1 Debugging
ifeq ($(debug),no)
CXXFLAGS += -DNDEBUG
else
CXXFLAGS += -g
endif
+### 3.2.2 Debugging with undefined behavior sanitizers
+ifeq ($(sanitize),yes)
+ CXXFLAGS += -g3 -fsanitize=undefined
+ LDFLAGS += -fsanitize=undefined
+endif
+
### 3.3 Optimization
ifeq ($(optimize),yes)
@@ -245,7 +271,7 @@ ifeq ($(optimize),yes)
ifeq ($(comp),gcc)
- ifeq ($(UNAME),Darwin)
+ ifeq ($(KERNEL),Darwin)
ifeq ($(arch),i386)
CXXFLAGS += -mdynamic-no-pic
endif
@@ -254,23 +280,21 @@ ifeq ($(optimize),yes)
endif
endif
- ifeq ($(arch),armv7)
+ ifeq ($(OS), Android)
CXXFLAGS += -fno-gcse -mthumb -march=armv7-a -mfloat-abi=softfp
endif
endif
ifeq ($(comp),icc)
- ifeq ($(UNAME),Darwin)
+ ifeq ($(KERNEL),Darwin)
CXXFLAGS += -mdynamic-no-pic
endif
endif
ifeq ($(comp),clang)
- ifeq ($(UNAME),Darwin)
- ifeq ($(pext),no)
+ ifeq ($(KERNEL),Darwin)
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS)
- endif
ifeq ($(arch),i386)
CXXFLAGS += -mdynamic-no-pic
endif
@@ -326,7 +350,7 @@ ifeq ($(comp),gcc)
endif
ifeq ($(comp),mingw)
- ifeq ($(UNAME),Linux)
+ ifeq ($(KERNEL),Linux)
ifeq ($(optimize),yes)
ifeq ($(debug),no)
CXXFLAGS += -flto
@@ -338,7 +362,7 @@ endif
### 3.9 Android 5 can only run position independent executables. Note that this
### breaks Android 4.0 and earlier.
-ifeq ($(arch),armv7)
+ifeq ($(OS), Android)
CXXFLAGS += -fPIE
LDFLAGS += -fPIE -pie
endif
@@ -394,30 +418,27 @@ help:
@echo ""
-.PHONY: build profile-build
-build:
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity
+.PHONY: help build profile-build strip install clean objclean profileclean help \
+ config-sanity icc-profile-use icc-profile-make gcc-profile-use gcc-profile-make \
+ clang-profile-use clang-profile-make
+
+build: config-sanity
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) all
-profile-build:
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity
+profile-build: config-sanity objclean profileclean
@echo ""
- @echo "Step 0/4. Preparing for profile build."
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_prepare)
- @echo ""
- @echo "Step 1/4. Building executable for benchmark ..."
- @touch *.cpp *.h syzygy/*.cpp syzygy/*.h
+ @echo "Step 1/4. Building instrumented executable ..."
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make)
@echo ""
@echo "Step 2/4. Running benchmark for pgo-build ..."
$(PGOBENCH) > /dev/null
@echo ""
- @echo "Step 3/4. Building final executable ..."
- @touch *.cpp *.h syzygy/*.cpp syzygy/*.h
+ @echo "Step 3/4. Building optimized executable ..."
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) objclean
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_use)
@echo ""
@echo "Step 4/4. Deleting profile data ..."
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_clean)
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) profileclean
strip:
strip $(EXE)
@@ -427,8 +448,19 @@ install:
-cp $(EXE) $(BINDIR)
-strip $(BINDIR)/$(EXE)
-clean:
- $(RM) $(EXE) $(EXE).exe *.o .depend *~ core bench.txt *.gcda ./syzygy/*.o ./syzygy/*.gcda
+#clean all
+clean: objclean profileclean
+ @rm -f .depend *~ core
+
+# clean binaries and objects
+objclean:
+ @rm -f $(EXE) $(EXE).exe *.o ./syzygy/*.o
+
+# clean auxiliary profiling files
+profileclean:
+ @rm -rf profdir
+ @rm -f bench.txt *.gcda ./syzygy/*.gcda *.gcno ./syzygy/*.gcno
+ @rm -f stockfish.profdata *.profraw
default:
help
@@ -443,9 +475,12 @@ config-sanity:
@echo ""
@echo "Config:"
@echo "debug: '$(debug)'"
+ @echo "sanitize: '$(sanitize)'"
@echo "optimize: '$(optimize)'"
@echo "arch: '$(arch)'"
@echo "bits: '$(bits)'"
+ @echo "kernel: '$(KERNEL)'"
+ @echo "os: '$(OS)'"
@echo "prefetch: '$(prefetch)'"
@echo "popcnt: '$(popcnt)'"
@echo "sse: '$(sse)'"
@@ -459,6 +494,7 @@ config-sanity:
@echo "Testing config sanity. If this fails, try 'make help' ..."
@echo ""
@test "$(debug)" = "yes" || test "$(debug)" = "no"
+ @test "$(sanitize)" = "yes" || test "$(sanitize)" = "no"
@test "$(optimize)" = "yes" || test "$(optimize)" = "no"
@test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "armv7"
@@ -472,8 +508,18 @@ config-sanity:
$(EXE): $(OBJS)
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
-gcc-profile-prepare:
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) gcc-profile-clean
+clang-profile-make:
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-instr-generate ' \
+ EXTRALDFLAGS=' -fprofile-instr-generate' \
+ all
+
+clang-profile-use:
+ llvm-profdata merge -output=stockfish.profdata *.profraw
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-instr-use=stockfish.profdata' \
+ EXTRALDFLAGS='-fprofile-use ' \
+ all
gcc-profile-make:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
@@ -487,14 +533,8 @@ gcc-profile-use:
EXTRALDFLAGS='-lgcov' \
all
-gcc-profile-clean:
- @rm -rf *.gcda *.gcno syzygy/*.gcda syzygy/*.gcno bench.txt
-
-icc-profile-prepare:
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) icc-profile-clean
- @mkdir profdir
-
icc-profile-make:
+ @mkdir -p profdir
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-prof-gen=srcpos -prof_dir ./profdir' \
all
@@ -504,9 +544,6 @@ icc-profile-use:
EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \
all
-icc-profile-clean:
- @rm -rf profdir bench.txt
-
.depend:
-@$(CXX) $(DEPENDFLAGS) -MM $(OBJS:.o=.cpp) > $@ 2> /dev/null
diff --git a/Engines/Windows/deepfish/srcD/benchmark.cpp b/Engines/Windows/mcbrain/src/benchmark.cpp
similarity index 94%
rename from Engines/Windows/deepfish/srcD/benchmark.cpp
rename to Engines/Windows/mcbrain/src/benchmark.cpp
index 9512540..21c6ec1 100644
--- a/Engines/Windows/deepfish/srcD/benchmark.cpp
+++ b/Engines/Windows/mcbrain/src/benchmark.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -76,7 +76,14 @@ const vector Defaults = {
"8/8/3P3k/8/1p6/8/1P6/1K3n2 b - - 0 1", // Nd2 - draw
// 7-man positions
- "8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124" // Draw
+ "8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124", // Draw
+
+ // Mate and stalemate positions
+ "8/8/8/8/8/6k1/6p1/6K1 w - -",
+ "5k2/5P2/5K2/8/8/8/8/8 b - -",
+ "8/8/8/8/8/4k3/4p3/4K3 w - -",
+ "8/8/8/8/8/5K2/8/3Q1k2 b - -",
+ "7k/7P/6K1/8/3B4/8/8/8 b - -"
};
} // namespace
@@ -110,7 +117,7 @@ void benchmark(const Position& current, istream& is) {
limits.movetime = stoi(limit); // movetime is in millisecs
else if (limitType == "nodes")
- limits.nodes = stoi(limit);
+ limits.nodes = stoll(limit);
else if (limitType == "mate")
limits.mate = stoi(limit);
diff --git a/Engines/Windows/deepfish/srcD/bitbase.cpp b/Engines/Windows/mcbrain/src/bitbase.cpp
similarity index 92%
rename from Engines/Windows/deepfish/srcD/bitbase.cpp
rename to Engines/Windows/mcbrain/src/bitbase.cpp
index 25570e1..1a6e807 100644
--- a/Engines/Windows/deepfish/srcD/bitbase.cpp
+++ b/Engines/Windows/mcbrain/src/bitbase.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -123,9 +123,9 @@ namespace {
// Immediate win if a pawn can be promoted without getting captured
else if ( us == WHITE
&& rank_of(psq) == RANK_7
- && ksq[us] != psq + DELTA_N
- && ( distance(ksq[~us], psq + DELTA_N) > 1
- || (StepAttacksBB[KING][ksq[us]] & (psq + DELTA_N))))
+ && ksq[us] != psq + NORTH
+ && ( distance(ksq[~us], psq + NORTH) > 1
+ || (StepAttacksBB[KING][ksq[us]] & (psq + NORTH))))
result = WIN;
// Immediate draw if it is a stalemate or a king captures undefended pawn
@@ -166,12 +166,12 @@ namespace {
if (Us == WHITE)
{
if (rank_of(psq) < RANK_7) // Single push
- r |= db[index(Them, ksq[Them], ksq[Us], psq + DELTA_N)];
+ r |= db[index(Them, ksq[Them], ksq[Us], psq + NORTH)];
if ( rank_of(psq) == RANK_2 // Double push
- && psq + DELTA_N != ksq[Us]
- && psq + DELTA_N != ksq[Them])
- r |= db[index(Them, ksq[Them], ksq[Us], psq + DELTA_N + DELTA_N)];
+ && psq + NORTH != ksq[Us]
+ && psq + NORTH != ksq[Them])
+ r |= db[index(Them, ksq[Them], ksq[Us], psq + NORTH + NORTH)];
}
return result = r & Good ? Good : r & UNKNOWN ? UNKNOWN : Bad;
diff --git a/Engines/Windows/deepfish/srcD/bitboard.cpp b/Engines/Windows/mcbrain/src/bitboard.cpp
similarity index 98%
rename from Engines/Windows/deepfish/srcD/bitboard.cpp
rename to Engines/Windows/mcbrain/src/bitboard.cpp
index 318ce04..3f05d8b 100644
--- a/Engines/Windows/deepfish/srcD/bitboard.cpp
+++ b/Engines/Windows/mcbrain/src/bitboard.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -205,8 +205,8 @@ void Bitboards::init() {
StepAttacksBB[make_piece(c, pt)][s] |= to;
}
- Square RookDeltas[] = { DELTA_N, DELTA_E, DELTA_S, DELTA_W };
- Square BishopDeltas[] = { DELTA_NE, DELTA_SE, DELTA_SW, DELTA_NW };
+ Square RookDeltas[] = { NORTH, EAST, SOUTH, WEST };
+ Square BishopDeltas[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
init_magics(RookTable, RookAttacks, RookMagics, RookMasks, RookShifts, RookDeltas, magic_index);
init_magics(BishopTable, BishopAttacks, BishopMagics, BishopMasks, BishopShifts, BishopDeltas, magic_index);
diff --git a/Engines/Windows/deepfish/srcD/bitboard.h b/Engines/Windows/mcbrain/src/bitboard.h
similarity index 93%
rename from Engines/Windows/deepfish/srcD/bitboard.h
rename to Engines/Windows/mcbrain/src/bitboard.h
index 390966e..bef6467 100644
--- a/Engines/Windows/deepfish/srcD/bitboard.h
+++ b/Engines/Windows/mcbrain/src/bitboard.h
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -124,13 +124,13 @@ inline Bitboard file_bb(Square s) {
}
-/// shift_bb() moves a bitboard one step along direction Delta. Mainly for pawns
+/// shift() moves a bitboard one step along direction D. Mainly for pawns
-template
-inline Bitboard shift_bb(Bitboard b) {
- return Delta == DELTA_N ? b << 8 : Delta == DELTA_S ? b >> 8
- : Delta == DELTA_NE ? (b & ~FileHBB) << 9 : Delta == DELTA_SE ? (b & ~FileHBB) >> 7
- : Delta == DELTA_NW ? (b & ~FileABB) << 7 : Delta == DELTA_SW ? (b & ~FileABB) >> 9
+template
+inline Bitboard shift(Bitboard b) {
+ return D == NORTH ? b << 8 : D == SOUTH ? b >> 8
+ : D == NORTH_EAST ? (b & ~FileHBB) << 9 : D == SOUTH_EAST ? (b & ~FileHBB) >> 7
+ : D == NORTH_WEST ? (b & ~FileABB) << 7 : D == SOUTH_WEST ? (b & ~FileABB) >> 9
: 0;
}
@@ -164,7 +164,7 @@ inline Bitboard in_front_bb(Color c, Rank r) {
/// forward_bb() returns a bitboard representing all the squares along the line
/// in front of the given one, from the point of view of the given color:
-/// ForwardBB[c][s] = in_front_bb(c, s) & file_bb(s)
+/// ForwardBB[c][s] = in_front_bb(c, rank_of(s)) & file_bb(s)
inline Bitboard forward_bb(Color c, Square s) {
return ForwardBB[c][s];
@@ -174,7 +174,7 @@ inline Bitboard forward_bb(Color c, Square s) {
/// pawn_attack_span() returns a bitboard representing all the squares that can be
/// attacked by a pawn of the given color when it moves along its file, starting
/// from the given square:
-/// PawnAttackSpan[c][s] = in_front_bb(c, s) & adjacent_files_bb(s);
+/// PawnAttackSpan[c][s] = in_front_bb(c, rank_of(s)) & adjacent_files_bb(s);
inline Bitboard pawn_attack_span(Color c, Square s) {
return PawnAttackSpan[c][s];
@@ -291,7 +291,7 @@ inline Square lsb(Bitboard b) {
inline Square msb(Bitboard b) {
assert(b);
- return Square(63 - __builtin_clzll(b));
+ return Square(63 ^ __builtin_clzll(b));
}
#elif defined(_WIN64) && defined(_MSC_VER)
diff --git a/Engines/Windows/deepfish/srcD/endgame.cpp b/Engines/Windows/mcbrain/src/endgame.cpp
similarity index 94%
rename from Engines/Windows/deepfish/srcD/endgame.cpp
rename to Engines/Windows/mcbrain/src/endgame.cpp
index 04469e8..d382478 100644
--- a/Engines/Windows/deepfish/srcD/endgame.cpp
+++ b/Engines/Windows/mcbrain/src/endgame.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -83,26 +83,6 @@ namespace {
return sq;
}
- // Get the material key of Position out of the given endgame key code
- // like "KBPKN". The trick here is to first forge an ad-hoc FEN string
- // and then let a Position object do the work for us.
- Key key(const string& code, Color c) {
-
- assert(code.length() > 0 && code.length() < 8);
- assert(code[0] == 'K');
-
- string sides[] = { code.substr(code.find('K', 1)), // Weak
- code.substr(0, code.find('K', 1)) }; // Strong
-
- std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
-
- string fen = sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/8/8/"
- + sides[1] + char(8 - sides[1].length() + '0') + " w - - 0 10";
-
- StateInfo st;
- return Position().set(fen, false, &st, nullptr).material_key();
- }
-
} // namespace
@@ -132,8 +112,9 @@ Endgames::Endgames() {
template
void Endgames::add(const string& code) {
- map()[key(code, WHITE)] = std::unique_ptr>(new Endgame(WHITE));
- map()[key(code, BLACK)] = std::unique_ptr>(new Endgame(BLACK));
+ StateInfo st;
+ map()[Position().set(code, WHITE, &st).material_key()] = std::unique_ptr>(new Endgame(WHITE));
+ map()[Position().set(code, BLACK, &st).material_key()] = std::unique_ptr>(new Endgame(BLACK));
}
@@ -259,8 +240,8 @@ Value Endgame::operator()(const Position& pos) const {
result = Value(80) - 8 * distance(wksq, psq);
else
- result = Value(200) - 8 * ( distance(wksq, psq + DELTA_S)
- - distance(bksq, psq + DELTA_S)
+ result = Value(200) - 8 * ( distance(wksq, psq + SOUTH)
+ - distance(bksq, psq + SOUTH)
- distance(psq, queeningSq));
return strongSide == pos.side_to_move() ? result : -result;
@@ -496,7 +477,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const {
// If the defending king blocks the pawn and the attacking king is too far
// away, it's a draw.
if ( r <= RANK_5
- && bksq == wpsq + DELTA_N
+ && bksq == wpsq + NORTH
&& distance(wksq, wpsq) - tempo >= 2
&& distance(wksq, brsq) - tempo >= 2)
return SCALE_FACTOR_DRAW;
@@ -517,10 +498,10 @@ ScaleFactor Endgame::operator()(const Position& pos) const {
&& file_of(wrsq) == f
&& wrsq < wpsq
&& (distance(wksq, queeningSq) < distance(bksq, queeningSq) - 2 + tempo)
- && (distance(wksq, wpsq + DELTA_N) < distance(bksq, wpsq + DELTA_N) - 2 + tempo)
+ && (distance(wksq, wpsq + NORTH) < distance(bksq, wpsq + NORTH) - 2 + tempo)
&& ( distance(bksq, wrsq) + tempo >= 3
|| ( distance(wksq, queeningSq) < distance(bksq, wrsq) + tempo
- && (distance(wksq, wpsq + DELTA_N) < distance(bksq, wrsq) + tempo))))
+ && (distance(wksq, wpsq + NORTH) < distance(bksq, wrsq) + tempo))))
return ScaleFactor( SCALE_FACTOR_MAX
- 8 * distance(wpsq, queeningSq)
- 2 * distance(wksq, queeningSq));
@@ -671,17 +652,15 @@ ScaleFactor Endgame::operator()(const Position& pos) const {
if (relative_rank(strongSide, pawnSq) <= RANK_5)
return SCALE_FACTOR_DRAW;
- else
- {
- Bitboard path = forward_bb(strongSide, pawnSq);
+
+ Bitboard path = forward_bb(strongSide, pawnSq);
- if (path & pos.pieces(weakSide, KING))
- return SCALE_FACTOR_DRAW;
+ if (path & pos.pieces(weakSide, KING))
+ return SCALE_FACTOR_DRAW;
- if ( (pos.attacks_from(weakBishopSq) & path)
- && distance(weakBishopSq, pawnSq) >= 3)
- return SCALE_FACTOR_DRAW;
- }
+ if ( (pos.attacks_from(weakBishopSq) & path)
+ && distance(weakBishopSq, pawnSq) >= 3)
+ return SCALE_FACTOR_DRAW;
}
return SCALE_FACTOR_NONE;
}
diff --git a/Engines/Windows/deepfish/srcD/endgame.h b/Engines/Windows/mcbrain/src/endgame.h
similarity index 98%
rename from Engines/Windows/deepfish/srcD/endgame.h
rename to Engines/Windows/mcbrain/src/endgame.h
index 5f6b4bb..509e8d4 100644
--- a/Engines/Windows/deepfish/srcD/endgame.h
+++ b/Engines/Windows/mcbrain/src/endgame.h
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/Engines/Windows/deepfish/srcD/evaluate.cpp b/Engines/Windows/mcbrain/src/evaluate.cpp
similarity index 66%
rename from Engines/Windows/deepfish/srcD/evaluate.cpp
rename to Engines/Windows/mcbrain/src/evaluate.cpp
index d533eed..6337045 100644
--- a/Engines/Windows/deepfish/srcD/evaluate.cpp
+++ b/Engines/Windows/mcbrain/src/evaluate.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -73,6 +73,10 @@ namespace {
// by the evaluation functions.
struct EvalInfo {
+ Material::Entry* me;
+ Pawns::Entry* pe;
+ Bitboard mobilityArea[COLOR_NB];
+
// attackedBy[color][piece type] is a bitboard representing all squares
// attacked by a given color and piece type (can be also ALL_PIECES).
Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB];
@@ -106,47 +110,36 @@ namespace {
// a white knight on g5 and black's king is on g8, this white knight adds 2
// to kingAdjacentZoneAttacksCount[WHITE].
int kingAdjacentZoneAttacksCount[COLOR_NB];
-
- Bitboard pinnedPieces[COLOR_NB];
- Material::Entry* me;
- Pawns::Entry* pi;
};
#define V(v) Value(v)
#define S(mg, eg) make_score(mg, eg)
- // MobilityBonus[PieceType][attacked] contains bonuses for middle and end
- // game, indexed by piece type and number of attacked squares in the MobilityArea.
- const Score MobilityBonus[][32] = {
- {}, {},
- { S(-75,-76), S(-56,-54), S( -9,-26), S( -2,-10), S( 6, 5), S( 15, 11), // Knights
- S( 22, 26), S( 30, 28), S( 36, 29) },
- { S(-48,-58), S(-21,-19), S( 16, -2), S( 26, 12), S( 37, 22), S( 51, 42), // Bishops
- S( 54, 54), S( 63, 58), S( 65, 63), S( 71, 70), S( 79, 74), S( 81, 86),
- S( 92, 90), S( 97, 94) },
- { S(-56,-78), S(-25,-18), S(-11, 26), S( -5, 55), S( -4, 70), S( -1, 81), // Rooks
- S( 8,109), S( 14,120), S( 21,128), S( 23,143), S( 31,154), S( 32,160),
- S( 43,165), S( 49,168), S( 59,169) },
- { S(-40,-35), S(-25,-12), S( 2, 7), S( 4, 19), S( 14, 37), S( 24, 55), // Queens
- S( 25, 62), S( 40, 76), S( 43, 79), S( 47, 87), S( 54, 94), S( 56,102),
- S( 60,111), S( 70,116), S( 72,118), S( 73,122), S( 75,128), S( 77,130),
- S( 85,133), S( 94,136), S( 99,140), S(108,157), S(112,158), S(113,161),
- S(118,174), S(119,177), S(123,191), S(128,199) }
+ // MobilityBonus[PieceType-2][attacked] contains bonuses for middle and end game,
+ // indexed by piece type and number of attacked squares in the mobility area.
+ const Score MobilityBonus[4][32] = {
+ { S(-75,-76), S(-57,-54), S( -9,-28), S( -2,-10), S( 6, 5), S( 14, 12), // Knights
+ S( 22, 26), S( 29, 29), S( 36, 29) },
+ { S(-48,-59), S(-20,-23), S( 16, -3), S( 26, 13), S( 38, 24), S( 51, 42), // Bishops
+ S( 55, 54), S( 63, 57), S( 63, 65), S( 68, 73), S( 81, 78), S( 81, 86),
+ S( 91, 88), S( 98, 97) },
+ { S(-60,-77), S(-26,-20), S(-11, 27), S( -6, 57), S( -3, 69), S( -1, 82), // Rooks
+ S( 10,109), S( 16,121), S( 24,131), S( 25,143), S( 32,155), S( 32,163),
+ S( 43,167), S( 48,171), S( 56,173) },
+ { S(-39,-36), S(-21,-15), S( 3, 8), S( 3, 18), S( 14, 34), S( 22, 54), // Queens
+ S( 28, 61), S( 41, 73), S( 43, 79), S( 48, 92), S( 56, 94), S( 60,104),
+ S( 60,113), S( 66,120), S( 67,123), S( 70,126), S( 71,133), S( 73,136),
+ S( 79,140), S( 88,143), S( 88,148), S( 99,166), S(102,170), S(102,175),
+ S(106,184), S(109,191), S(113,206), S(116,212) }
};
- // Outpost[knight/bishop][supported by pawn] contains bonuses for knights and
- // bishops outposts, bigger if outpost piece is supported by a pawn.
+ // Outpost[knight/bishop][supported by pawn] contains bonuses for minor
+ // pieces if they can reach an outpost square, bigger if that square is
+ // supported by a pawn. If the minor piece occupies an outpost square
+ // then score is doubled.
const Score Outpost[][2] = {
- { S(43,11), S(65,20) }, // Knights
- { S(20, 3), S(29, 8) } // Bishops
- };
-
- // ReachableOutpost[knight/bishop][supported by pawn] contains bonuses for
- // knights and bishops which can reach an outpost square in one move, bigger
- // if outpost square is supported by a pawn.
- const Score ReachableOutpost[][2] = {
- { S(21, 5), S(35, 8) }, // Knights
- { S( 8, 0), S(14, 4) } // Bishops
+ { S(22, 6), S(33, 9) }, // Knight
+ { S( 9, 2), S(14, 4) } // Bishop
};
// RookOnFile[semiopen/open] contains bonuses for each rook when there is no
@@ -156,17 +149,21 @@ namespace {
// ThreatBySafePawn[PieceType] contains bonuses according to which piece
// type is attacked by a pawn which is protected or is not attacked.
const Score ThreatBySafePawn[PIECE_TYPE_NB] = {
- S(0, 0), S(0, 0), S(176, 139), S(131, 127), S(217, 218), S(203, 215) };
-
- // Threat[by minor/by rook][attacked PieceType] contains
- // bonuses according to which piece type attacks which one.
- // Attacks on lesser pieces which are pawn-defended are not considered.
- const Score Threat[][PIECE_TYPE_NB] = {
- { S(0, 0), S(0, 33), S(45, 43), S(46, 47), S(72,107), S(48,118) }, // by Minor
- { S(0, 0), S(0, 25), S(40, 62), S(40, 59), S( 0, 34), S(35, 48) } // by Rook
+ S(0, 0), S(0, 0), S(176, 139), S(131, 127), S(217, 218), S(203, 215)
+ };
+
+ // ThreatByMinor/ByRook[attacked PieceType] contains bonuses according to
+ // which piece type attacks which one. Attacks on lesser pieces which are
+ // pawn-defended are not considered.
+ const Score ThreatByMinor[PIECE_TYPE_NB] = {
+ S(0, 0), S(0, 33), S(45, 43), S(46, 47), S(72, 107), S(48, 118)
};
- // ThreatByKing[on one/on many] contains bonuses for King attacks on
+ const Score ThreatByRook[PIECE_TYPE_NB] = {
+ S(0, 0), S(0, 25), S(40, 62), S(40, 59), S( 0, 34), S(35, 48)
+ };
+
+ // ThreatByKing[on one/on many] contains bonuses for king attacks on
// pawns or pieces which are not pawn-defended.
const Score ThreatByKing[2] = { S(3, 62), S(9, 138) };
@@ -180,7 +177,16 @@ namespace {
// PassedFile[File] contains a bonus according to the file of a passed pawn
const Score PassedFile[FILE_NB] = {
S( 9, 10), S( 2, 10), S( 1, -8), S(-20,-12),
- S(-20,-12), S( 1, -8), S( 2, 10), S( 9, 10)
+ S(-20,-12), S( 1, -8), S( 2, 10), S( 9, 10)
+ };
+
+ // Protector[PieceType-2][distance] contains a protecting bonus for our king,
+ // indexed by piece type and distance between the piece and the king.
+ const Score Protector[4][8] = {
+ { S(0, 0), S( 7, 9), S( 7, 1), S( 1, 5), S(-10,-4), S( -1,-4), S( -7,-3), S(-16,-10) }, // Knight
+ { S(0, 0), S(11, 8), S(-7,-1), S(-1,-2), S( -1,-7), S(-11,-3), S( -9,-1), S(-16, -1) }, // Bishop
+ { S(0, 0), S(10, 0), S(-2, 2), S(-5, 4), S( -6, 2), S(-14,-3), S( -2,-9), S(-12, -7) }, // Rook
+ { S(0, 0), S( 3,-5), S( 2,-5), S(-4, 0), S( -9,-6), S(-4, 7), S(-13,-7), S(-10, -7) } // Queen
};
// Assorted bonuses and penalties used by evaluation
@@ -188,15 +194,16 @@ namespace {
const Score BishopPawns = S( 8, 12);
const Score RookOnPawn = S( 8, 24);
const Score TrappedRook = S(92, 0);
- const Score CloseEnemies = S( 7, 0);
- const Score SafeCheck = S(20, 20);
+ const Score WeakQueen = S(50, 10);
const Score OtherCheck = S(10, 10);
+ const Score CloseEnemies = S( 7, 0);
+ const Score PawnlessFlank = S(20, 80);
const Score ThreatByHangingPawn = S(71, 61);
- const Score LooseEnemies = S( 0, 25);
- const Score WeakQueen = S(35, 0);
+ const Score ThreatByRank = S(16, 3);
const Score Hanging = S(48, 27);
+ const Score MobilityAdjust = S( 5, 10);
const Score ThreatByPawnPush = S(38, 22);
- const Score Unstoppable = S( 0, 20);
+ const Score HinderPassedPawn = S( 7, 0);
// Penalty for a bishop on a1/h1 (a8/h8 for black) which is trapped by
// a friendly pawn on b2/g2 (b7/g7 for black). This can obviously only
@@ -206,22 +213,17 @@ namespace {
#undef S
#undef V
- // King danger constants and variables. The king danger scores are looked-up
- // in KingDanger[]. Various little "meta-bonuses" measuring the strength
- // of the enemy attack are added up into an integer, which is used as an
- // index to KingDanger[].
- Score KingDanger[400];
-
// KingAttackWeights[PieceType] contains king attack weights by piece type
- const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 7, 5, 4, 1 };
+ const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 78, 56, 45, 11 };
// Penalties for enemy's safe checks
- const int QueenContactCheck = 89;
- const int QueenCheck = 62;
- const int RookCheck = 57;
- const int BishopCheck = 48;
- const int KnightCheck = 78;
+ const int QueenCheck = 745;
+ const int RookCheck = 688;
+ const int BishopCheck = 588;
+ const int KnightCheck = 924;
+ // Threshold for lazy evaluation
+ const Value LazyThreshold = Value(1500);
// eval_init() initializes king and attack bitboards for a given color
// adding pawn attacks. To be done at the beginning of the evaluation.
@@ -229,25 +231,34 @@ namespace {
template
void eval_init(const Position& pos, EvalInfo& ei) {
- const Color Them = (Us == WHITE ? BLACK : WHITE);
- const Square Down = (Us == WHITE ? DELTA_S : DELTA_N);
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const Square Up = (Us == WHITE ? NORTH : SOUTH);
+ const Square Down = (Us == WHITE ? SOUTH : NORTH);
+ const Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB);
+
+ // Find our pawns on the first two ranks, and those which are blocked
+ Bitboard b = pos.pieces(Us, PAWN) & (shift(pos.pieces()) | LowRanks);
+
+ // Squares occupied by those pawns, by our king, or controlled by enemy pawns
+ // are excluded from the mobility area.
+ ei.mobilityArea[Us] = ~(b | pos.square(Us) | ei.pe->pawn_attacks(Them));
- ei.pinnedPieces[Us] = pos.pinned_pieces(Us);
- Bitboard b = ei.attackedBy[Them][KING];
- ei.attackedBy[Them][ALL_PIECES] |= b;
- ei.attackedBy[Us][ALL_PIECES] |= ei.attackedBy[Us][PAWN] = ei.pi->pawn_attacks(Us);
- ei.attackedBy2[Us] = ei.attackedBy[Us][PAWN] & ei.attackedBy[Us][KING];
+ // Initialise the attack bitboards with the king and pawn information
+ b = ei.attackedBy[Us][KING] = pos.attacks_from(pos.square(Us));
+ ei.attackedBy[Us][PAWN] = ei.pe->pawn_attacks(Us);
- // Init king safety tables only if we are going to use them
- if (pos.non_pawn_material(Us) >= QueenValueMg)
+ ei.attackedBy2[Us] = b & ei.attackedBy[Us][PAWN];
+ ei.attackedBy[Us][ALL_PIECES] = b | ei.attackedBy[Us][PAWN];
+
+ // Init our king safety tables only if we are going to use them
+ if (pos.non_pawn_material(Them) >= QueenValueMg)
{
- ei.kingRing[Them] = b | shift_bb(b);
- b &= ei.attackedBy[Us][PAWN];
- ei.kingAttackersCount[Us] = popcount(b);
- ei.kingAdjacentZoneAttacksCount[Us] = ei.kingAttackersWeight[Us] = 0;
+ ei.kingRing[Us] = b | shift(b);
+ ei.kingAttackersCount[Them] = popcount(b & ei.pe->pawn_attacks(Them));
+ ei.kingAdjacentZoneAttacksCount[Them] = ei.kingAttackersWeight[Them] = 0;
}
else
- ei.kingRing[Them] = ei.kingAttackersCount[Us] = 0;
+ ei.kingRing[Us] = ei.kingAttackersCount[Them] = 0;
}
@@ -255,11 +266,7 @@ namespace {
// color and type.
template
- Score evaluate_pieces(const Position& pos, EvalInfo& ei, Score* mobility,
- const Bitboard* mobilityArea) {
- Bitboard b, bb;
- Square s;
- Score score = SCORE_ZERO;
+ Score evaluate_pieces(const Position& pos, EvalInfo& ei, Score* mobility) {
const PieceType NextPt = (Us == WHITE ? Pt : PieceType(Pt + 1));
const Color Them = (Us == WHITE ? BLACK : WHITE);
@@ -267,6 +274,10 @@ namespace {
: Rank5BB | Rank4BB | Rank3BB);
const Square* pl = pos.squares(Us);
+ Bitboard b, bb;
+ Square s;
+ Score score = SCORE_ZERO;
+
ei.attackedBy[Us][Pt] = 0;
while ((s = *pl++) != SQ_NONE)
@@ -276,7 +287,7 @@ namespace {
: Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(Us, ROOK, QUEEN))
: pos.attacks_from(s);
- if (ei.pinnedPieces[Us] & s)
+ if (pos.pinned_pieces(Us) & s)
b &= LineBB[pos.square(Us)][s];
ei.attackedBy2[Us] |= ei.attackedBy[Us][ALL_PIECES] & b;
@@ -289,26 +300,24 @@ namespace {
ei.kingAdjacentZoneAttacksCount[Us] += popcount(b & ei.attackedBy[Them][KING]);
}
- if (Pt == QUEEN)
- b &= ~( ei.attackedBy[Them][KNIGHT]
- | ei.attackedBy[Them][BISHOP]
- | ei.attackedBy[Them][ROOK]);
+ int mob = popcount(b & ei.mobilityArea[Us]);
- int mob = popcount(b & mobilityArea[Us]);
+ mobility[Us] += MobilityBonus[Pt-2][mob];
- mobility[Us] += MobilityBonus[Pt][mob];
+ // Bonus for this piece as a king protector
+ score += Protector[Pt-2][distance(s, pos.square(Us))];
if (Pt == BISHOP || Pt == KNIGHT)
{
// Bonus for outpost squares
- bb = OutpostRanks & ~ei.pi->pawn_attacks_span(Them);
+ bb = OutpostRanks & ~ei.pe->pawn_attacks_span(Them);
if (bb & s)
- score += Outpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & s)];
+ score += Outpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & s)] * 2;
else
{
bb &= b & ~pos.pieces(Us);
if (bb)
- score += ReachableOutpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & bb)];
+ score += Outpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & bb)];
}
// Bonus when behind a pawn
@@ -318,7 +327,7 @@ namespace {
// Penalty for pawns on the same color square as the bishop
if (Pt == BISHOP)
- score -= BishopPawns * ei.pi->pawns_on_same_color_squares(Us, s);
+ score -= BishopPawns * ei.pe->pawns_on_same_color_squares(Us, s);
// An important Chess960 pattern: A cornered bishop blocked by a friendly
// pawn diagonally in front of it is a very serious problem, especially
@@ -327,7 +336,7 @@ namespace {
&& pos.is_chess960()
&& (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1)))
{
- Square d = pawn_push(Us) + (file_of(s) == FILE_A ? DELTA_E : DELTA_W);
+ Square d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST);
if (pos.piece_on(s + d) == make_piece(Us, PAWN))
score -= !pos.empty(s + d + pawn_push(Us)) ? TrappedBishopA1H1 * 4
: pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? TrappedBishopA1H1 * 2
@@ -342,17 +351,16 @@ namespace {
score += RookOnPawn * popcount(pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]);
// Bonus when on an open or semi-open file
- if (ei.pi->semiopen_file(Us, file_of(s)))
- score += RookOnFile[!!ei.pi->semiopen_file(Them, file_of(s))];
+ if (ei.pe->semiopen_file(Us, file_of(s)))
+ score += RookOnFile[!!ei.pe->semiopen_file(Them, file_of(s))];
- // Penalize when trapped by the king, even more if the king cannot castle
+ // Penalty when trapped by the king, even more if the king cannot castle
else if (mob <= 3)
{
Square ksq = pos.square(Us);
if ( ((file_of(ksq) < FILE_E) == (file_of(s) < file_of(ksq)))
- && (rank_of(ksq) == rank_of(s) || relative_rank(Us, ksq) == RANK_1)
- && !ei.pi->semiopen_side(Us, file_of(ksq), file_of(s) < file_of(ksq)))
+ && !ei.pe->semiopen_side(Us, file_of(ksq), file_of(s) < file_of(ksq)))
score -= (TrappedRook - make_score(mob * 22, 0)) * (1 + !pos.can_castle(Us));
}
}
@@ -360,7 +368,8 @@ namespace {
if (Pt == QUEEN)
{
// Penalty if any relative pin or discovered attack against the queen
- if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s))
+ Bitboard pinners;
+ if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, pinners))
score -= WeakQueen;
}
}
@@ -369,47 +378,44 @@ namespace {
Trace::add(Pt, Us, score);
// Recursively call evaluate_pieces() of next piece type until KING is excluded
- return score - evaluate_pieces(pos, ei, mobility, mobilityArea);
+ return score - evaluate_pieces(pos, ei, mobility);
}
template<>
- Score evaluate_pieces(const Position&, EvalInfo&, Score*, const Bitboard*) { return SCORE_ZERO; }
+ Score evaluate_pieces(const Position&, EvalInfo&, Score*) { return SCORE_ZERO; }
template<>
- Score evaluate_pieces< true, WHITE, KING>(const Position&, EvalInfo&, Score*, const Bitboard*) { return SCORE_ZERO; }
+ Score evaluate_pieces< true, WHITE, KING>(const Position&, EvalInfo&, Score*) { return SCORE_ZERO; }
// evaluate_king() assigns bonuses and penalties to a king of a given color
- const Bitboard WhiteCamp = Rank1BB | Rank2BB | Rank3BB | Rank4BB | Rank5BB;
- const Bitboard BlackCamp = Rank8BB | Rank7BB | Rank6BB | Rank5BB | Rank4BB;
const Bitboard QueenSide = FileABB | FileBBB | FileCBB | FileDBB;
const Bitboard CenterFiles = FileCBB | FileDBB | FileEBB | FileFBB;
const Bitboard KingSide = FileEBB | FileFBB | FileGBB | FileHBB;
- const Bitboard KingFlank[COLOR_NB][FILE_NB] = {
- { QueenSide & WhiteCamp, QueenSide & WhiteCamp, QueenSide & WhiteCamp, CenterFiles & WhiteCamp,
- CenterFiles & WhiteCamp, KingSide & WhiteCamp, KingSide & WhiteCamp, KingSide & WhiteCamp },
- { QueenSide & BlackCamp, QueenSide & BlackCamp, QueenSide & BlackCamp, CenterFiles & BlackCamp,
- CenterFiles & BlackCamp, KingSide & BlackCamp, KingSide & BlackCamp, KingSide & BlackCamp },
+ const Bitboard KingFlank[FILE_NB] = {
+ QueenSide, QueenSide, QueenSide, CenterFiles, CenterFiles, KingSide, KingSide, KingSide
};
template
Score evaluate_king(const Position& pos, const EvalInfo& ei) {
- const Color Them = (Us == WHITE ? BLACK : WHITE);
- const Square Up = (Us == WHITE ? DELTA_N : DELTA_S);
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const Square Up = (Us == WHITE ? NORTH : SOUTH);
+ const Bitboard Camp = (Us == WHITE ? ~Bitboard(0) ^ Rank6BB ^ Rank7BB ^ Rank8BB
+ : ~Bitboard(0) ^ Rank1BB ^ Rank2BB ^ Rank3BB);
- Bitboard undefended, b, b1, b2, safe, other;
- int attackUnits;
const Square ksq = pos.square(Us);
+ Bitboard undefended, b, b1, b2, safe, other;
+ int kingDanger;
// King shelter and enemy pawns storm
- Score score = ei.pi->king_safety(pos, ksq);
+ Score score = ei.pe->king_safety(pos, ksq);
// Main king safety evaluation
if (ei.kingAttackersCount[Them])
{
- // Find the attacked squares which are defended only by the king...
+ // Find the attacked squares which are defended only by our king...
undefended = ei.attackedBy[Them][ALL_PIECES]
& ei.attackedBy[Us][KING]
& ~ei.attackedBy2[Us];
@@ -418,56 +424,51 @@ namespace {
b = ei.attackedBy[Them][ALL_PIECES] & ~ei.attackedBy[Us][ALL_PIECES]
& ei.kingRing[Us] & ~pos.pieces(Them);
- // Initialize the 'attackUnits' variable, which is used later on as an
- // index into the KingDanger[] array. The initial value is based on the
+ // Initialize the 'kingDanger' variable, which will be transformed
+ // later into a king danger score. The initial value is based on the
// number and types of the enemy's attacking pieces, the number of
// attacked and undefended squares around our king and the quality of
// the pawn shelter (current 'score' value).
- attackUnits = std::min(72, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them])
- + 9 * ei.kingAdjacentZoneAttacksCount[Them]
- + 21 * popcount(undefended)
- + 12 * (popcount(b) + !!ei.pinnedPieces[Us])
- - 64 * !pos.count(Them)
- - mg_value(score) / 8;
-
- // Analyse the enemy's safe queen contact checks. Firstly, find the
- // undefended squares around the king reachable by the enemy queen...
- b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them);
+ kingDanger = std::min(807, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them])
+ + 101 * ei.kingAdjacentZoneAttacksCount[Them]
+ + 235 * popcount(undefended)
+ + 134 * (popcount(b) + !!pos.pinned_pieces(Us))
+ - 717 * !pos.count(Them)
+ - 7 * mg_value(score) / 5 - 5;
- // ...and keep squares supported by another enemy piece
- attackUnits += QueenContactCheck * popcount(b & ei.attackedBy2[Them]);
-
- // Analyse the safe enemy's checks which are possible on next move...
- safe = ~(ei.attackedBy[Us][ALL_PIECES] | pos.pieces(Them));
-
- // ... and some other potential checks, only requiring the square to be
- // safe from pawn-attacks, and not being occupied by a blocked pawn.
- other = ~( ei.attackedBy[Us][PAWN]
- | (pos.pieces(Them, PAWN) & shift_bb(pos.pieces(PAWN))));
+ // Analyse the safe enemy's checks which are possible on next move
+ safe = ~pos.pieces(Them);
+ safe &= ~ei.attackedBy[Us][ALL_PIECES] | (undefended & ei.attackedBy2[Them]);
b1 = pos.attacks_from(ksq);
b2 = pos.attacks_from(ksq);
// Enemy queen safe checks
if ((b1 | b2) & ei.attackedBy[Them][QUEEN] & safe)
- attackUnits += QueenCheck, score -= SafeCheck;
+ kingDanger += QueenCheck;
- // For other pieces, also consider the square safe if attacked twice,
- // and only defended by a queen.
+ // For minors and rooks, also consider the square safe if attacked twice,
+ // and only defended by our queen.
safe |= ei.attackedBy2[Them]
& ~(ei.attackedBy2[Us] | pos.pieces(Them))
& ei.attackedBy[Us][QUEEN];
+ // Some other potential checks are also analysed, even from squares
+ // currently occupied by the opponent own pieces, as long as the square
+ // is not attacked by our pawns, and is not occupied by a blocked pawn.
+ other = ~( ei.attackedBy[Us][PAWN]
+ | (pos.pieces(Them, PAWN) & shift(pos.pieces(PAWN))));
+
// Enemy rooks safe and other checks
if (b1 & ei.attackedBy[Them][ROOK] & safe)
- attackUnits += RookCheck, score -= SafeCheck;
+ kingDanger += RookCheck;
else if (b1 & ei.attackedBy[Them][ROOK] & other)
score -= OtherCheck;
// Enemy bishops safe and other checks
if (b2 & ei.attackedBy[Them][BISHOP] & safe)
- attackUnits += BishopCheck, score -= SafeCheck;
+ kingDanger += BishopCheck;
else if (b2 & ei.attackedBy[Them][BISHOP] & other)
score -= OtherCheck;
@@ -475,18 +476,19 @@ namespace {
// Enemy knights safe and other checks
b = pos.attacks_from(ksq) & ei.attackedBy[Them][KNIGHT];
if (b & safe)
- attackUnits += KnightCheck, score -= SafeCheck;
+ kingDanger += KnightCheck;
else if (b & other)
score -= OtherCheck;
- // Finally, extract the king danger score from the KingDanger[]
- // array and subtract the score from the evaluation.
- score -= KingDanger[std::max(std::min(attackUnits, 399), 0)];
+ // Transform the kingDanger units into a Score, and substract it from the evaluation
+ if (kingDanger > 0)
+ score -= make_score(std::min(kingDanger * kingDanger / 4096, 2 * int(BishopValueMg)), 0);
}
// King tropism: firstly, find squares that opponent attacks in our king flank
- b = ei.attackedBy[Them][ALL_PIECES] & KingFlank[Us][file_of(ksq)];
+ File kf = file_of(ksq);
+ b = ei.attackedBy[Them][ALL_PIECES] & KingFlank[kf] & Camp;
assert(((Us == WHITE ? b << 4 : b >> 4) & b) == 0);
assert(popcount(Us == WHITE ? b << 4 : b >> 4) == popcount(b));
@@ -498,6 +500,10 @@ namespace {
score -= CloseEnemies * popcount(b);
+ // Penalty when our king is on a pawnless flank
+ if (!(pos.pieces(PAWN) & KingFlank[kf]))
+ score -= PawnlessFlank;
+
if (DoTrace)
Trace::add(KING, Us, score);
@@ -511,23 +517,16 @@ namespace {
template
Score evaluate_threats(const Position& pos, const EvalInfo& ei) {
- const Color Them = (Us == WHITE ? BLACK : WHITE);
- const Square Up = (Us == WHITE ? DELTA_N : DELTA_S);
- const Square Left = (Us == WHITE ? DELTA_NW : DELTA_SE);
- const Square Right = (Us == WHITE ? DELTA_NE : DELTA_SW);
- const Bitboard TRank2BB = (Us == WHITE ? Rank2BB : Rank7BB);
- const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
-
- enum { Minor, Rook };
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const Square Up = (Us == WHITE ? NORTH : SOUTH);
+ const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
+ const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
+ const Bitboard TRank2BB = (Us == WHITE ? Rank2BB : Rank7BB);
+ const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
- Bitboard b, weak, defended, safeThreats;
+ Bitboard b, weak, defended, stronglyProtected, safeThreats;
Score score = SCORE_ZERO;
- // Small bonus if the opponent has loose pawns or pieces
- if ( (pos.pieces(Them) ^ pos.pieces(Them, QUEEN, KING))
- & ~(ei.attackedBy[Us][ALL_PIECES] | ei.attackedBy[Them][ALL_PIECES]))
- score += LooseEnemies;
-
// Non-pawn enemies attacked by a pawn
weak = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) & ei.attackedBy[Us][PAWN];
@@ -536,7 +535,7 @@ namespace {
b = pos.pieces(Us, PAWN) & ( ~ei.attackedBy[Them][ALL_PIECES]
| ei.attackedBy[Us][ALL_PIECES]);
- safeThreats = (shift_bb(b) | shift_bb(b)) & weak;
+ safeThreats = (shift(b) | shift(b)) & weak;
if (weak ^ safeThreats)
score += ThreatByHangingPawn;
@@ -545,12 +544,18 @@ namespace {
score += ThreatBySafePawn[type_of(pos.piece_on(pop_lsb(&safeThreats)))];
}
- // Non-pawn enemies defended by a pawn
- defended = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) & ei.attackedBy[Them][PAWN];
+ // Squares strongly protected by the opponent, either because they attack the
+ // square with a pawn, or because they attack the square twice and we don't.
+ stronglyProtected = ei.attackedBy[Them][PAWN]
+ | (ei.attackedBy2[Them] & ~ei.attackedBy2[Us]);
+
+ // Non-pawn enemies, strongly protected
+ defended = (pos.pieces(Them) ^ pos.pieces(Them, PAWN))
+ & stronglyProtected;
- // Enemies not defended by a pawn and under our attack
+ // Enemies not strongly protected and under our attack
weak = pos.pieces(Them)
- & ~ei.attackedBy[Them][PAWN]
+ & ~stronglyProtected
& ei.attackedBy[Us][ALL_PIECES];
// Add a bonus according to the kind of attacking pieces
@@ -558,11 +563,21 @@ namespace {
{
b = (defended | weak) & (ei.attackedBy[Us][KNIGHT] | ei.attackedBy[Us][BISHOP]);
while (b)
- score += Threat[Minor][type_of(pos.piece_on(pop_lsb(&b)))];
+ {
+ Square s = pop_lsb(&b);
+ score += ThreatByMinor[type_of(pos.piece_on(s))];
+ if (type_of(pos.piece_on(s)) != PAWN)
+ score += ThreatByRank * (int)relative_rank(Them, s);
+ }
b = (pos.pieces(Them, QUEEN) | weak) & ei.attackedBy[Us][ROOK];
while (b)
- score += Threat[Rook ][type_of(pos.piece_on(pop_lsb(&b)))];
+ {
+ Square s = pop_lsb(&b);
+ score += ThreatByRook[type_of(pos.piece_on(s))];
+ if (type_of(pos.piece_on(s)) != PAWN)
+ score += ThreatByRank * (int)relative_rank(Them, s);
+ }
score += Hanging * popcount(weak & ~ei.attackedBy[Them][ALL_PIECES]);
@@ -570,16 +585,22 @@ namespace {
if (b)
score += ThreatByKing[more_than_one(b)];
}
+
+ // Some mobility bonus was allocated in evaluate_pieces for major pieces even
+ // for some squares controlled by the enemy. Penalize those squares.
+ b = (ei.attackedBy[Us][ROOK] | ei.attackedBy[Us][QUEEN])
+ & ei.mobilityArea[Us] & stronglyProtected;
+ score -= MobilityAdjust * popcount(b);
// Bonus if some pawns can safely push and attack an enemy piece
b = pos.pieces(Us, PAWN) & ~TRank7BB;
- b = shift_bb(b | (shift_bb(b & TRank2BB) & ~pos.pieces()));
+ b = shift(b | (shift(b & TRank2BB) & ~pos.pieces()));
b &= ~pos.pieces()
& ~ei.attackedBy[Them][PAWN]
& (ei.attackedBy[Us][ALL_PIECES] | ~ei.attackedBy[Them][ALL_PIECES]);
- b = (shift_bb(b) | shift_bb(b))
+ b = (shift(b) | shift(b))
& pos.pieces(Them)
& ~ei.attackedBy[Us][PAWN];
@@ -592,25 +613,28 @@ namespace {
}
- // evaluate_passed_pawns() evaluates the passed pawns of the given color
+ // evaluate_passer_pawns() evaluates the passed pawns and candidate passed
+ // pawns of the given color.
template
- Score evaluate_passed_pawns(const Position& pos, const EvalInfo& ei) {
+ Score evaluate_passer_pawns(const Position& pos, const EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
- Bitboard b, squaresToQueen, defendedSquares, unsafeSquares;
+ Bitboard b, bb, squaresToQueen, defendedSquares, unsafeSquares;
Score score = SCORE_ZERO;
- b = ei.pi->passed_pawns(Us);
+ b = ei.pe->passed_pawns(Us);
while (b)
{
Square s = pop_lsb(&b);
- assert(pos.pawn_passed(Us, s));
assert(!(pos.pieces(PAWN) & forward_bb(Us, s)));
+ bb = forward_bb(Us, s) & (ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
+ score -= HinderPassedPawn * popcount(bb);
+
int r = relative_rank(Us, s) - RANK_2;
int rr = r * (r - 1);
@@ -636,7 +660,7 @@ namespace {
// in the pawn's path attacked or occupied by the enemy.
defendedSquares = unsafeSquares = squaresToQueen = forward_bb(Us, s);
- Bitboard bb = forward_bb(Them, s) & pos.pieces(ROOK, QUEEN) & pos.attacks_from(s);
+ bb = forward_bb(Them, s) & pos.pieces(ROOK, QUEEN) & pos.attacks_from(s);
if (!(pos.pieces(Us) & bb))
defendedSquares &= ei.attackedBy[Us][ALL_PIECES];
@@ -662,13 +686,17 @@ namespace {
mbonus += rr + r * 2, ebonus += rr + r * 2;
} // rr != 0
+ // Scale down bonus for candidate passers which need more than one
+ // pawn push to become passed.
+ if (!pos.pawn_passed(Us, s + pawn_push(Us)))
+ mbonus /= 2, ebonus /= 2;
+
score += make_score(mbonus, ebonus) + PassedFile[file_of(s)];
}
if (DoTrace)
Trace::add(PASSED, Us, score);
- // Add the scores to the middlegame and endgame eval
return score;
}
@@ -684,8 +712,8 @@ namespace {
const Color Them = (Us == WHITE ? BLACK : WHITE);
const Bitboard SpaceMask =
- Us == WHITE ? (FileCBB | FileDBB | FileEBB | FileFBB) & (Rank2BB | Rank3BB | Rank4BB)
- : (FileCBB | FileDBB | FileEBB | FileFBB) & (Rank7BB | Rank6BB | Rank5BB);
+ Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB)
+ : CenterFiles & (Rank7BB | Rank6BB | Rank5BB);
// Find the safe squares for our pieces inside the area defined by
// SpaceMask. A square is unsafe if it is attacked by an enemy
@@ -703,12 +731,12 @@ namespace {
// Since SpaceMask[Us] is fully on our half of the board...
assert(unsigned(safe >> (Us == WHITE ? 32 : 0)) == 0);
- // ...count safe + (behind & safe) with a single popcount
+ // ...count safe + (behind & safe) with a single popcount.
int bonus = popcount((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe));
bonus = std::min(16, bonus);
- int weight = pos.count(Us);
+ int weight = pos.count(Us) - 2 * ei.pe->open_files();
- return make_score(bonus * weight * weight / 22, 0);
+ return make_score(bonus * weight * weight / 18, 0);
}
@@ -719,15 +747,15 @@ namespace {
int kingDistance = distance(pos.square(WHITE), pos.square(BLACK))
- distance(pos.square(WHITE), pos.square(BLACK));
- int pawns = pos.count(WHITE) + pos.count(BLACK);
+ bool bothFlanks = (pos.pieces(PAWN) & QueenSide) && (pos.pieces(PAWN) & KingSide);
// Compute the initiative bonus for the attacking side
- int initiative = 8 * (asymmetry + kingDistance - 15) + 12 * pawns;
+ int initiative = 8 * (asymmetry + kingDistance - 17) + 12 * pos.count() + 16 * bothFlanks;
// Now apply the bonus: note that we find the attacking side by extracting
// the sign of the endgame value, and that we carefully cap the bonus so
- // that the endgame score will never be divided by more than two.
- int value = ((eg > 0) - (eg < 0)) * std::max(initiative, -abs(eg / 2));
+ // that the endgame score will never change sign after the bonus.
+ int value = ((eg > 0) - (eg < 0)) * std::max(initiative, -abs(eg));
return make_score(0, value);
}
@@ -741,8 +769,7 @@ namespace {
// If we don't already have an unusual scale factor, check for certain
// types of endgames, and use a lower scale for those.
- if ( ei.me->game_phase() < PHASE_MIDGAME
- && (sf == SCALE_FACTOR_NORMAL || sf == SCALE_FACTOR_ONEPAWN))
+ if (sf == SCALE_FACTOR_NORMAL || sf == SCALE_FACTOR_ONEPAWN)
{
if (pos.opposite_bishops())
{
@@ -750,19 +777,18 @@ namespace {
// is almost a draw, in case of KBP vs KB, it is even more a draw.
if ( pos.non_pawn_material(WHITE) == BishopValueMg
&& pos.non_pawn_material(BLACK) == BishopValueMg)
- sf = more_than_one(pos.pieces(PAWN)) ? ScaleFactor(31) : ScaleFactor(9);
+ return more_than_one(pos.pieces(PAWN)) ? ScaleFactor(31) : ScaleFactor(9);
// Endgame with opposite-colored bishops, but also other pieces. Still
// a bit drawish, but not as drawish as with only the two bishops.
- else
- sf = ScaleFactor(46);
+ return ScaleFactor(46);
}
// Endings where weaker side can place his king in front of the opponent's
// pawns are drawish.
else if ( abs(eg) <= BishopValueEg
&& pos.count(strongSide) <= 2
&& !pos.pawn_passed(~strongSide, pos.square(~strongSide)))
- sf = ScaleFactor(37 + 7 * pos.count(strongSide));
+ return ScaleFactor(37 + 7 * pos.count(strongSide));
}
return sf;
@@ -779,49 +805,38 @@ Value Eval::evaluate(const Position& pos) {
assert(!pos.checkers());
+ Score mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO };
+ Value v;
EvalInfo ei;
- Score score, mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO };
-
- // Initialize score by reading the incrementally updated scores included in
- // the position object (material + piece square tables). Score is computed
- // internally from the white point of view.
- score = pos.psq_score();
// Probe the material hash table
ei.me = Material::probe(pos);
- score += ei.me->imbalance();
// If we have a specialized evaluation function for the current material
// configuration, call it and return.
if (ei.me->specialized_eval_exists())
return ei.me->evaluate(pos);
+ // Initialize score by reading the incrementally updated scores included in
+ // the position object (material + piece square tables) and the material
+ // imbalance. Score is computed internally from the white point of view.
+ Score score = pos.psq_score() + ei.me->imbalance();
+
// Probe the pawn hash table
- ei.pi = Pawns::probe(pos);
- score += ei.pi->pawns_score();
+ ei.pe = Pawns::probe(pos);
+ score += ei.pe->pawns_score();
+
+ // Early exit if score is high
+ v = (mg_value(score) + eg_value(score)) / 2;
+ if (abs(v) > LazyThreshold)
+ return pos.side_to_move() == WHITE ? v : -v;
// Initialize attack and king safety bitboards
- ei.attackedBy[WHITE][ALL_PIECES] = ei.attackedBy[BLACK][ALL_PIECES] = 0;
- ei.attackedBy[WHITE][KING] = pos.attacks_from(pos.square(WHITE));
- ei.attackedBy[BLACK][KING] = pos.attacks_from(pos.square(BLACK));
eval_init(pos, ei);
eval_init(pos, ei);
- // Pawns blocked or on ranks 2 and 3 will be excluded from the mobility area
- Bitboard blockedPawns[] = {
- pos.pieces(WHITE, PAWN) & (shift_bb(pos.pieces()) | Rank2BB | Rank3BB),
- pos.pieces(BLACK, PAWN) & (shift_bb(pos.pieces()) | Rank7BB | Rank6BB)
- };
-
- // Do not include in mobility area squares protected by enemy pawns, or occupied
- // by our blocked pawns or king.
- Bitboard mobilityArea[] = {
- ~(ei.attackedBy[BLACK][PAWN] | blockedPawns[WHITE] | pos.square(WHITE)),
- ~(ei.attackedBy[WHITE][PAWN] | blockedPawns[BLACK] | pos.square(BLACK))
- };
-
// Evaluate all pieces but king and pawns
- score += evaluate_pieces(pos, ei, mobility, mobilityArea);
+ score += evaluate_pieces(pos, ei, mobility);
score += mobility[WHITE] - mobility[BLACK];
// Evaluate kings after all other pieces because we need full attack
@@ -834,34 +849,23 @@ Value Eval::evaluate(const Position& pos) {
- evaluate_threats(pos, ei);
// Evaluate passed pawns, we need full attack information including king
- score += evaluate_passed_pawns(pos, ei)
- - evaluate_passed_pawns(pos, ei);
-
- // If both sides have only pawns, score for potential unstoppable pawns
- if (!pos.non_pawn_material(WHITE) && !pos.non_pawn_material(BLACK))
- {
- Bitboard b;
- if ((b = ei.pi->passed_pawns(WHITE)) != 0)
- score += Unstoppable * int(relative_rank(WHITE, frontmost_sq(WHITE, b)));
-
- if ((b = ei.pi->passed_pawns(BLACK)) != 0)
- score -= Unstoppable * int(relative_rank(BLACK, frontmost_sq(BLACK, b)));
- }
+ score += evaluate_passer_pawns(pos, ei)
+ - evaluate_passer_pawns(pos, ei);
// Evaluate space for both sides, only during opening
- if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >= 12222)
+ if (pos.non_pawn_material() >= 12222)
score += evaluate_space(pos, ei)
- evaluate_space(pos, ei);
// Evaluate position potential for the winning side
- score += evaluate_initiative(pos, ei.pi->pawn_asymmetry(), eg_value(score));
+ score += evaluate_initiative(pos, ei.pe->pawn_asymmetry(), eg_value(score));
// Evaluate scale factor for the winning side
ScaleFactor sf = evaluate_scale_factor(pos, ei, eg_value(score));
// Interpolate between a middlegame and a (scaled by 'sf') endgame score
- Value v = mg_value(score) * int(ei.me->game_phase())
- + eg_value(score) * int(PHASE_MIDGAME - ei.me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
+ v = mg_value(score) * int(ei.me->game_phase())
+ + eg_value(score) * int(PHASE_MIDGAME - ei.me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
v /= int(PHASE_MIDGAME);
@@ -870,10 +874,11 @@ Value Eval::evaluate(const Position& pos) {
{
Trace::add(MATERIAL, pos.psq_score());
Trace::add(IMBALANCE, ei.me->imbalance());
- Trace::add(PAWN, ei.pi->pawns_score());
+ Trace::add(PAWN, ei.pe->pawns_score());
Trace::add(MOBILITY, mobility[WHITE], mobility[BLACK]);
- Trace::add(SPACE, evaluate_space(pos, ei)
- , evaluate_space(pos, ei));
+ if (pos.non_pawn_material() >= 12222)
+ Trace::add(SPACE, evaluate_space(pos, ei)
+ , evaluate_space(pos, ei));
Trace::add(TOTAL, score);
}
@@ -920,19 +925,3 @@ std::string Eval::trace(const Position& pos) {
return ss.str();
}
-
-
-/// init() computes evaluation weights, usually at startup
-
-void Eval::init() {
-
- const int MaxSlope = 322;
- const int Peak = 47410;
- int t = 0;
-
- for (int i = 0; i < 400; ++i)
- {
- t = std::min(Peak, std::min(i * i - 16, t + MaxSlope));
- KingDanger[i] = make_score(t * 268 / 7700, 0);
- }
-}
diff --git a/Engines/Windows/deepfish/srcD/evaluate.h b/Engines/Windows/mcbrain/src/evaluate.h
similarity index 93%
rename from Engines/Windows/deepfish/srcD/evaluate.h
rename to Engines/Windows/mcbrain/src/evaluate.h
index 26661dc..d5cf2f2 100644
--- a/Engines/Windows/deepfish/srcD/evaluate.h
+++ b/Engines/Windows/mcbrain/src/evaluate.h
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -31,7 +31,6 @@ namespace Eval {
const Value Tempo = Value(20); // Must be visible to search
-void init();
std::string trace(const Position& pos);
template
diff --git a/Engines/Windows/deepfish/srcD/main.cpp b/Engines/Windows/mcbrain/src/main.cpp
similarity index 80%
rename from Engines/Windows/deepfish/srcD/main.cpp
rename to Engines/Windows/mcbrain/src/main.cpp
index 1d36e39..c63bc2e 100644
--- a/Engines/Windows/deepfish/srcD/main.cpp
+++ b/Engines/Windows/mcbrain/src/main.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,42 +21,35 @@
#include
#include "bitboard.h"
-#include "evaluate.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
+#include "tzbook.h"
#include "uci.h"
-#include "syzygy/tbprobe.h"
+#include "tbprobe.h"
-void SETUP_PRIVILEGES();
-void FREE_MEM(void *);
+namespace PSQT {
+ void init();
+}
int main(int argc, char* argv[]) {
std::cout << engine_info() << std::endl;
- #ifndef BENCH
- SETUP_PRIVILEGES();
- #endif
+
UCI::init(Options);
- TT.resize(Options["Hash"]);
PSQT::init();
Bitboards::init();
Position::init();
Bitbases::init();
- Search::init();
- Eval::init();
Pawns::init();
Threads.init();
Tablebases::init(Options["SyzygyPath"]);
+ TT.resize(Options["Hash"]);
+ tzbook.init(Options["BookPath"]);
UCI::loop(argc, argv);
- if (large_use) {
- FREE_MEM(TT.mem);
- TT.mem = nullptr;
- }
-
Threads.exit();
return 0;
-}
\ No newline at end of file
+}
diff --git a/Engines/Windows/deepfish/srcD/material.cpp b/Engines/Windows/mcbrain/src/material.cpp
similarity index 95%
rename from Engines/Windows/deepfish/srcD/material.cpp
rename to Engines/Windows/mcbrain/src/material.cpp
index f73977b..498ef33 100644
--- a/Engines/Windows/deepfish/srcD/material.cpp
+++ b/Engines/Windows/mcbrain/src/material.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -31,14 +31,11 @@ namespace {
// Polynomial material imbalance parameters
- // pair pawn knight bishop rook queen
- const int Linear[6] = { 1667, -168, -1027, -166, 238, -138 };
-
const int QuadraticOurs[][PIECE_TYPE_NB] = {
// OUR PIECES
// pair pawn knight bishop rook queen
- { 0 }, // Bishop pair
- { 40, 2 }, // Pawn
+ {1667 }, // Bishop pair
+ { 40, 0 }, // Pawn
{ 32, 255, -3 }, // Knight OUR PIECES
{ 0, 104, 4, 0 }, // Bishop
{ -26, -2, 47, 105, -149 }, // Rook
@@ -56,6 +53,11 @@ namespace {
{ 101, 100, -37, 141, 268, 0 } // Queen
};
+ // PawnsSet[count] contains a bonus/malus indexed by number of pawns
+ const int PawnsSet[9] = {
+ 24, -32, 107, -51, 117, -9, -126, -21, 31
+ };
+
// Endgame evaluation and scaling functions are accessed directly and not through
// the function maps because they correspond to more than one material hash key.
Endgame EvaluateKXK[] = { Endgame(WHITE), Endgame(BLACK) };
@@ -92,7 +94,7 @@ namespace {
const Color Them = (Us == WHITE ? BLACK : WHITE);
- int bonus = 0;
+ int bonus = PawnsSet[pieceCount[Us][PAWN]];
// Second-degree polynomial material imbalance by Tord Romstad
for (int pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1)
@@ -100,7 +102,7 @@ namespace {
if (!pieceCount[Us][pt1])
continue;
- int v = Linear[pt1];
+ int v = 0;
for (int pt2 = NO_PIECE_TYPE; pt2 <= pt1; ++pt2)
v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2]
diff --git a/Engines/Windows/deepfish/srcD/material.h b/Engines/Windows/mcbrain/src/material.h
similarity index 97%
rename from Engines/Windows/deepfish/srcD/material.h
rename to Engines/Windows/mcbrain/src/material.h
index bec2d66..ccf97b7 100644
--- a/Engines/Windows/deepfish/srcD/material.h
+++ b/Engines/Windows/mcbrain/src/material.h
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -56,11 +56,11 @@ struct Entry {
}
Key key;
- int16_t value;
- uint8_t factor[COLOR_NB];
EndgameBase* evaluationFunction;
EndgameBase* scalingFunction[COLOR_NB]; // Could be one for each
// side (e.g. KPKP, KBPsKs)
+ int16_t value;
+ uint8_t factor[COLOR_NB];
Phase gamePhase;
};
diff --git a/Engines/Windows/deepfish/srcD/misc.cpp b/Engines/Windows/mcbrain/src/misc.cpp
similarity index 53%
rename from Engines/Windows/deepfish/srcD/misc.cpp
rename to Engines/Windows/mcbrain/src/misc.cpp
index 19e493b..880e958 100644
--- a/Engines/Windows/deepfish/srcD/misc.cpp
+++ b/Engines/Windows/mcbrain/src/misc.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,10 +18,29 @@
along with this program. If not, see .
*/
+#ifdef _WIN32
+#if _WIN32_WINNT < 0x0601
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0601 // Force to include needed API prototypes
+#endif
+#include
+// The needed Windows API for processor groups could be missed from old Windows
+// versions, so instead of calling them directly (forcing the linker to resolve
+// the calls at compile time), try to load them at runtime. To do this we need
+// first to define the corresponding function pointers.
+extern "C" {
+typedef bool(*fun1_t)(LOGICAL_PROCESSOR_RELATIONSHIP,
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD);
+typedef bool(*fun2_t)(USHORT, PGROUP_AFFINITY);
+typedef bool(*fun3_t)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY);
+}
+#endif
+
#include
#include
#include
#include
+#include
#include "misc.h"
#include "thread.h"
@@ -32,7 +51,7 @@ namespace {
/// Version number. If Version is left empty, then compile date in the format
/// DD-MM-YY and show in engine_info.
-static const string Version = " ";
+const string Version = "2.1a";
/// Our fancy logging facility. The trick here is to replace cin.rdbuf() and
/// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We
@@ -103,7 +122,7 @@ const string engine_info(bool to_uci) {
string month, day, year;
stringstream ss, date(__DATE__); // From compiler, format is "Sep 21 2008"
- ss << "DeepFishMZ" << Version << setfill('0');
+ ss << "McBrain " << Version << setfill('0');
if (Version.empty())
{
@@ -114,10 +133,9 @@ const string engine_info(bool to_uci) {
ss << (Is64Bit ? " 64" : "")
<< (HasPext ? " BMI2" : (HasPopCnt ? " POPCNT" : ""))
<< (to_uci ? "\nid author ": " by ")
- << "T. Romstad, M. Costalba, J. Kiiski, G. Linscott\n"
- << "compiled by M.Z";
+ << "M. Byrne, based on Stockfish";
- return ss.str();
+ return ss.str();
}
@@ -186,3 +204,122 @@ void prefetch(void* addr) {
}
#endif
+
+void prefetch2(void* addr) {
+
+ prefetch(addr);
+ prefetch((uint8_t*)addr + 64);
+}
+
+namespace WinProcGroup {
+
+#ifndef _WIN32
+
+void bindThisThread(size_t) {}
+
+#else
+
+/// get_group() retrieves logical processor information using Windows specific
+/// API and returns the best group id for the thread with index idx. Original
+/// code from Texel by Peter Österlund.
+
+int get_group(size_t idx) {
+
+ int threads = 0;
+ int nodes = 0;
+ int cores = 0;
+ DWORD returnLength = 0;
+ DWORD byteOffset = 0;
+
+ // Early exit if the needed API is not available at runtime
+ HMODULE k32 = GetModuleHandle("Kernel32.dll");
+ auto fun1 = (fun1_t)GetProcAddress(k32, "GetLogicalProcessorInformationEx");
+ if (!fun1)
+ return -1;
+
+ // First call to get returnLength. We expect it to fail due to null buffer
+ if (fun1(RelationAll, nullptr, &returnLength))
+ return -1;
+
+ // Once we know returnLength, allocate the buffer
+ SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buffer, *ptr;
+ ptr = buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(returnLength);
+
+ // Second call, now we expect to succeed
+ if (!fun1(RelationAll, buffer, &returnLength))
+ {
+ free(buffer);
+ return -1;
+ }
+
+ while (ptr->Size > 0 && byteOffset + ptr->Size <= returnLength)
+ {
+ if (ptr->Relationship == RelationNumaNode)
+ nodes++;
+
+ else if (ptr->Relationship == RelationProcessorCore)
+ {
+ cores++;
+ threads += (ptr->Processor.Flags == LTP_PC_SMT) ? 2 : 1;
+ }
+
+ byteOffset += ptr->Size;
+ ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((char*)ptr) + ptr->Size);
+ }
+
+ free(buffer);
+
+ std::vector groups;
+
+ // Run as many threads as possible on the same node until core limit is
+ // reached, then move on filling the next node.
+ for (int n = 0; n < nodes; n++)
+ for (int i = 0; i < cores / nodes; i++)
+ groups.push_back(n);
+
+ // In case a core has more than one logical processor (we assume 2) and we
+ // have still threads to allocate, then spread them evenly across available
+ // nodes.
+ for (int t = 0; t < threads - cores; t++)
+ groups.push_back(t % nodes);
+
+ // If we still have more threads than the total number of logical processors
+ // then return -1 and let the OS to decide what to do.
+ return idx < groups.size() ? groups[idx] : -1;
+}
+
+
+/// bindThisThread() set the group affinity of the current thread
+
+void bindThisThread(size_t idx) {
+
+ // If OS already scheduled us on a different group than 0 then don't overwrite
+ // the choice, eventually we are one of many one-threaded processes running on
+ // some Windows NUMA hardware, for instance in fishtest. To make it simple,
+ // just check if running threads are below a threshold, in this case all this
+ // NUMA machinery is not needed.
+ if (Threads.size() < 8)
+ return;
+
+ // Use only local variables to be thread-safe
+ int group = get_group(idx);
+
+ if (group == -1)
+ return;
+
+ // Early exit if the needed API are not available at runtime
+ HMODULE k32 = GetModuleHandle("Kernel32.dll");
+ auto fun2 = (fun2_t)GetProcAddress(k32, "GetNumaNodeProcessorMaskEx");
+ auto fun3 = (fun3_t)GetProcAddress(k32, "SetThreadGroupAffinity");
+
+ if (!fun2 || !fun3)
+ return;
+
+ GROUP_AFFINITY affinity;
+ if (fun2(group, &affinity))
+ fun3(GetCurrentThread(), &affinity, nullptr);
+}
+
+#endif
+
+} // namespace WinProcGroup
diff --git a/Engines/Windows/deepfish/srcD/misc.h b/Engines/Windows/mcbrain/src/misc.h
similarity index 85%
rename from Engines/Windows/deepfish/srcD/misc.h
rename to Engines/Windows/mcbrain/src/misc.h
index a2307fe..b63e613 100644
--- a/Engines/Windows/deepfish/srcD/misc.h
+++ b/Engines/Windows/mcbrain/src/misc.h
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -31,6 +31,7 @@
const std::string engine_info(bool to_uci = false);
void prefetch(void* addr);
+void prefetch2(void* addr);
void start_logger(const std::string& fname);
void dbg_hit_on(bool b);
@@ -97,4 +98,15 @@ class PRNG {
{ return T(rand64() & rand64() & rand64()); }
};
+
+/// Under Windows it is not possible for a process to run on more than one
+/// logical processor group. This usually means to be limited to use max 64
+/// cores. To overcome this, some special platform specific API should be
+/// called to set group affinity for each thread. Original code from Texel by
+/// Peter Österlund.
+
+namespace WinProcGroup {
+ void bindThisThread(size_t idx);
+}
+
#endif // #ifndef MISC_H_INCLUDED
diff --git a/Engines/Windows/deepfish/srcD/movegen.cpp b/Engines/Windows/mcbrain/src/movegen.cpp
similarity index 88%
rename from Engines/Windows/deepfish/srcD/movegen.cpp
rename to Engines/Windows/mcbrain/src/movegen.cpp
index efa47bd..ac5f565 100644
--- a/Engines/Windows/deepfish/srcD/movegen.cpp
+++ b/Engines/Windows/mcbrain/src/movegen.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -42,8 +42,8 @@ namespace {
assert(!pos.checkers());
- const Square K = Chess960 ? kto > kfrom ? DELTA_W : DELTA_E
- : KingSide ? DELTA_W : DELTA_E;
+ const Square K = Chess960 ? kto > kfrom ? WEST : EAST
+ : KingSide ? WEST : EAST;
for (Square s = kto; s != kfrom; s += K)
if (pos.attackers_to(s) & enemies)
@@ -65,23 +65,23 @@ namespace {
}
- template
+ template
ExtMove* make_promotions(ExtMove* moveList, Square to, Square ksq) {
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
- *moveList++ = make(to - Delta, to, QUEEN);
+ *moveList++ = make(to - D, to, QUEEN);
if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS)
{
- *moveList++ = make(to - Delta, to, ROOK);
- *moveList++ = make(to - Delta, to, BISHOP);
- *moveList++ = make(to - Delta, to, KNIGHT);
+ *moveList++ = make(to - D, to, ROOK);
+ *moveList++ = make(to - D, to, BISHOP);
+ *moveList++ = make(to - D, to, KNIGHT);
}
// Knight promotion is the only promotion that can give a direct check
// that's not already included in the queen promotion.
if (Type == QUIET_CHECKS && (StepAttacksBB[W_KNIGHT][to] & ksq))
- *moveList++ = make(to - Delta, to, KNIGHT);
+ *moveList++ = make(to - D, to, KNIGHT);
else
(void)ksq; // Silence a warning under MSVC
@@ -94,13 +94,13 @@ namespace {
// Compute our parametrized parameters at compile time, named according to
// the point of view of white side.
- const Color Them = (Us == WHITE ? BLACK : WHITE);
- const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
- const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
- const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
- const Square Up = (Us == WHITE ? DELTA_N : DELTA_S);
- const Square Right = (Us == WHITE ? DELTA_NE : DELTA_SW);
- const Square Left = (Us == WHITE ? DELTA_NW : DELTA_SE);
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
+ const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
+ const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
+ const Square Up = (Us == WHITE ? NORTH : SOUTH);
+ const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
+ const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
Bitboard emptySquares;
@@ -115,8 +115,8 @@ namespace {
{
emptySquares = (Type == QUIETS || Type == QUIET_CHECKS ? target : ~pos.pieces());
- Bitboard b1 = shift_bb(pawnsNotOn7) & emptySquares;
- Bitboard b2 = shift_bb(b1 & TRank3BB) & emptySquares;
+ Bitboard b1 = shift(pawnsNotOn7) & emptySquares;
+ Bitboard b2 = shift(b1 & TRank3BB) & emptySquares;
if (Type == EVASIONS) // Consider only blocking squares
{
@@ -138,8 +138,8 @@ namespace {
Bitboard dcCandidates = pos.discovered_check_candidates();
if (pawnsNotOn7 & dcCandidates)
{
- Bitboard dc1 = shift_bb(pawnsNotOn7 & dcCandidates) & emptySquares & ~file_bb(ksq);
- Bitboard dc2 = shift_bb(dc1 & TRank3BB) & emptySquares;
+ Bitboard dc1 = shift(pawnsNotOn7 & dcCandidates) & emptySquares & ~file_bb(ksq);
+ Bitboard dc2 = shift(dc1 & TRank3BB) & emptySquares;
b1 |= dc1;
b2 |= dc2;
@@ -168,9 +168,9 @@ namespace {
if (Type == EVASIONS)
emptySquares &= target;
- Bitboard b1 = shift_bb(pawnsOn7) & enemies;
- Bitboard b2 = shift_bb(pawnsOn7) & enemies;
- Bitboard b3 = shift_bb(pawnsOn7) & emptySquares;
+ Bitboard b1 = shift(pawnsOn7) & enemies;
+ Bitboard b2 = shift(pawnsOn7) & enemies;
+ Bitboard b3 = shift(pawnsOn7) & emptySquares;
Square ksq = pos.square(Them);
@@ -187,8 +187,8 @@ namespace {
// Standard and en-passant captures
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
{
- Bitboard b1 = shift_bb(pawnsNotOn7) & enemies;
- Bitboard b2 = shift_bb(pawnsNotOn7) & enemies;
+ Bitboard b1 = shift(pawnsNotOn7) & enemies;
+ Bitboard b2 = shift(pawnsNotOn7) & enemies;
while (b1)
{
diff --git a/Engines/Windows/deepfish/srcD/movegen.h b/Engines/Windows/mcbrain/src/movegen.h
similarity index 96%
rename from Engines/Windows/deepfish/srcD/movegen.h
rename to Engines/Windows/mcbrain/src/movegen.h
index 2721f15..33177ed 100644
--- a/Engines/Windows/deepfish/srcD/movegen.h
+++ b/Engines/Windows/mcbrain/src/movegen.h
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/Engines/Windows/deepfish/srcD/movepick.cpp b/Engines/Windows/mcbrain/src/movepick.cpp
similarity index 57%
rename from Engines/Windows/deepfish/srcD/movepick.cpp
rename to Engines/Windows/mcbrain/src/movepick.cpp
index 78765be..bfa5e4f 100644
--- a/Engines/Windows/deepfish/srcD/movepick.cpp
+++ b/Engines/Windows/mcbrain/src/movepick.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,13 +26,12 @@
namespace {
enum Stages {
- MAIN_SEARCH, GOOD_CAPTURES, KILLERS, QUIET, BAD_CAPTURES,
- EVASION, ALL_EVASIONS,
- QSEARCH_WITH_CHECKS, QCAPTURES_1, CHECKS,
- QSEARCH_WITHOUT_CHECKS, QCAPTURES_2,
- PROBCUT, PROBCUT_CAPTURES,
- RECAPTURE, RECAPTURES,
- STOP
+ MAIN_SEARCH, CAPTURES_INIT, GOOD_CAPTURES, KILLERS, COUNTERMOVE, QUIET_INIT, QUIET, BAD_CAPTURES,
+ EVASION, EVASIONS_INIT, ALL_EVASIONS,
+ PROBCUT, PROBCUT_INIT, PROBCUT_CAPTURES,
+ QSEARCH_WITH_CHECKS, QCAPTURES_1_INIT, QCAPTURES_1, QCHECKS,
+ QSEARCH_NO_CHECKS, QCAPTURES_2_INIT, QCAPTURES_2,
+ QSEARCH_RECAPTURES, QRECAPTURES
};
// Our insertion sort, which is guaranteed to be stable, as it should be
@@ -77,7 +76,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, Search::Stack* s)
stage = pos.checkers() ? EVASION : MAIN_SEARCH;
ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE;
- endMoves += (ttMove != MOVE_NONE);
+ stage += (ttMove == MOVE_NONE);
}
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, Square s)
@@ -92,17 +91,17 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, Square s)
stage = QSEARCH_WITH_CHECKS;
else if (d > DEPTH_QS_RECAPTURES)
- stage = QSEARCH_WITHOUT_CHECKS;
+ stage = QSEARCH_NO_CHECKS;
else
{
- stage = RECAPTURE;
+ stage = QSEARCH_RECAPTURES;
recaptureSquare = s;
- ttm = MOVE_NONE;
+ return;
}
ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE;
- endMoves += (ttMove != MOVE_NONE);
+ stage += (ttMove == MOVE_NONE);
}
MovePicker::MovePicker(const Position& p, Move ttm, Value th)
@@ -112,13 +111,13 @@ MovePicker::MovePicker(const Position& p, Move ttm, Value th)
stage = PROBCUT;
- // In ProbCut we generate captures with SEE higher than the given threshold
+ // In ProbCut we generate captures with SEE higher than or equal to the given threshold
ttMove = ttm
&& pos.pseudo_legal(ttm)
&& pos.capture(ttm)
- && pos.see(ttm) > threshold ? ttm : MOVE_NONE;
+ && pos.see_ge(ttm, threshold)? ttm : MOVE_NONE;
- endMoves += (ttMove != MOVE_NONE);
+ stage += (ttMove == MOVE_NONE);
}
@@ -142,71 +141,102 @@ template<>
void MovePicker::score() {
const HistoryStats& history = pos.this_thread()->history;
- const FromToStats& fromTo = pos.this_thread()->fromTo;
- const CounterMoveStats* cm = (ss-1)->counterMoves;
- const CounterMoveStats* fm = (ss-2)->counterMoves;
- const CounterMoveStats* f2 = (ss-4)->counterMoves;
+ const CounterMoveStats& cmh = *(ss-1)->counterMoves;
+ const CounterMoveStats& fmh = *(ss-2)->counterMoves;
+ const CounterMoveStats& fm2 = *(ss-4)->counterMoves;
Color c = pos.side_to_move();
for (auto& m : *this)
- m.value = history[pos.moved_piece(m)][to_sq(m)]
- + (cm ? (*cm)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
- + (fm ? (*fm)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
- + (f2 ? (*f2)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
- + fromTo.get(c, m);
+ m.value = cmh[pos.moved_piece(m)][to_sq(m)]
+ + fmh[pos.moved_piece(m)][to_sq(m)]
+ + fm2[pos.moved_piece(m)][to_sq(m)]
+ + history.get(c, m);
}
template<>
void MovePicker::score() {
- // Try winning and equal captures ordered by MVV/LVA, then non-captures ordered
- // by history value, then bad captures and quiet moves with a negative SEE ordered
- // by SEE value.
+ // Try captures ordered by MVV/LVA, then non-captures ordered by stats heuristics
const HistoryStats& history = pos.this_thread()->history;
- const FromToStats& fromTo = pos.this_thread()->fromTo;
Color c = pos.side_to_move();
- Value see;
for (auto& m : *this)
- if ((see = pos.see_sign(m)) < VALUE_ZERO)
- m.value = see - HistoryStats::Max; // At the bottom
-
- else if (pos.capture(m))
+ if (pos.capture(m))
m.value = PieceValue[MG][pos.piece_on(to_sq(m))]
- Value(type_of(pos.moved_piece(m))) + HistoryStats::Max;
else
- m.value = history[pos.moved_piece(m)][to_sq(m)] + fromTo.get(c, m);
+ m.value = history.get(c, m);
}
-/// generate_next_stage() generates, scores, and sorts the next bunch of moves
-/// when there are no more moves to try for the current stage.
+/// next_move() is the most important method of the MovePicker class. It returns
+/// a new pseudo legal move every time it is called, until there are no more moves
+/// left. It picks the move with the biggest value from a list of generated moves
+/// taking care not to return the ttMove if it has already been searched.
-void MovePicker::generate_next_stage() {
+Move MovePicker::next_move(bool skipQuiets, bool skipBadCaptures) {
- assert(stage != STOP);
+ Move move;
- cur = moves;
+ switch (stage) {
- switch (++stage) {
+ case MAIN_SEARCH: case EVASION: case QSEARCH_WITH_CHECKS:
+ case QSEARCH_NO_CHECKS: case PROBCUT:
+ ++stage;
+ return ttMove;
- case GOOD_CAPTURES: case QCAPTURES_1: case QCAPTURES_2:
- case PROBCUT_CAPTURES: case RECAPTURES:
- endMoves = generate(pos, moves);
+ case CAPTURES_INIT:
+ endBadCaptures = cur = moves;
+ endMoves = generate(pos, cur);
score();
- break;
+ ++stage;
- case KILLERS:
- killers[0] = ss->killers[0];
- killers[1] = ss->killers[1];
- killers[2] = countermove;
- cur = killers;
- endMoves = cur + 2 + (countermove != killers[0] && countermove != killers[1]);
- break;
+ case GOOD_CAPTURES:
+ while (cur < endMoves)
+ {
+ move = pick_best(cur++, endMoves);
+ if (move != ttMove)
+ {
+ if (pos.see_ge(move, VALUE_ZERO))
+ return move;
- case QUIET:
- endMoves = generate(pos, moves);
+ // Losing capture, move it to the beginning of the array
+ *endBadCaptures++ = move;
+ }
+ }
+
+ ++stage;
+ move = ss->killers[0]; // First killer move
+ if ( move != MOVE_NONE
+ && move != ttMove
+ && pos.pseudo_legal(move)
+ && !pos.capture(move))
+ return move;
+
+ case KILLERS:
+ ++stage;
+ move = ss->killers[1]; // Second killer move
+ if ( move != MOVE_NONE
+ && move != ttMove
+ && pos.pseudo_legal(move)
+ && !pos.capture(move))
+ return move;
+
+ case COUNTERMOVE:
+ ++stage;
+ move = countermove;
+ if ( move != MOVE_NONE
+ && move != ttMove
+ && move != ss->killers[0]
+ && move != ss->killers[1]
+ && pos.pseudo_legal(move)
+ && !pos.capture(move))
+ return move;
+
+ case QUIET_INIT:
+ cur = endBadCaptures;
+ endMoves = generate(pos, cur);
score();
if (depth < 3 * ONE_PLY)
{
@@ -215,118 +245,104 @@ void MovePicker::generate_next_stage() {
insertion_sort(cur, goodQuiet);
} else
insertion_sort(cur, endMoves);
- break;
+ ++stage;
+
+ case QUIET:
+ while (cur < endMoves
+ && (!skipQuiets || cur->value >= VALUE_ZERO))
+ {
+ move = *cur++;
+ if ( move != ttMove
+ && move != ss->killers[0]
+ && move != ss->killers[1]
+ && move != countermove)
+ return move;
+ }
+ ++stage;
+ cur = moves; // Point to beginning of bad captures
case BAD_CAPTURES:
- // Just pick them in reverse order to get correct ordering
- cur = moves + MAX_MOVES - 1;
- endMoves = endBadCaptures;
+ if (cur < endBadCaptures && !skipBadCaptures)
+ return *cur++;
break;
+ case EVASIONS_INIT:
+ cur = moves;
+ endMoves = generate(pos, cur);
+ score();
+ ++stage;
+
case ALL_EVASIONS:
- endMoves = generate(pos, moves);
- if (endMoves - moves > 1)
- score();
+ while (cur < endMoves)
+ {
+ move = pick_best(cur++, endMoves);
+ if (move != ttMove)
+ return move;
+ }
break;
- case CHECKS:
- endMoves = generate(pos, moves);
- break;
+ case PROBCUT_INIT:
+ cur = moves;
+ endMoves = generate(pos, cur);
+ score();
+ ++stage;
- case EVASION: case QSEARCH_WITH_CHECKS: case QSEARCH_WITHOUT_CHECKS:
- case PROBCUT: case RECAPTURE: case STOP:
- stage = STOP;
+ case PROBCUT_CAPTURES:
+ while (cur < endMoves)
+ {
+ move = pick_best(cur++, endMoves);
+ if ( move != ttMove
+ && pos.see_ge(move, threshold))
+ return move;
+ }
break;
- default:
- assert(false);
- }
-}
-
-
-/// next_move() is the most important method of the MovePicker class. It returns
-/// a new pseudo legal move every time it is called, until there are no more moves
-/// left. It picks the move with the biggest value from a list of generated moves
-/// taking care not to return the ttMove if it has already been searched.
-
-Move MovePicker::next_move() {
-
- Move move;
-
- while (true)
- {
- while (cur == endMoves && stage != STOP)
- generate_next_stage();
-
- switch (stage) {
-
- case MAIN_SEARCH: case EVASION: case QSEARCH_WITH_CHECKS:
- case QSEARCH_WITHOUT_CHECKS: case PROBCUT:
- ++cur;
- return ttMove;
+ case QCAPTURES_1_INIT: case QCAPTURES_2_INIT:
+ cur = moves;
+ endMoves = generate(pos, cur);
+ score();
+ ++stage;
- case GOOD_CAPTURES:
+ case QCAPTURES_1: case QCAPTURES_2:
+ while (cur < endMoves)
+ {
move = pick_best(cur++, endMoves);
if (move != ttMove)
- {
- if (pos.see_sign(move) >= VALUE_ZERO)
- return move;
-
- // Losing capture, move it to the tail of the array
- *endBadCaptures-- = move;
- }
- break;
-
- case KILLERS:
- move = *cur++;
- if ( move != MOVE_NONE
- && move != ttMove
- && pos.pseudo_legal(move)
- && !pos.capture(move))
- return move;
- break;
-
- case QUIET:
- move = *cur++;
- if ( move != ttMove
- && move != killers[0]
- && move != killers[1]
- && move != killers[2])
return move;
+ }
+ if (stage == QCAPTURES_2)
break;
+ cur = moves;
+ endMoves = generate(pos, cur);
+ ++stage;
- case BAD_CAPTURES:
- return *cur--;
-
- case ALL_EVASIONS: case QCAPTURES_1: case QCAPTURES_2:
- move = pick_best(cur++, endMoves);
+ case QCHECKS:
+ while (cur < endMoves)
+ {
+ move = cur++->move;
if (move != ttMove)
return move;
- break;
+ }
+ break;
- case PROBCUT_CAPTURES:
- move = pick_best(cur++, endMoves);
- if (move != ttMove && pos.see(move) > threshold)
- return move;
- break;
+ case QSEARCH_RECAPTURES:
+ cur = moves;
+ endMoves = generate(pos, cur);
+ score();
+ ++stage;
- case RECAPTURES:
+ case QRECAPTURES:
+ while (cur < endMoves)
+ {
move = pick_best(cur++, endMoves);
if (to_sq(move) == recaptureSquare)
return move;
- break;
-
- case CHECKS:
- move = *cur++;
- if (move != ttMove)
- return move;
- break;
-
- case STOP:
- return MOVE_NONE;
-
- default:
- assert(false);
}
+ break;
+
+ default:
+ assert(false);
}
+
+ return MOVE_NONE;
}
diff --git a/Engines/Windows/deepfish/srcD/movepick.h b/Engines/Windows/mcbrain/src/movepick.h
similarity index 62%
rename from Engines/Windows/deepfish/srcD/movepick.h
rename to Engines/Windows/mcbrain/src/movepick.h
index 8028d48..d87ce85 100644
--- a/Engines/Windows/deepfish/srcD/movepick.h
+++ b/Engines/Windows/mcbrain/src/movepick.h
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,34 +26,46 @@
#include "movegen.h"
#include "position.h"
-#include "search.h"
#include "types.h"
-/// The Stats struct stores moves statistics. According to the template parameter
-/// the class can store History and Countermoves. History records how often
-/// different moves have been successful or unsuccessful during the current search
-/// and is used for reduction and move ordering decisions.
-/// Countermoves store the move that refute a previous one. Entries are stored
-/// using only the moving piece and destination square, hence two moves with
-/// different origin but same destination and piece will be considered identical.
-template
-struct Stats {
+/// HistoryStats records how often quiet moves have been successful or unsuccessful
+/// during the current search, and is used for reduction and move ordering decisions.
+struct HistoryStats {
static const Value Max = Value(1 << 28);
+ Value get(Color c, Move m) const { return table[c][from_sq(m)][to_sq(m)]; }
+ void clear() { std::memset(table, 0, sizeof(table)); }
+ void update(Color c, Move m, Value v) {
+
+ Square from = from_sq(m);
+ Square to = to_sq(m);
+
+ table[c][from][to] -= table[c][from][to] * abs(int(v)) / 324;
+ table[c][from][to] += int(v) * 32;
+ }
+
+private:
+ Value table[COLOR_NB][SQUARE_NB][SQUARE_NB];
+};
+
+
+/// A template struct, used to generate MoveStats and CounterMoveHistoryStats:
+/// MoveStats store the move that refute a previous one.
+/// CounterMoveHistoryStats is like HistoryStats, but with two consecutive moves.
+/// Entries are stored using only the moving piece and destination square, hence
+/// two moves with different origin but same destination and piece will be
+/// considered identical.
+template
+struct Stats {
const T* operator[](Piece pc) const { return table[pc]; }
T* operator[](Piece pc) { return table[pc]; }
void clear() { std::memset(table, 0, sizeof(table)); }
-
void update(Piece pc, Square to, Move m) { table[pc][to] = m; }
-
void update(Piece pc, Square to, Value v) {
- if (abs(int(v)) >= 324)
- return;
-
- table[pc][to] -= table[pc][to] * abs(int(v)) / (CM ? 936 : 324);
+ table[pc][to] -= table[pc][to] * abs(int(v)) / 936;
table[pc][to] += int(v) * 32;
}
@@ -62,30 +74,9 @@ struct Stats {
};
typedef Stats MoveStats;
-typedef Stats HistoryStats;
-typedef Stats CounterMoveStats;
+typedef Stats CounterMoveStats;
typedef Stats CounterMoveHistoryStats;
-struct FromToStats {
-
- Value get(Color c, Move m) const { return table[c][from_sq(m)][to_sq(m)]; }
- void clear() { std::memset(table, 0, sizeof(table)); }
-
- void update(Color c, Move m, Value v)
- {
- if (abs(int(v)) >= 324)
- return;
-
- Square f = from_sq(m);
- Square t = to_sq(m);
-
- table[c][f][t] -= table[c][f][t] * abs(int(v)) / 324;
- table[c][f][t] += int(v) * 32;
- }
-
-private:
- Value table[COLOR_NB][SQUARE_NB][SQUARE_NB];
-};
/// MovePicker class is used to pick one pseudo legal move at a time from the
/// current position. The most important method is next_move(), which returns a
@@ -93,6 +84,7 @@ struct FromToStats {
/// when MOVE_NONE is returned. In order to improve the efficiency of the alpha
/// beta algorithm, MovePicker attempts to return the moves which are most likely
/// to get a cut-off first.
+namespace Search { struct Stack; }
class MovePicker {
public:
@@ -103,12 +95,11 @@ class MovePicker {
MovePicker(const Position&, Move, Depth, Square);
MovePicker(const Position&, Move, Depth, Search::Stack*);
- Move next_move();
+ Move next_move(bool skipQuiets = false, bool skipBadCaptures = false);
private:
template void score();
- void generate_next_stage();
- ExtMove* begin() { return moves; }
+ ExtMove* begin() { return cur; }
ExtMove* end() { return endMoves; }
const Position& pos;
@@ -116,12 +107,11 @@ class MovePicker {
Move countermove;
Depth depth;
Move ttMove;
- ExtMove killers[3];
Square recaptureSquare;
Value threshold;
int stage;
- ExtMove* endBadCaptures = moves + MAX_MOVES - 1;
- ExtMove moves[MAX_MOVES], *cur = moves, *endMoves = moves;
+ ExtMove *cur, *endMoves, *endBadCaptures;
+ ExtMove moves[MAX_MOVES];
};
#endif // #ifndef MOVEPICK_H_INCLUDED
diff --git a/Engines/Windows/deepfish/srcD/pawns.cpp b/Engines/Windows/mcbrain/src/pawns.cpp
similarity index 72%
rename from Engines/Windows/deepfish/srcD/pawns.cpp
rename to Engines/Windows/mcbrain/src/pawns.cpp
index 72496fc..10f6723 100644
--- a/Engines/Windows/deepfish/srcD/pawns.cpp
+++ b/Engines/Windows/mcbrain/src/pawns.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -37,46 +37,51 @@ namespace {
// Backward pawn penalty by opposed flag
const Score Backward[2] = { S(56, 33), S(41, 19) };
- // Unsupported pawn penalty for pawns which are neither isolated or backward,
- // by number of pawns it supports [less than 2 / exactly 2].
- const Score Unsupported[2] = { S(17, 8), S(21, 12) };
+ // Unsupported pawn penalty for pawns which are neither isolated or backward
+ const Score Unsupported = S(17, 8);
// Connected pawn bonus by opposed, phalanx, twice supported and rank
Score Connected[2][2][2][RANK_NB];
// Doubled pawn penalty
- const Score Doubled = S(18,38);
+ const Score Doubled = S(18, 38);
// Lever bonus by rank
const Score Lever[RANK_NB] = {
S( 0, 0), S( 0, 0), S(0, 0), S(0, 0),
- S(17, 16), S(33, 32), S(0, 0), S(0, 0) };
+ S(17, 16), S(33, 32), S(0, 0), S(0, 0)
+ };
- // Weakness of our pawn shelter in front of the king by [distance from edge][rank]
+ // Weakness of our pawn shelter in front of the king by [distance from edge][rank].
+ // RANK_1 = 0 is used for files where we have no pawns or our pawn is behind our king.
const Value ShelterWeakness[][RANK_NB] = {
- { V( 97), V(21), V(26), V(51), V(87), V( 89), V( 99) },
- { V(120), V( 0), V(28), V(76), V(88), V(103), V(104) },
- { V(101), V( 7), V(54), V(78), V(77), V( 92), V(101) },
- { V( 80), V(11), V(44), V(68), V(87), V( 90), V(119) } };
-
- // Danger of enemy pawns moving toward our king by [type][distance from edge][rank]
+ { V(100), V(20), V(10), V(46), V(82), V( 86), V( 98) },
+ { V(116), V( 4), V(28), V(87), V(94), V(108), V(104) },
+ { V(109), V( 1), V(59), V(87), V(62), V( 91), V(116) },
+ { V( 75), V(12), V(43), V(59), V(90), V( 84), V(112) }
+ };
+
+ // Danger of enemy pawns moving toward our king by [type][distance from edge][rank].
+ // For the unopposed and unblocked cases, RANK_1 = 0 is used when opponent has no pawn
+ // on the given file, or their pawn is behind our king.
const Value StormDanger[][4][RANK_NB] = {
- { { V( 0), V( 67), V( 134), V(38), V(32) },
- { V( 0), V( 57), V( 139), V(37), V(22) },
- { V( 0), V( 43), V( 115), V(43), V(27) },
- { V( 0), V( 68), V( 124), V(57), V(32) } },
- { { V(20), V( 43), V( 100), V(56), V(20) },
- { V(23), V( 20), V( 98), V(40), V(15) },
- { V(23), V( 39), V( 103), V(36), V(18) },
- { V(28), V( 19), V( 108), V(42), V(26) } },
- { { V( 0), V( 0), V( 75), V(14), V( 2) },
- { V( 0), V( 0), V( 150), V(30), V( 4) },
- { V( 0), V( 0), V( 160), V(22), V( 5) },
- { V( 0), V( 0), V( 166), V(24), V(13) } },
- { { V( 0), V(-283), V(-281), V(57), V(31) },
- { V( 0), V( 58), V( 141), V(39), V(18) },
- { V( 0), V( 65), V( 142), V(48), V(32) },
- { V( 0), V( 60), V( 126), V(51), V(19) } } };
+ { { V( 0), V(-290), V(-274), V(57), V(41) }, //BlockedByKing
+ { V( 0), V( 60), V( 144), V(39), V(13) },
+ { V( 0), V( 65), V( 141), V(41), V(34) },
+ { V( 0), V( 53), V( 127), V(56), V(14) } },
+ { { V( 4), V( 73), V( 132), V(46), V(31) }, //Unopposed
+ { V( 1), V( 64), V( 143), V(26), V(13) },
+ { V( 1), V( 47), V( 110), V(44), V(24) },
+ { V( 0), V( 72), V( 127), V(50), V(31) } },
+ { { V( 0), V( 0), V( 79), V(23), V( 1) }, //BlockedByPawn
+ { V( 0), V( 0), V( 148), V(27), V( 2) },
+ { V( 0), V( 0), V( 161), V(16), V( 1) },
+ { V( 0), V( 0), V( 171), V(22), V(15) } },
+ { { V(22), V( 45), V( 104), V(62), V( 6) }, //Unblocked
+ { V(31), V( 30), V( 99), V(39), V(19) },
+ { V(23), V( 29), V( 96), V(41), V(15) },
+ { V(21), V( 23), V( 116), V(41), V(15) } }
+ };
// Max bonus for king safety. Corresponds to start position with all the pawns
// in front of the king and no enemy pawn on the horizon.
@@ -88,14 +93,15 @@ namespace {
template
Score evaluate(const Position& pos, Pawns::Entry* e) {
- const Color Them = (Us == WHITE ? BLACK : WHITE);
- const Square Up = (Us == WHITE ? DELTA_N : DELTA_S);
- const Square Right = (Us == WHITE ? DELTA_NE : DELTA_SW);
- const Square Left = (Us == WHITE ? DELTA_NW : DELTA_SE);
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const Square Up = (Us == WHITE ? NORTH : SOUTH);
+ const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
+ const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
Bitboard b, neighbours, stoppers, doubled, supported, phalanx;
+ Bitboard lever, leverPush, connected;
Square s;
- bool opposed, lever, connected, backward;
+ bool opposed, backward;
Score score = SCORE_ZERO;
const Square* pl = pos.squares(Us);
const Bitboard* pawnAttacksBB = StepAttacksBB[make_piece(Us, PAWN)];
@@ -103,10 +109,10 @@ namespace {
Bitboard ourPawns = pos.pieces(Us , PAWN);
Bitboard theirPawns = pos.pieces(Them, PAWN);
- e->passedPawns[Us] = e->pawnAttacksSpan[Us] = 0;
- e->kingSquares[Us] = SQ_NONE;
+ e->passedPawns[Us] = e->pawnAttacksSpan[Us] = 0;
e->semiopenFiles[Us] = 0xFF;
- e->pawnAttacks[Us] = shift_bb(ourPawns) | shift_bb(ourPawns);
+ e->kingSquares[Us] = SQ_NONE;
+ e->pawnAttacks[Us] = shift(ourPawns) | shift(ourPawns);
e->pawnsOnSquares[Us][BLACK] = popcount(ourPawns & DarkSquares);
e->pawnsOnSquares[Us][WHITE] = pos.count(Us) - e->pawnsOnSquares[Us][BLACK];
@@ -117,13 +123,14 @@ namespace {
File f = file_of(s);
- e->semiopenFiles[Us] &= ~(1 << f);
+ e->semiopenFiles[Us] &= ~(1 << f);
e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s);
// Flag the pawn
opposed = theirPawns & forward_bb(Us, s);
stoppers = theirPawns & passed_pawn_mask(Us, s);
lever = theirPawns & pawnAttacksBB[s];
+ leverPush = theirPawns & pawnAttacksBB[s + Up];
doubled = ourPawns & (s + Up);
neighbours = ourPawns & adjacent_files_bb(f);
phalanx = neighbours & rank_bb(s);
@@ -142,14 +149,19 @@ namespace {
// The pawn is backward when it cannot safely progress to that rank:
// either there is a stopper in the way on this rank, or there is a
// stopper on adjacent file which controls the way to that rank.
- backward = (b | shift_bb(b & adjacent_files_bb(f))) & stoppers;
+ backward = (b | shift(b & adjacent_files_bb(f))) & stoppers;
assert(!backward || !(pawn_attack_span(Them, s + Up) & neighbours));
}
// Passed pawns will be properly scored in evaluation because we need
- // full attack info to evaluate them.
- if (!stoppers && !(ourPawns & forward_bb(Us, s)))
+ // full attack info to evaluate them. Include also not passed pawns
+ // which could become passed after one or two pawn pushes when are
+ // not attacked more times than defended.
+ if ( !(stoppers ^ lever ^ leverPush)
+ && !(ourPawns & forward_bb(Us, s))
+ && popcount(supported) >= popcount(lever)
+ && popcount(phalanx) >= popcount(leverPush))
e->passedPawns[Us] |= s;
// Score this pawn
@@ -160,7 +172,7 @@ namespace {
score -= Backward[opposed];
else if (!supported)
- score -= Unsupported[more_than_one(neighbours & pawnAttacksBB[s])];
+ score -= Unsupported;
if (connected)
score += Connected[opposed][!!phalanx][more_than_one(supported)][relative_rank(Us, s)];
@@ -183,8 +195,8 @@ namespace Pawns {
/// hard-coded tables, when makes sense, we prefer to calculate them with a formula
/// to reduce independent parameters and to allow easier tuning and better insight.
-void init()
-{
+void init() {
+
static const int Seed[RANK_NB] = { 0, 8, 19, 13, 71, 94, 169, 324 };
for (int opposed = 0; opposed <= 1; ++opposed)
@@ -194,7 +206,7 @@ void init()
{
int v = (Seed[r] + (phalanx ? (Seed[r + 1] - Seed[r]) / 2 : 0)) >> opposed;
v += (apex ? v / 2 : 0);
- Connected[opposed][phalanx][apex][r] = make_score(v, v * 5 / 8);
+ Connected[opposed][phalanx][apex][r] = make_score(v, v * (r-2) / 4);
}
}
@@ -215,19 +227,20 @@ Entry* probe(const Position& pos) {
e->key = key;
e->score = evaluate(pos, e) - evaluate(pos, e);
e->asymmetry = popcount(e->semiopenFiles[WHITE] ^ e->semiopenFiles[BLACK]);
+ e->openFiles = popcount(e->semiopenFiles[WHITE] & e->semiopenFiles[BLACK]);
return e;
}
/// Entry::shelter_storm() calculates shelter and storm penalties for the file
-/// the king is on, as well as the two adjacent files.
+/// the king is on, as well as the two closest files.
template
Value Entry::shelter_storm(const Position& pos, Square ksq) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
- enum { NoFriendlyPawn, Unblocked, BlockedByPawn, BlockedByKing };
+ enum { BlockedByKing, Unopposed, BlockedByPawn, Unblocked };
Bitboard b = pos.pieces(PAWN) & (in_front_bb(Us, rank_of(ksq)) | rank_bb(ksq));
Bitboard ourPawns = b & pos.pieces(Us);
@@ -243,12 +256,13 @@ Value Entry::shelter_storm(const Position& pos, Square ksq) {
b = theirPawns & file_bb(f);
Rank rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1;
- safety -= ShelterWeakness[std::min(f, FILE_H - f)][rkUs]
+ int d = std::min(f, FILE_H - f);
+ safety -= ShelterWeakness[d][rkUs]
+ StormDanger
[f == file_of(ksq) && rkThem == relative_rank(Us, ksq) + 1 ? BlockedByKing :
- rkUs == RANK_1 ? NoFriendlyPawn :
+ rkUs == RANK_1 ? Unopposed :
rkThem == rkUs + 1 ? BlockedByPawn : Unblocked]
- [std::min(f, FILE_H - f)][rkThem];
+ [d][rkThem];
}
return safety;
diff --git a/Engines/Windows/deepfish/srcD/pawns.h b/Engines/Windows/mcbrain/src/pawns.h
similarity index 95%
rename from Engines/Windows/deepfish/srcD/pawns.h
rename to Engines/Windows/mcbrain/src/pawns.h
index 24843e3..15b0b77 100644
--- a/Engines/Windows/deepfish/srcD/pawns.h
+++ b/Engines/Windows/mcbrain/src/pawns.h
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -38,6 +38,7 @@ struct Entry {
Bitboard passed_pawns(Color c) const { return passedPawns[c]; }
Bitboard pawn_attacks_span(Color c) const { return pawnAttacksSpan[c]; }
int pawn_asymmetry() const { return asymmetry; }
+ int open_files() const { return openFiles; }
int semiopen_file(Color c, File f) const {
return semiopenFiles[c] & (1 << f);
@@ -74,6 +75,7 @@ struct Entry {
int semiopenFiles[COLOR_NB];
int pawnsOnSquares[COLOR_NB][COLOR_NB]; // [color][light/dark squares]
int asymmetry;
+ int openFiles;
};
typedef HashTable Table;
diff --git a/Engines/Windows/deepfish/srcD/position.cpp b/Engines/Windows/mcbrain/src/position.cpp
similarity index 75%
rename from Engines/Windows/deepfish/srcD/position.cpp
rename to Engines/Windows/mcbrain/src/position.cpp
index bc8e92a..ceed0f1 100644
--- a/Engines/Windows/deepfish/srcD/position.cpp
+++ b/Engines/Windows/mcbrain/src/position.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,7 +20,8 @@
#include
#include
-#include // For std::memset, std::memcmp
+#include // For offsetof()
+#include // For std::memset, std::memcmp
#include
#include
@@ -31,25 +32,27 @@
#include "thread.h"
#include "tt.h"
#include "uci.h"
+#include "tbprobe.h"
using std::string;
+namespace PSQT {
+ extern Score psq[PIECE_NB][SQUARE_NB];
+}
+
namespace Zobrist {
- Key psq[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+ Key psq[PIECE_NB][SQUARE_NB];
Key enpassant[FILE_NB];
Key castling[CASTLING_RIGHT_NB];
- Key side;
- Key exclusion;
+ Key side, noPawns;
}
-Key Position::exclusion_key() const { return st->key ^ Zobrist::exclusion; }
-
namespace {
const string PieceToChar(" PNBRQK pnbrqk");
-// min_attacker() is a helper function used by see() to locate the least
+// min_attacker() is a helper function used by see_ge() to locate the least
// valuable attacker for the side to move, remove the attacker we just found
// from the bitboards and scan for new X-ray attacks behind it.
@@ -96,11 +99,25 @@ std::ostream& operator<<(std::ostream& os, const Position& pos) {
}
os << "\nFen: " << pos.fen() << "\nKey: " << std::hex << std::uppercase
- << std::setfill('0') << std::setw(16) << pos.key() << std::dec << "\nCheckers: ";
+ << std::setfill('0') << std::setw(16) << pos.key()
+ << std::setfill(' ') << std::dec << "\nCheckers: ";
for (Bitboard b = pos.checkers(); b; )
os << UCI::square(pop_lsb(&b)) << " ";
+ if ( int(Tablebases::MaxCardinality) >= popcount(pos.pieces())
+ && !pos.can_castle(ANY_CASTLING))
+ {
+ StateInfo st;
+ Position p;
+ p.set(pos.fen(), pos.is_chess960(), &st, pos.this_thread());
+ Tablebases::ProbeState s1, s2;
+ Tablebases::WDLScore wdl = Tablebases::probe_wdl(p, &s1);
+ int dtz = Tablebases::probe_dtz(p, &s2);
+ os << "\nTablebases WDL: " << std::setw(4) << wdl << " (" << s1 << ")"
+ << "\nTablebases DTZ: " << std::setw(4) << dtz << " (" << s2 << ")";
+ }
+
return os;
}
@@ -112,10 +129,9 @@ void Position::init() {
PRNG rng(1070372);
- for (Color c = WHITE; c <= BLACK; ++c)
- for (PieceType pt = PAWN; pt <= KING; ++pt)
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
- Zobrist::psq[c][pt][s] = rng.rand();
+ for (Piece pc : Pieces)
+ for (Square s = SQ_A1; s <= SQ_H8; ++s)
+ Zobrist::psq[pc][s] = rng.rand();
for (File f = FILE_A; f <= FILE_H; ++f)
Zobrist::enpassant[f] = rng.rand();
@@ -132,7 +148,7 @@ void Position::init() {
}
Zobrist::side = rng.rand