diff --git a/Code/Analisis.py b/Code/Analisis.py
index 685e4cf..ebe914d 100644
--- a/Code/Analisis.py
+++ b/Code/Analisis.py
@@ -595,7 +595,8 @@ def siElegido(self, posRM):
def ponPosRMactual(self, posRM):
self.posRMactual = posRM
self.rm = self.listaRM[self.posRMactual][0]
- self.partida = Partida.Partida(self.jg.posicionBase).leerPV(self.rm.pv)
+ self.partida = Partida.Partida(self.jg.posicionBase)
+ self.partida.leerPV(self.rm.pv)
self.partida.siTerminada()
self.posMovActual = 0
@@ -817,7 +818,8 @@ def analizaJugada(self, jgNueva):
self.rm = self.xtutor.analizaVariante(jgNueva, secs * 1000, self.siBlancas)
me.final()
- self.partidaTutor = Partida.Partida(jgNueva.posicion).leerPV(self.rm.pv)
+ self.partidaTutor = Partida.Partida(jgNueva.posicion)
+ self.partidaTutor.leerPV(self.rm.pv)
if len(self.partidaTutor):
self.w.tableroT.ponPosicion(self.partidaTutor.jugada(0).posicion)
diff --git a/Code/AnalisisIndexes.py b/Code/AnalisisIndexes.py
index 5324a22..05590f8 100644
--- a/Code/AnalisisIndexes.py
+++ b/Code/AnalisisIndexes.py
@@ -1,4 +1,4 @@
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import VarGen
from Code import Partida
diff --git a/Code/AperturasStd.py b/Code/AperturasStd.py
index b54665e..9dd6056 100644
--- a/Code/AperturasStd.py
+++ b/Code/AperturasStd.py
@@ -1,3 +1,5 @@
+import LCEngineV1 as LCEngine
+
from operator import attrgetter
from Code import TrListas
@@ -34,6 +36,7 @@ def __str__(self):
class ListaAperturasStd:
def __init__(self):
self.dic = None
+ self.dicFenM2 = None
self.hijos = None
self.lia1h8 = None
@@ -49,6 +52,14 @@ def reset(self, configuracion, siBasic, siEntrenar):
bl.trOrdena = ("A" if bl.siBasic else "B") + bl.trNombre.upper()
self.hijos = self.ordena(self.hijos, 0)
+ dfen = {}
+ makePV = LCEngine.makePV
+ fen2fenM2 = LCEngine.fen2fenM2
+ for pv, ap in self.dic.iteritems():
+ fen = makePV(pv)
+ dfen[fen2fenM2(fen)] = ap
+ self.dicFenM2 = dfen
+
def ordena(self, hijos, n):
if hijos:
hijos = sorted(hijos, key=attrgetter("trOrdena"))
@@ -132,6 +143,16 @@ def lee(self, ficheroPers, siEntrenar):
if n <= 0:
self.hijos.append(bloque)
+ def asignaTransposition(self, partida):
+ partida.transposition = None
+ if not (partida.apertura is None or partida.pendienteApertura):
+ for nj, jg in enumerate(partida.liJugadas):
+ if not jg.siApertura:
+ fenm2 = jg.posicion.fenM2()
+ if fenm2 in self.dicFenM2:
+ partida.transposition = self.dicFenM2[fenm2]
+ partida.jg_transposition = jg
+
def asignaApertura(self, partida):
partida.apertura = None
if not partida.siFenInicial():
diff --git a/Code/CajonDesastre.py b/Code/CajonDesastre.py
index 5c21041..a83b37b 100644
--- a/Code/CajonDesastre.py
+++ b/Code/CajonDesastre.py
@@ -4,7 +4,7 @@
import shutil
import sqlite3
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import BaseConfig
from Code import Util
diff --git a/Code/Constantes.py b/Code/Constantes.py
index ab6eab1..adc4f39 100644
--- a/Code/Constantes.py
+++ b/Code/Constantes.py
@@ -2,27 +2,34 @@
kSigueApertura, kSigueUsuario, kMalApertura = range(3)
-kJugNueva, kJugEntPos, kJugPGN, kJugEntMaq, kJugGM, kJugRemoto, kJugSolo, kJug60, kJugElo, kJugMicElo, \
-kJugBooks, kJugAperturas, kJugBoxing, kJugEntTac, kJugMvM, kJugAlbum, kJugFics, kJugFide, kJugLichess, \
-kJugWorldMap, kJugRoute, kJugEntLight, kJugWashingCreate, kJugWashingTactics, kJugWashingReplay, kJugSingularMoves\
- = range(26)
+(
+ kJugNueva, kJugEntPos, kJugPGN, kJugEntMaq, kJugGM, kJugRemoto, kJugSolo, kJug60, kJugElo, kJugMicElo,
+ kJugBooks, kJugAperturas, kJugOpeningLines, kJugBoxing, kJugEntTac, kJugMvM, kJugAlbum, kJugFics, kJugFide,
+ kJugLichess, kJugWorldMap, kJugRoute, kJugEntLight, kJugWashingCreate, kJugWashingTactics, kJugWashingReplay,
+ kJugSingularMoves
+) = range(27)
kFinNormal, kFinReinicio = range(2)
-kGanamos, kGanaRival, kTablas, kTablasRepeticion, kTablas50, kTablasFaltaMaterial, kGanamosTiempo, kGanaRivalTiempo, kTablasAcuerdo, kDesconocido = range(10)
+(
+ kGanamos, kGanaRival, kTablas, kTablasRepeticion, kTablas50, kTablasFaltaMaterial, kGanamosTiempo,
+ kGanaRivalTiempo, kTablasAcuerdo, kDesconocido
+) = range(10)
kMoverAdelante, kMoverAtras, kMoverInicio, kMoverFinal, kMoverLibre, kMoverReloj = range(6)
-k_terminar, k_play, k_mainmenu, k_competicion, k_competir, k_entrenamiento, k_opciones, \
-k_informacion, k_grabar, k_grabarComo, k_file, k_recuperar, k_abandonar, k_reiniciar, k_atras, \
-k_aplazar, k_finpartida, k_ent_empezar, k_ent_otro, k_pgnFin, k_pgnPaste, \
-k_pgnFichero, k_pgnInformacion, k_pgnFicheroRepite, k_pgnNuestroFichero, k_jugadadia, k_pgnComandoExterno, \
-k_rendirse, k_tablas, k_libros, \
-k_peliculaTerminar, k_peliculaLento, k_peliculaPausa, k_peliculaSeguir, k_peliculaRapido, k_peliculaRepetir, \
-k_peliculaPGN, k_jugar, k_anterior, k_siguiente, k_trasteros, \
-k_ayuda, k_mateNivel, k_ayudaMover, \
-k_aceptar, k_cancelar, \
-k_configurar, k_utilidades, k_variantes, k_tools, k_elo, k_cambiar, k_libre, k_showtext, k_enviar = range(55)
+(
+ k_terminar, k_play, k_mainmenu, k_competicion, k_competir, k_entrenamiento, k_opciones,
+ k_informacion, k_grabar, k_grabarComo, k_file, k_recuperar, k_abandonar, k_reiniciar, k_atras,
+ k_aplazar, k_finpartida, k_ent_empezar, k_ent_otro, k_pgnFin, k_pgnPaste,
+ k_pgnFichero, k_pgnInformacion, k_pgnFicheroRepite, k_pgnNuestroFichero, k_jugadadia, k_pgnComandoExterno,
+ k_rendirse, k_tablas, k_libros,
+ k_peliculaTerminar, k_peliculaLento, k_peliculaPausa, k_peliculaSeguir, k_peliculaRapido, k_peliculaRepetir,
+ k_peliculaPGN, k_jugar, k_anterior, k_siguiente, k_trasteros,
+ k_ayuda, k_mateNivel, k_ayudaMover,
+ k_aceptar, k_cancelar,
+ k_configurar, k_utilidades, k_variantes, k_tools, k_elo, k_cambiar, k_libre, k_showtext, k_enviar
+) = range(55)
kMP_1, kMP_2, kMP_3, kMP_4, kMP_5, kMP_6, kMP_7 = range(7)
@@ -30,9 +37,11 @@
kTutorH, kTutorH2_1, kTutorH1_2, kTutorV = range(4)
-kAjustarMejor, kAjustarSuperior, kAjustarSimilar, kAjustarInferior, kAjustarPeor, kAjustarPlayer, \
-kAjustarNivelAlto, kAjustarNivelMedio, kAjustarNivelBajo, kAjustarSuperiorM, kAjustarSuperiorMM, \
-kAjustarInferiorM, kAjustarInferiorMM = range(13)
+(
+ kAjustarMejor, kAjustarSuperior, kAjustarSimilar, kAjustarInferior, kAjustarPeor, kAjustarPlayer,
+ kAjustarNivelAlto, kAjustarNivelMedio, kAjustarNivelBajo, kAjustarSuperiorM, kAjustarSuperiorMM,
+ kAjustarInferiorM, kAjustarInferiorMM
+) = range(13)
kControlTableroNo, kControlTableroGeneral, kControlTableroParticular = range(3)
diff --git a/Code/ControlPosicion.py b/Code/ControlPosicion.py
index 26524f3..42eb2aa 100644
--- a/Code/ControlPosicion.py
+++ b/Code/ControlPosicion.py
@@ -1,4 +1,4 @@
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import TrListas
@@ -434,3 +434,6 @@ def siPeonCoronando(self, desdeA1H8, hastaA1H8):
return False
return True
+
+def distancia(desde, hasta):
+ return ((ord(desde[0])-ord(hasta[0]))**2 + (ord(desde[1])-ord(hasta[1]))**2)**0.5
diff --git a/Code/DBgames.py b/Code/DBgames.py
index f0c3acc..8ee44cc 100644
--- a/Code/DBgames.py
+++ b/Code/DBgames.py
@@ -4,7 +4,7 @@
import time
import random
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import ControlPosicion
from Code import Partida
@@ -524,8 +524,9 @@ def getSummary(self, pvBase, dicAnalisis, siFigurinesPGN, allmoves=True):
class DBgames:
- def __init__(self, nomFichero):
+ def __init__(self, nomFichero, with_dbSTAT=True):
self.nomFichero = Util.dirRelativo(nomFichero)
+ self.with_dbSTAT = with_dbSTAT
self.liCamposBase = ["EVENT", "SITE", "DATE", "WHITE", "BLACK", "RESULT", "ECO", "WHITEELO", "BLACKELO", "PLIES"]
self.liCamposWork = ["XPV", ]
self.liCamposBLOB = ["PGN", ]
@@ -556,7 +557,10 @@ def __init__(self, nomFichero):
self.liOrden = []
- self.dbSTAT = TreeSTAT(self.nomFichero + "_s1")
+ if self.with_dbSTAT:
+ self.dbSTAT = TreeSTAT(self.nomFichero + "_s1")
+ else:
+ self.dbSTAT = None
self.liRowids = []
@@ -759,10 +763,12 @@ def borrarLista(self, lista):
for recno in lista:
pv = self.damePV(recno)
result = self.field(recno, "RESULT")
- self.dbSTAT.append(pv, result, -1)
+ if self.with_dbSTAT:
+ self.dbSTAT.append(pv, result, -1)
self._cursor.execute(cSQL,(self.liRowids[recno],))
del self.liRowids[recno]
- self.dbSTAT.commit()
+ if self.with_dbSTAT:
+ self.dbSTAT.commit()
self._conexion.commit()
def getSummary(self, pvBase, dicAnalisis, siFigurinesPGN, allmoves=True):
@@ -803,7 +809,8 @@ def leerPGNs(self, ficheros, dlTmp):
t1 = time.time()-0.7 # para que empiece enseguida
- self.dbSTAT.massive_append_set(True)
+ if self.with_dbSTAT:
+ self.dbSTAT.massive_append_set(True)
def write_logs(fich, pgn):
with open(fich, "ab") as ferr:
@@ -880,7 +887,8 @@ def write_logs(fich, pgn):
pgn = Util.var2blob(pgn)
reg = (xpv, event, site, date, white, black, result, eco, whiteelo, blackelo, pgn, plies)
- self.dbSTAT.append_fen(pv, result, liFens)
+ if self.with_dbSTAT:
+ self.dbSTAT.append_fen(pv, result, liFens)
liRegs.append(reg)
nRegs += 1
importados += 1
@@ -890,9 +898,10 @@ def write_logs(fich, pgn):
liRegs = []
stRegs = set()
conexion.commit()
- self.dbSTAT.massive_append_set(False)
- self.dbSTAT.commit()
- self.dbSTAT.massive_append_set(True)
+ if self.with_dbSTAT:
+ self.dbSTAT.massive_append_set(False)
+ self.dbSTAT.commit()
+ self.dbSTAT.massive_append_set(True)
if n == next_n:
if time.time()-t1> 0.8:
if not dlTmp.actualiza(erroneos+duplicados+importados, erroneos, duplicados, importados):
@@ -906,15 +915,17 @@ def write_logs(fich, pgn):
dlTmp.actualiza(erroneos+duplicados+importados, erroneos, duplicados, importados)
dlTmp.ponSaving()
- self.dbSTAT.massive_append_set(False)
- self.dbSTAT.commit()
+ if self.with_dbSTAT:
+ self.dbSTAT.massive_append_set(False)
+ self.dbSTAT.commit()
conexion.commit()
dlTmp.ponContinuar()
def appendDB(self, db, liRecnos, dlTmp):
duplicados = importados = 0
- self.dbSTAT.massive_append_set(True)
+ if self.with_dbSTAT:
+ self.dbSTAT.massive_append_set(True)
t1 = time.time() - 0.7 # para que empiece enseguida
@@ -941,7 +952,8 @@ def appendDB(self, db, liRecnos, dlTmp):
pv = xpv2pv(xpv)
reg = (xpv, raw["EVENT"], raw["SITE"], raw["DATE"], raw["WHITE"], raw["BLACK"], raw["RESULT"], raw["ECO"], raw["WHITEELO"],
raw["BLACKELO"], raw["PGN"], raw["PLIES"])
- self.dbSTAT.append(pv, raw["RESULT"])
+ if self.with_dbSTAT:
+ self.dbSTAT.append(pv, raw["RESULT"])
liRegs.append(reg)
nRegs += 1
importados += 1
@@ -949,9 +961,10 @@ def appendDB(self, db, liRecnos, dlTmp):
cursor.executemany(sql, liRegs)
liRegs = []
conexion.commit()
- self.dbSTAT.massive_append_set(False)
- self.dbSTAT.commit()
- self.dbSTAT.massive_append_set(True)
+ if self.with_dbSTAT:
+ self.dbSTAT.massive_append_set(False)
+ self.dbSTAT.commit()
+ self.dbSTAT.massive_append_set(True)
if pos == next_n:
if time.time() - t1 > 0.8:
@@ -967,8 +980,9 @@ def appendDB(self, db, liRecnos, dlTmp):
dlTmp.actualiza(duplicados + importados, duplicados, importados)
dlTmp.ponSaving()
- self.dbSTAT.massive_append_set(False)
- self.dbSTAT.commit()
+ if self.with_dbSTAT:
+ self.dbSTAT.massive_append_set(False)
+ self.dbSTAT.commit()
conexion.commit()
dlTmp.ponContinuar()
@@ -1022,7 +1036,7 @@ def leePartidaRaw(self, raw):
litags.extend(rtags)
p.setTags(litags)
- p.asignaApertura(VarGen.configuracion)
+ p.asignaApertura()
return p
def leePGNRecno(self, recno):
@@ -1102,9 +1116,10 @@ def modifica(self, recno, partidaCompleta):
self._conexion.commit()
pvAnt = xpv2pv(reg_ant["XPV"])
resNue = dTags.get("RESULT", "*")
- self.dbSTAT.append(pvAnt, resAnt, -1)
- self.dbSTAT.append(pvNue, resNue, +1)
- self.dbSTAT.commit()
+ if self.with_dbSTAT:
+ self.dbSTAT.append(pvAnt, resAnt, -1)
+ self.dbSTAT.append(pvNue, resNue, +1)
+ self.dbSTAT.commit()
del self.cache[rowid]
@@ -1136,8 +1151,9 @@ def inserta(self, partidaCompleta):
sql = "insert into games (XPV,EVENT,SITE,DATE,WHITE,BLACK,RESULT,ECO,WHITEELO,BLACKELO,PLIES,PGN) values (?,?,?,?,?,?,?,?,?,?,?,?);"
self._cursor.execute(sql, data)
self._conexion.commit()
- self.dbSTAT.append(pv, dTags.get("RESULT", "*"), +1)
- self.dbSTAT.commit()
+ if self.with_dbSTAT:
+ self.dbSTAT.append(pv, dTags.get("RESULT", "*"), +1)
+ self.dbSTAT.commit()
self.liRowids.append(self._cursor.lastrowid)
diff --git a/Code/DBgamesFEN.py b/Code/DBgamesFEN.py
index bdd021e..e6b29ff 100644
--- a/Code/DBgamesFEN.py
+++ b/Code/DBgamesFEN.py
@@ -4,7 +4,7 @@
import time
import random
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import Partida
from Code import Util
diff --git a/Code/EngineThread.py b/Code/EngineThread.py
index 16d012f..f8ef893 100644
--- a/Code/EngineThread.py
+++ b/Code/EngineThread.py
@@ -10,7 +10,6 @@
DEBUG_ENGINE = False
-
def xpr(line):
if DEBUG_ENGINE:
t = time.time()
@@ -130,6 +129,10 @@ def start(self):
startupinfo = None
curdir = os.path.abspath(os.curdir) # problem with "." as curdir
os.chdir(self.direxe) # to fix problems with non ascii folders
+ if VarGen.isLinux:
+ argv0 = self.args[0]
+ if "/" not in argv0:
+ self.args[0] = os.path.join(self.direxe, argv0)
self.process = subprocess.Popen(self.args, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
startupinfo=startupinfo, shell=False)
os.chdir(curdir)
diff --git a/Code/EnginesLinux32.py b/Code/EnginesLinux32.py
index 3e91a81..c1c89b9 100644
--- a/Code/EnginesLinux32.py
+++ b/Code/EnginesLinux32.py
@@ -151,10 +151,10 @@ def mas(cm):
cm.ordenUCI("Hash", "64")
mas(cm)
- cm = ConfigMotor("mcbrain", "Michael Byrne (based on stockfish)", "4.0", "https://github.com/MichaelB7/Stockfish/releases")
- cm.path = "SF-McBrain-v40_x32_linux"
+ cm = ConfigMotor("mcbrain", "Michael Byrne", "9", "https://github.com/MichaelB7/Stockfish/releases")
+ cm.path = "McBrain-9_x32_linux"
cm.elo = 3200
- cm.ordenUCI("Tactical", "3")
+ cm.ordenUCI("Contempt", "0")
cm.ordenUCI("Hash", "64")
cm.ponMultiPV(20, 500)
mas(cm)
diff --git a/Code/EnginesLinux64.py b/Code/EnginesLinux64.py
index 924cd69..c4d6e83 100644
--- a/Code/EnginesLinux64.py
+++ b/Code/EnginesLinux64.py
@@ -48,8 +48,8 @@ def mas(cm):
cm.ponMultiPV(20, 218)
mas(cm)
- cm = ConfigMotor("stockfish", "Tord Romstad, Marco Costalba, Joona Kiiski", "8", "http://stockfishchess.org/")
- cm.path = "Linux/stockfish_8_x64"
+ cm = ConfigMotor("stockfish", "Tord Romstad, Marco Costalba, Joona Kiiski", "9", "http://stockfishchess.org/")
+ cm.path = "Linux/stockfish-9-64"
cm.elo = 3300
cm.ordenUCI("Ponder", "false")
cm.ordenUCI("Hash", "64")
@@ -138,10 +138,10 @@ def mas(cm):
cm.ordenUCI("Hash", "64")
mas(cm)
- cm = ConfigMotor("mcbrain", "Michael Byrne (based on stockfish)", "4.0", "https://github.com/MichaelB7/Stockfish/releases")
- cm.path = "SSF-McBrain-v40_x64_linux"
+ cm = ConfigMotor("mcbrain", "Michael Byrne", "9", "https://github.com/MichaelB7/Stockfish/releases")
+ cm.path = "McBrain-9_x64_linux"
cm.elo = 3200
- cm.ordenUCI("Tactical", "3")
+ cm.ordenUCI("Contempt", "0")
cm.ordenUCI("Hash", "64")
cm.ponMultiPV(20, 500)
mas(cm)
diff --git a/Code/EnginesWindows.py b/Code/EnginesWindows.py
index 56b0a14..c8a0778 100644
--- a/Code/EnginesWindows.py
+++ b/Code/EnginesWindows.py
@@ -208,9 +208,9 @@ def mas(cm):
cm.ponMultiPV(20, 256)
mas(cm)
- cm = ConfigMotor("stockfish", "Tord Romstad, Marco Costalba, Joona Kiiski", "8 32bits", "http://stockfishchess.org/")
- cm.path = "Windows/stockfish_8_x32.exe"
- cm.path_64 = "Windows/stockfish_8_x64_bmi2.exe", "8 64bits bmi2"
+ cm = ConfigMotor("stockfish", "Tord Romstad, Marco Costalba, Joona Kiiski", "9 32bits", "http://stockfishchess.org/")
+ cm.path = "Windows/stockfish_9_x32.exe"
+ cm.path_64 = "Windows/stockfish_9_x64_bmi2.exe", "9 64bits bmi2"
cm.elo = 3300
cm.ordenUCI("Ponder", "false")
cm.ordenUCI("Hash", "64")
@@ -218,11 +218,11 @@ def mas(cm):
cm.ponMultiPV(20, 500)
mas(cm)
- cm = ConfigMotor("mcbrain", "Michael Byrne (based on stockfish)", "4.0 32bit", "https://github.com/MichaelB7/Stockfish/releases")
- cm.path = "SF-McBrain-v40_x32_old.exe"
- cm.path_64 = "SF-McBrain-v40_x64_bmi2.exe", "4.0 64bit bmi2"
+ cm = ConfigMotor("mcbrain", "Michael Byrne", "9 32bit", "https://github.com/MichaelB7/Stockfish/releases")
+ cm.path = "McBrain-9_x32_old.exe"
+ cm.path_64 = "McBrain-9_x64_bmi2.exe", "9 64bit bmi2"
cm.elo = 3200
- cm.ordenUCI("Tactical", "3")
+ cm.ordenUCI("Contempt", "0")
cm.ordenUCI("Hash", "64")
cm.ponMultiPV(20, 500)
mas(cm)
diff --git a/Code/Entrenamientos.py b/Code/Entrenamientos.py
index 722862b..d20911b 100644
--- a/Code/Entrenamientos.py
+++ b/Code/Entrenamientos.py
@@ -261,14 +261,18 @@ def menuTacticas(submenu, tipo, carpetaBase, lista):
menu1.separador()
menu2 = menu1.submenu(_("Turn on the lights"), Iconos.TOL())
menu3 = menu2.submenu(_("Memory mode"), Iconos.TOL())
- xopcion(menu3, "tol_uned", _("UNED chess school"), Iconos.Uned())
+ xopcion(menu3, "tol_uned_easy", "%s (%s)" % (_("UNED chess school"), _("Initial")), Iconos.Uned())
+ menu3.separador()
+ xopcion(menu3, "tol_uned", "%s (%s)" % (_("UNED chess school"), _("Complete")), Iconos.Uned())
menu3.separador()
xopcion(menu3, "tol_uwe_easy", "%s (%s)" % (_("Uwe Auerswald"), _("Initial")), Iconos.Uwe())
menu3.separador()
xopcion(menu3, "tol_uwe", "%s (%s)" % (_("Uwe Auerswald"), _("Complete")), Iconos.Uwe())
menu2.separador()
menu3 = menu2.submenu(_("Calculation mode"), Iconos.Calculo())
- xopcion(menu3, "tol_uned_calc", _("UNED chess school"), Iconos.Uned())
+ xopcion(menu3, "tol_uned_easy_calc", "%s (%s)" % (_("UNED chess school"), _("Initial")), Iconos.Uned())
+ menu3.separador()
+ xopcion(menu3, "tol_uned_calc", "%s (%s)" % (_("UNED chess school"), _("Complete")), Iconos.Uned())
menu3.separador()
xopcion(menu3, "tol_uwe_easy_calc", "%s (%s)" % (_("Uwe Auerswald"), _("Initial")), Iconos.Uwe())
menu3.separador()
@@ -290,8 +294,8 @@ def menuTacticas(submenu, tipo, carpetaBase, lista):
txt = cat.nombre()
nm = mem.nivel(x)
- if nm > -1:
- txt += " %s %d" % (_("Level"), nm + 1)
+ if nm >= 0:
+ txt += " %s %d" % (_("Level"), nm+1)
xopcion(menu2, -100 - x, txt, cat.icono(), siDeshabilitado=not mem.siActiva(x))
@@ -667,7 +671,12 @@ def everest(self):
PantallaEverest.everest(self.procesador)
def turn_on_lights(self, name):
- if name.startswith("uned"):
+ if name.startswith("uned_easy"):
+ title = "%s (%s)" % (_("UNED chess school"), _("Initial"))
+ folder = "Trainings/Tactics by UNED chess school"
+ icono = Iconos.Uned()
+ li_tam_blocks = (4, 6, 9, 12, 18, 36)
+ elif name.startswith("uned"):
title = _("UNED chess school")
folder = "Trainings/Tactics by UNED chess school"
icono = Iconos.Uned()
diff --git a/Code/Everest.py b/Code/Everest.py
index f34f0ff..3bc652d 100644
--- a/Code/Everest.py
+++ b/Code/Everest.py
@@ -1,4 +1,4 @@
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import Partida
from Code.SQL import Base
diff --git a/Code/GM.py b/Code/GM.py
index e2ba76c..853265a 100644
--- a/Code/GM.py
+++ b/Code/GM.py
@@ -1,7 +1,7 @@
import operator
import os
-from LCEngine import xpv2pv, pv2xpv
+from LCEngineV1 import xpv2pv, pv2xpv
from Code import Jugada
from Code import Util
diff --git a/Code/Gestor.py b/Code/Gestor.py
index edc5501..5009532 100644
--- a/Code/Gestor.py
+++ b/Code/Gestor.py
@@ -3,7 +3,7 @@
import random
import time
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import Analisis
from Code import AnalisisIndexes
@@ -977,9 +977,13 @@ def borrar(self):
li_del.append((_("Comments") + ":", False))
li_del.append(separador)
li_del.append((_("Analysis") + ":", False))
+ li_del.append(separador)
+ li_del.append((_("All") + ":", False))
resultado = FormLayout.fedit(li_del, title=_("Remove"), parent=self.pantalla, icon=Iconos.Delete())
if resultado:
- variants, ratings, comments, analysis = resultado[1]
+ variants, ratings, comments, analysis, all = resultado[1]
+ if all:
+ variants, ratings, comments, analysis = True, True, True, True
for jg in self.partida.liJugadas:
if variants:
jg.variantes = ""
@@ -1500,6 +1504,7 @@ def showAnalisis(self):
elos = self.partida.calc_elos(self.configuracion)
alm = Histogram.genHistograms(self.partida, self.configuracion.centipawns)
alm.indexesHTML, alm.indexesRAW, alm.eloW, alm.eloB, alm.eloT = AnalisisIndexes.genIndexes(self.partida, elos, alm)
+ alm.siBlancasAbajo = self.tablero.siBlancasAbajo
um.final()
PantallaAnalisis.showGraph(self.pantalla, self, alm, Analisis.muestraAnalisis)
diff --git a/Code/Gestor60.py b/Code/Gestor60.py
index 0b62c8c..92987b2 100644
--- a/Code/Gestor60.py
+++ b/Code/Gestor60.py
@@ -2,7 +2,7 @@
import random
import time
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import ControlPosicion
from Code import Gestor
diff --git a/Code/GestorAlbum.py b/Code/GestorAlbum.py
index b0e0af9..b3ed1c1 100644
--- a/Code/GestorAlbum.py
+++ b/Code/GestorAlbum.py
@@ -36,7 +36,7 @@ def inicio(self, album, cromo, aplazamiento=None):
# -Aplazamiento 1/2--------------------------------------------------
if aplazamiento:
self.partida.recuperaDeTexto(aplazamiento["JUGADAS"])
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.xrival = Albums.GestorMotorAlbum(self, self.cromo)
self.pantalla.ponToolBar((k_rendirse, k_aplazar, k_configurar, k_utilidades))
@@ -196,7 +196,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
diff --git a/Code/GestorAperturas.py b/Code/GestorAperturas.py
index 45462c2..3958f8d 100644
--- a/Code/GestorAperturas.py
+++ b/Code/GestorAperturas.py
@@ -218,7 +218,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponFlechaSC(jg.desde, jg.hasta)
self.beepExtendido(siNuestra)
diff --git a/Code/GestorBooks.py b/Code/GestorBooks.py
index fa4df2f..77edaa9 100644
--- a/Code/GestorBooks.py
+++ b/Code/GestorBooks.py
@@ -280,7 +280,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponFlechaSC(jg.desde, jg.hasta)
self.beepExtendido(siNuestra)
diff --git a/Code/GestorCompeticion.py b/Code/GestorCompeticion.py
index 4651eb5..5c3a09c 100644
--- a/Code/GestorCompeticion.py
+++ b/Code/GestorCompeticion.py
@@ -185,7 +185,7 @@ def atras(self):
self.ponAyudas(self.ayudas)
self.partida.anulaUltimoMovimiento(self.siJugamosConBlancas)
self.siApertura = False
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponteAlFinal()
self.siAnalizadoTutor = False
self.refresh()
@@ -322,7 +322,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
diff --git a/Code/GestorElo.py b/Code/GestorElo.py
index 74815e3..a0d4712 100644
--- a/Code/GestorElo.py
+++ b/Code/GestorElo.py
@@ -529,7 +529,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
@@ -692,7 +692,7 @@ def determinaColor(self, datosMotor):
def atras(self):
if self.partida.numJugadas() > 2:
self.partida.anulaUltimoMovimiento(self.siJugamosConBlancas)
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponteAlFinal()
self.refresh()
self.siguienteJugada()
diff --git a/Code/GestorEntMaq.py b/Code/GestorEntMaq.py
index ade5792..2602bb7 100644
--- a/Code/GestorEntMaq.py
+++ b/Code/GestorEntMaq.py
@@ -1,4 +1,4 @@
-import LCEngine
+import LCEngineV1 as LCEngine
from PyQt4 import QtCore
from Code import Analisis
@@ -475,7 +475,7 @@ def atras(self):
self.ponAyudasEM()
self.partida.anulaUltimoMovimiento(self.siJugamosConBlancas)
if not self.fen:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponteAlFinal()
self.reOpenBook()
self.refresh()
@@ -883,7 +883,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
diff --git a/Code/GestorEverest.py b/Code/GestorEverest.py
index bcee87f..989288b 100644
--- a/Code/GestorEverest.py
+++ b/Code/GestorEverest.py
@@ -246,6 +246,13 @@ def mueveHumano(self, desde, hasta, coronacion=""):
um.final()
rmUsu, posUsu = mrm.buscaRM(jgUsu.movimiento())
+ if rmUsu is None:
+ um = QTUtil2.analizando(self.pantalla)
+ self.analizaFinal()
+ rmUsu = self.xanalyzer.valora(posicion, desde, hasta, coronacion)
+ mrm.agregaRM(rmUsu)
+ self.analizaInicio()
+ um.final()
w = PantallaJuicio.WJuicio(self, self.xanalyzer, self.nombreObj, posicion, mrm, rmObj, rmUsu, analisis,
siCompetitivo=False)
@@ -286,7 +293,7 @@ def masJugada(self, siNuestra, analisis=None, comentario=None):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.movimientosPiezas(jg.liMovs, True)
self.tablero.ponPosicion(jg.posicion)
self.ponFlechaSC(jg.desde, jg.hasta)
diff --git a/Code/GestorFideFics.py b/Code/GestorFideFics.py
index 103a09b..ee7ef5a 100644
--- a/Code/GestorFideFics.py
+++ b/Code/GestorFideFics.py
@@ -3,7 +3,7 @@
import datetime
import random
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import Apertura
from Code import Gestor
@@ -414,7 +414,7 @@ def masJugada(self, siNuestra, comentario=None, analisis=None):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.movimientosPiezas(jg.liMovs, True)
self.tablero.ponPosicion(jg.posicion)
self.ponFlechaSC(jg.desde, jg.hasta)
@@ -506,7 +506,7 @@ def atras(self):
if self.partida.numJugadas() > 2:
self.analizaFinal()
ndel = self.partida.anulaUltimoMovimiento(self.siJugamosConBlancas)
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.posJugadaObj -= ndel
self.analisis = None
self.ponteAlFinal()
diff --git a/Code/GestorGM.py b/Code/GestorGM.py
index c6beeab..b5f2493 100644
--- a/Code/GestorGM.py
+++ b/Code/GestorGM.py
@@ -308,10 +308,12 @@ def mueveHumano(self, desde, hasta, coronacion=None):
rmUsu, nada = mrm.buscaRM(jgUsu.movimiento())
if rmUsu is None:
+ um = QTUtil2.analizando(self.pantalla)
self.analizaFinal()
rmUsu = self.xtutor.valora(posicion, desde, hasta, coronacion)
mrm.agregaRM(rmUsu)
self.analizaInicio()
+ um.final()
rmGM, posGM = mrm.buscaRM(jgGM.movimiento())
if rmGM is None:
@@ -390,7 +392,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponFlechaSC(jg.desde, jg.hasta)
self.beepExtendido(siNuestra)
diff --git a/Code/GestorMicElo.py b/Code/GestorMicElo.py
index 49b74f1..cdf827a 100644
--- a/Code/GestorMicElo.py
+++ b/Code/GestorMicElo.py
@@ -134,7 +134,7 @@ def inicio(self, datosMotor, minutos, segundos, siCompetitivo, aplazamiento=None
self.maxSegundos = aplazamiento["MAXSEGUNDOS"]
self.segundosJugada = aplazamiento["SEGUNDOSJUGADA"]
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
else:
self.datosMotor = datosMotor
@@ -392,7 +392,7 @@ def masJugada(self, jg, siNuestra):
self.partida.liJugadas.append(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
@@ -601,7 +601,7 @@ def relojStop(self, siUsuario):
def atras(self):
if self.partida.numJugadas() > 2:
self.partida.anulaUltimoMovimiento(self.siJugamosConBlancas)
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponteAlFinal()
self.refresh()
self.siguienteJugada()
diff --git a/Code/GestorOpeningLines.py b/Code/GestorOpeningLines.py
new file mode 100644
index 0000000..127f0e6
--- /dev/null
+++ b/Code/GestorOpeningLines.py
@@ -0,0 +1,548 @@
+import time
+
+from Code import Gestor
+from Code import Jugada
+from Code import ControlPosicion
+from Code import TrListas
+from Code.QT import QTUtil2
+from Code import Util
+from Code import OpeningLines
+from Code import XMotorRespuesta
+from Code import Partida
+from Code.Constantes import *
+
+
+class GestorOpeningLines(Gestor.Gestor):
+ def inicio(self, pathFichero, modo, num_linea):
+ self.tablero.saveVisual()
+
+ self.pathFichero = pathFichero
+ dbop = OpeningLines.Opening(pathFichero)
+ self.tablero.dbVisual_setFichero(dbop.nomFichero)
+ self.reinicio(dbop, modo, num_linea)
+
+ def reinicio(self, dbop, modo, num_linea):
+ self.dbop = dbop
+ self.tipoJuego = kJugOpeningLines
+
+ self.modo = modo
+ self.num_linea = num_linea
+
+ self.training = self.dbop.training()
+ self.liGames = self.training["LIGAMES_%s" % modo.upper()]
+ self.game = self.liGames[num_linea]
+ self.liPV = self.game["LIPV"]
+ self.numPV = len(self.liPV)
+
+ self.calc_totalTiempo()
+
+ self.dicFENm2 = self.training["DICFENM2"]
+
+
+ self.liMensBasic = [
+ "%s: %d" % (_("Lines"), len(self.liGames)),
+ ]
+
+ self.siAyuda = False
+ self.tablero.dbVisual_setShowAllways(False)
+
+ self.partida = Partida.Partida()
+
+ self.ayudas = 9999 # Para que analice sin problemas
+
+ self.siJugamosConBlancas = self.training["COLOR"] == "WHITE"
+ self.siRivalConBlancas = not self.siJugamosConBlancas
+
+ self.pantalla.ponToolBar((k_mainmenu, k_ayuda, k_reiniciar))
+ self.pantalla.activaJuego(True, False, siAyudas=False)
+ self.ponMensajero(self.mueveHumano)
+ self.ponPosicion(self.partida.ultPosicion)
+ self.mostrarIndicador(True)
+ self.quitaAyudas()
+ self.ponPiezasAbajo(self.siJugamosConBlancas)
+ self.pgnRefresh(True)
+
+ self.ponCapInfoPorDefecto()
+
+ self.estado = kJugando
+
+ self.ponPosicionDGT()
+
+ self.errores = 0
+ self.ini_time = time.time()
+ self.muestraInformacion()
+ self.siguienteJugada()
+
+ def calc_totalTiempo(self):
+ self.tm = 0
+ for game in self.liGames:
+ for tr in game["TRIES"]:
+ self.tm += tr["TIME"]
+
+ def ayuda(self):
+ self.siAyuda = True
+ self.pantalla.ponToolBar((k_mainmenu, k_reiniciar))
+ self.tablero.dbVisual_setShowAllways(True)
+
+ self.muestraAyuda()
+ self.muestraInformacion()
+
+ def muestraInformacion(self):
+ li = []
+ li.append("%s: %d" %(_("Errors"), self.errores))
+ if self.siAyuda:
+ li.append(_("Help activated"))
+ self.ponRotulo1("\n".join(li))
+
+ tgm = 0
+ for tr in self.game["TRIES"]:
+ tgm += tr["TIME"]
+
+ mens = "\n" + "\n".join(self.liMensBasic)
+ mens += "\n%s:\n %s %s\n %s %s" % (_("Working time"),
+ time.strftime("%H:%M:%S", time.gmtime(tgm)), _("Current"),
+ time.strftime("%H:%M:%S", time.gmtime(self.tm)), _("Total"))
+
+ self.ponRotulo2(mens)
+
+ if self.siAyuda:
+ dicNAGs = TrListas.dicNAGs()
+ mens3 = ""
+ fenM2 = self.partida.ultPosicion.fenM2()
+ reg = self.dbop.getfenvalue(fenM2)
+ if reg:
+ mens3 = reg["COMENTARIO"]
+ ventaja = reg.get("VENTAJA", 0)
+ valoracion = reg.get("VALORACION", 0)
+ if ventaja:
+ mens3 += "\n %s" % dicNAGs[ventaja]
+ if valoracion:
+ mens3 += "\n %s" % dicNAGs[valoracion]
+ self.ponRotulo3(mens3 if mens3 else None)
+
+
+ def partidaTerminada(self, siCompleta):
+ tm = time.time() - self.ini_time
+ li = [_("Line finished.")]
+ if self.siAyuda:
+ li.append(_("Help activated"))
+ if self.errores > 0:
+ li.append("%s: %d" % (_("Errors"), self.errores))
+
+ if siCompleta:
+ QTUtil2.mensaje(self.pantalla, "\n".join(li))
+
+ dictry = {
+ "DATE": Util.hoy(),
+ "TIME": tm,
+ "AYUDA": self.siAyuda,
+ "ERRORS": self.errores
+ }
+ self.game["TRIES"].append(dictry)
+
+ sinError = self.errores == 0 and not self.siAyuda
+ if siCompleta:
+ if sinError:
+ self.game["NOERROR"] += 1
+ noError = self.game["NOERROR"]
+ if self.modo == "sequential":
+ salto = 2**(noError + 1)
+ numGames = len(self.liGames)
+ for x in range(salto, numGames):
+ game = self.liGames[x]
+ if game["NOERROR"] != noError:
+ salto = x
+ break
+
+ liNuevo = self.liGames[1:salto]
+ liNuevo.append(self.game)
+ if numGames > salto:
+ liNuevo.extend(self.liGames[salto:])
+ self.training["LIGAMES_SEQUENTIAL"] = liNuevo
+ self.pantalla.ponToolBar((k_mainmenu, k_siguiente))
+ else:
+ self.pantalla.ponToolBar((k_mainmenu, k_reiniciar))
+ else:
+ self.game["NOERROR"] -= 1
+
+ self.pantalla.ponToolBar((k_mainmenu, k_reiniciar))
+ else:
+ if not sinError:
+ self.game["NOERROR"] -= 1
+ self.game["NOERROR"] = max(0, self.game["NOERROR"])
+
+ self.dbop.setTraining(self.training)
+ self.estado = kFinJuego
+ self.calc_totalTiempo()
+ self.muestraInformacion()
+
+ def muestraAyuda(self):
+ pv = self.liPV[len(self.partida)]
+ self.tablero.creaFlechaMov(pv[:2], pv[2:4], "mt80")
+ fenM2 = self.partida.ultPosicion.fenM2()
+ for pv1 in self.dicFENm2[fenM2]:
+ if pv1 != pv:
+ self.tablero.creaFlechaMov(pv1[:2], pv1[2:4], "ms40")
+
+ def procesarAccion(self, clave):
+ if clave == k_mainmenu:
+ self.finPartida()
+
+ elif clave == k_reiniciar :
+ self.reiniciar()
+
+ elif clave == k_configurar:
+ self.configurar(siSonidos=True)
+
+ elif clave == k_utilidades:
+ self.utilidades()
+
+ elif clave == k_siguiente:
+ self.reinicio(self.dbop, self.modo, self.num_linea)
+
+ elif clave == k_ayuda:
+ self.ayuda()
+
+ else:
+ Gestor.Gestor.rutinaAccionDef(self, clave)
+
+ def finalX(self):
+ return self.finPartida()
+
+ def finPartida(self):
+ self.dbop.close()
+ self.tablero.restoreVisual()
+ self.procesador.inicio()
+ if self.modo == "static":
+ self.procesador.openingsTrainingStatic(self.pathFichero)
+ else:
+ self.procesador.openings()
+ return False
+
+ def reiniciar(self):
+ if len(self.partida) > 0 and self.estado != kFinJuego:
+ self.partidaTerminada(False)
+ self.reinicio(self.dbop, self.modo, self.num_linea)
+
+ def siguienteJugada(self):
+ self.muestraInformacion()
+ if self.estado == kFinJuego:
+ return
+
+ self.estado = kJugando
+
+ self.siJuegaHumano = False
+ self.ponVista()
+
+ siBlancas = self.partida.ultPosicion.siBlancas
+
+ self.ponIndicador(siBlancas)
+ self.refresh()
+
+ siRival = siBlancas == self.siRivalConBlancas
+
+ numJugadas = len(self.partida)
+ if numJugadas >= self.numPV:
+ self.partidaTerminada(True)
+ return
+ pv = self.liPV[numJugadas]
+
+ if siRival:
+ self.desactivaTodas()
+
+ self.rmRival = XMotorRespuesta.RespuestaMotor("Apertura", self.siRivalConBlancas)
+ self.rmRival.desde = pv[:2]
+ self.rmRival.hasta = pv[2:4]
+ self.rmRival.coronacion = pv[4:]
+
+ self.mueveRival(self.rmRival)
+ self.siguienteJugada()
+
+ else:
+ self.activaColor(siBlancas)
+ self.siJuegaHumano = True
+ if self.siAyuda:
+ self.muestraAyuda()
+
+ def mueveHumano(self, desde, hasta, coronacion=""):
+ jg = self.checkMueveHumano(desde, hasta, coronacion)
+ if not jg:
+ return False
+ pvSel = desde + hasta + coronacion
+ pvObj = self.liPV[len(self.partida)]
+
+ if pvSel != pvObj:
+ fenM2 = jg.posicionBase.fenM2()
+ li = self.dicFENm2[fenM2]
+ if pvSel in li:
+ mens = _("You have selected a correct move, but this line uses another one.")
+ QTUtil2.mensajeTemporal(self.pantalla, mens, 2, posicion="tb", background="#C3D6E8")
+ self.sigueHumano()
+ return False
+
+ self.errores += 1
+ mens = "%s: %d" % (_("Error"), self.errores)
+ QTUtil2.mensajeTemporal(self.pantalla, mens, 2, posicion="tb", background="#FF9B00")
+ self.muestraInformacion()
+ self.sigueHumano()
+ return False
+
+ self.movimientosPiezas(jg.liMovs)
+
+ self.masJugada(jg, True)
+ self.siguienteJugada()
+ return True
+
+ def masJugada(self, jg, siNuestra):
+ self.partida.append_jg(jg)
+ if self.partida.pendienteApertura:
+ self.partida.asignaApertura()
+
+ self.ponFlechaSC(jg.desde, jg.hasta)
+ self.beepExtendido(siNuestra)
+
+ self.pgnRefresh(self.partida.ultPosicion.siBlancas)
+ self.refresh()
+
+ self.ponPosicionDGT()
+
+ def mueveRival(self, respMotor):
+ desde = respMotor.desde
+ hasta = respMotor.hasta
+
+ coronacion = respMotor.coronacion
+
+ siBien, mens, jg = Jugada.dameJugada(self.partida.ultPosicion, desde, hasta, coronacion)
+ if siBien:
+ self.partida.ultPosicion = jg.posicion
+
+ self.masJugada(jg, False)
+ self.movimientosPiezas(jg.liMovs, True)
+
+ self.error = ""
+
+ return True
+ else:
+ self.error = mens
+ return False
+
+
+class GestorOpeningLinesPositions(Gestor.Gestor):
+ def inicio(self, pathFichero):
+ self.pathFichero = pathFichero
+ dbop = OpeningLines.Opening(pathFichero)
+ self.reinicio(dbop)
+
+ def reinicio(self, dbop):
+ self.dbop = dbop
+ self.tipoJuego = kJugOpeningLines
+
+ self.training = self.dbop.training()
+ self.liTrainPositions = self.training["LITRAINPOSITIONS"]
+ self.trposition = self.liTrainPositions[0]
+
+ self.tm = 0
+ for game in self.liTrainPositions:
+ for tr in game["TRIES"]:
+ self.tm += tr["TIME"]
+
+ self.liMensBasic = [
+ "%s: %d" % (_("Moves"), len(self.liTrainPositions)),
+ ]
+
+ self.siAyuda = False
+
+ cp = ControlPosicion.ControlPosicion()
+ cp.leeFen(self.trposition["FENM2"] + " 0 1")
+
+ self.partida = Partida.Partida(iniPosicion=cp)
+
+ self.ayudas = 9999 # Para que analice sin problemas
+
+ self.siJugamosConBlancas = self.training["COLOR"] == "WHITE"
+ self.siRivalConBlancas = not self.siJugamosConBlancas
+
+ self.pantalla.ponToolBar((k_mainmenu, k_ayuda, k_reiniciar))
+ self.pantalla.activaJuego(True, False, siAyudas=False)
+ self.ponMensajero(self.mueveHumano)
+ self.ponPosicion(cp)
+ self.mostrarIndicador(True)
+ self.quitaAyudas()
+ self.ponPiezasAbajo(self.siJugamosConBlancas)
+ self.pgnRefresh(True)
+
+ self.ponCapInfoPorDefecto()
+
+ self.estado = kJugando
+
+ self.ponPosicionDGT()
+
+ self.quitaInformacion()
+
+ self.errores = 0
+ self.ini_time = time.time()
+ self.muestraInformacion()
+ self.siguienteJugada()
+
+ def ayuda(self):
+ self.siAyuda = True
+ self.pantalla.ponToolBar((k_mainmenu, k_reiniciar))
+
+ self.muestraAyuda()
+ self.muestraInformacion()
+
+ def muestraInformacion(self):
+ li = []
+ li.append("%s: %d" %(_("Errors"), self.errores))
+ if self.siAyuda:
+ li.append(_("Help activated"))
+ self.ponRotulo1("\n".join(li))
+
+ tgm = 0
+ for tr in self.trposition["TRIES"]:
+ tgm += tr["TIME"]
+
+ mas = time.time() - self.ini_time
+
+ mens = "\n" + "\n".join(self.liMensBasic)
+ mens += "\n%s:\n %s %s\n %s %s" % (_("Working time"),
+ time.strftime("%H:%M:%S", time.gmtime(tgm+mas)), _("Current"),
+ time.strftime("%H:%M:%S", time.gmtime(self.tm+mas)), _("Total"))
+
+ self.ponRotulo2(mens)
+
+ def posicionTerminada(self):
+ tm = time.time() - self.ini_time
+ li = [_("Finished.")]
+ if self.siAyuda:
+ li.append(_("Help activated"))
+ if self.errores > 0:
+ li.append("%s: %d" % (_("Errors"), self.errores))
+
+ QTUtil2.mensajeTemporal(self.pantalla, "\n".join(li), 1.2)
+
+ dictry = {
+ "DATE": Util.hoy(),
+ "TIME": tm,
+ "AYUDA": self.siAyuda,
+ "ERRORS": self.errores
+ }
+ self.trposition["TRIES"].append(dictry)
+
+ sinError = self.errores == 0 and not self.siAyuda
+ if sinError:
+ self.trposition["NOERROR"] += 1
+ else:
+ self.trposition["NOERROR"] = max(0, self.trposition["NOERROR"]-1)
+ noError = self.trposition["NOERROR"]
+ salto = 2**(noError + 1) + 1
+ numPosics = len(self.liTrainPositions)
+ for x in range(salto, numPosics):
+ posic = self.liTrainPositions[x]
+ if posic["NOERROR"] != noError:
+ salto = x
+ break
+
+ liNuevo = self.liTrainPositions[1:salto]
+ liNuevo.append(self.trposition)
+ if numPosics > salto:
+ liNuevo.extend(self.liTrainPositions[salto:])
+ self.training["LITRAINPOSITIONS"] = liNuevo
+ self.pantalla.ponToolBar((k_mainmenu, k_siguiente))
+
+ self.dbop.setTraining(self.training)
+ self.estado = kFinJuego
+ self.muestraInformacion()
+
+ def muestraAyuda(self):
+ liMoves = self.trposition["MOVES"]
+ for pv in liMoves:
+ self.tablero.creaFlechaMov(pv[:2], pv[2:4], "mt80")
+
+ def procesarAccion(self, clave):
+ if clave == k_mainmenu:
+ self.finPartida()
+
+ elif clave == k_reiniciar :
+ self.reiniciar()
+
+ elif clave == k_configurar:
+ self.configurar(siSonidos=True)
+
+ elif clave == k_utilidades:
+ self.utilidades()
+
+ elif clave == k_siguiente:
+ self.reinicio(self.dbop)
+
+ elif clave == k_ayuda:
+ self.ayuda()
+
+ else:
+ Gestor.Gestor.rutinaAccionDef(self, clave)
+
+ def finalX(self):
+ return self.finPartida()
+
+ def finPartida(self):
+ self.dbop.close()
+ self.procesador.inicio()
+ self.procesador.openings()
+ return False
+
+ def reiniciar(self):
+ self.reinicio(self.dbop)
+
+ def siguienteJugada(self):
+ self.muestraInformacion()
+ if self.estado == kFinJuego:
+ return
+
+ self.estado = kJugando
+
+ self.siJuegaHumano = False
+ self.ponVista()
+
+ siBlancas = self.partida.ultPosicion.siBlancas
+
+ self.ponIndicador(siBlancas)
+ self.refresh()
+
+ self.activaColor(siBlancas)
+ self.siJuegaHumano = True
+ if self.siAyuda:
+ self.muestraAyuda()
+
+ def mueveHumano(self, desde, hasta, coronacion=""):
+ jg = self.checkMueveHumano(desde, hasta, coronacion)
+ if not jg:
+ return False
+ pvSel = desde + hasta + coronacion
+ lipvObj = self.trposition["MOVES"]
+
+ if pvSel not in lipvObj:
+ self.errores += 1
+ mens = "%s: %d" % (_("Error"), self.errores)
+ QTUtil2.mensajeTemporal(self.pantalla, mens, 2, posicion="ad", background="#FF9B00")
+ self.muestraInformacion()
+ self.sigueHumano()
+ return False
+
+ self.movimientosPiezas(jg.liMovs)
+
+ self.masJugada(jg, True)
+ self.posicionTerminada()
+ return True
+
+ def masJugada(self, jg, siNuestra):
+ self.partida.append_jg(jg)
+ if self.partida.pendienteApertura:
+ self.partida.asignaApertura()
+
+ self.ponFlechaSC(jg.desde, jg.hasta)
+ self.beepExtendido(siNuestra)
+
+ self.pgnRefresh(self.partida.ultPosicion.siBlancas)
+ self.refresh()
+
+ self.ponPosicionDGT()
\ No newline at end of file
diff --git a/Code/GestorPGN.py b/Code/GestorPGN.py
index 6289032..ba24e05 100644
--- a/Code/GestorPGN.py
+++ b/Code/GestorPGN.py
@@ -193,7 +193,7 @@ def miniatura(self):
def mostrar(self, pgn, siRepiteFichero, siBlancas=None):
self.pensando(True)
self.partida.leeOtra(pgn.partida)
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
blancas = pgn.variable("WHITE")
negras = pgn.variable("BLACK")
resultado = pgn.variable("RESULT")
diff --git a/Code/GestorPartida.py b/Code/GestorPartida.py
index 96418e2..efcad16 100644
--- a/Code/GestorPartida.py
+++ b/Code/GestorPartida.py
@@ -184,7 +184,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
@@ -349,8 +349,7 @@ def configurarGS(self):
return
p = Partida.PartidaCompleta()
p.leeOtra(partida)
- if self.siCompleta:
- p.asignaApertura(self.configuracion)
+ p.asignaApertura()
p.setTags(unpgn.listaCabeceras())
self.reinicio = p.save()
self.reiniciar()
@@ -368,8 +367,7 @@ def configurarGS(self):
return
p = Partida.PartidaCompleta()
p.leeOtra(partida)
- if self.siCompleta:
- p.asignaApertura(self.configuracion)
+ p.asignaApertura()
p.setTags(unpgn.listaCabeceras())
self.reinicio = p.save()
self.reiniciar()
@@ -438,7 +436,7 @@ def atras(self):
if self.partida.numJugadas():
self.partida.anulaSoloUltimoMovimiento()
if not self.fen:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponteAlFinal()
self.estado = kJugando
self.refresh()
diff --git a/Code/GestorPerson.py b/Code/GestorPerson.py
index cb94dcd..aea2165 100644
--- a/Code/GestorPerson.py
+++ b/Code/GestorPerson.py
@@ -299,7 +299,7 @@ def atras(self):
self.ayudas -= 1
self.partida.anulaUltimoMovimiento(self.siJugamosConBlancas)
if not self.fen:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponteAlFinal()
self.refresh()
self.siguienteJugada()
@@ -422,7 +422,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
diff --git a/Code/GestorPlayPGN.py b/Code/GestorPlayPGN.py
index 6adeb38..2c60080 100644
--- a/Code/GestorPlayPGN.py
+++ b/Code/GestorPlayPGN.py
@@ -275,7 +275,7 @@ def masJugada(self, siNuestra, analisis=None, comentario=None):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.movimientosPiezas(jg.liMovs, True)
self.tablero.ponPosicion(jg.posicion)
self.ponFlechaSC(jg.desde, jg.hasta)
diff --git a/Code/GestorResistance.py b/Code/GestorResistance.py
index 91db0bb..fda1525 100644
--- a/Code/GestorResistance.py
+++ b/Code/GestorResistance.py
@@ -34,7 +34,6 @@ def inicio(self, resistance, numEngine, clave):
self.apertura = Apertura.AperturaPol(5) # lee las aperturas
# debe hacerse antes que rival
- # arbitro = self.configuracion.buscaRival( "stockfish" )
self.xarbitro = self.procesador.creaGestorMotor(self.configuracion.tutor, self.segundos * 1000, None)
self.xarbitro.anulaMultiPV()
@@ -289,7 +288,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
diff --git a/Code/GestorRoutes.py b/Code/GestorRoutes.py
index b14aec9..37c3076 100644
--- a/Code/GestorRoutes.py
+++ b/Code/GestorRoutes.py
@@ -1,7 +1,7 @@
import random
import time
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import Util
from Code import Books
@@ -141,7 +141,7 @@ def finalX(self):
def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
diff --git a/Code/GestorSolo.py b/Code/GestorSolo.py
index b3467f9..2562198 100644
--- a/Code/GestorSolo.py
+++ b/Code/GestorSolo.py
@@ -152,12 +152,12 @@ def inicio(self, dic=None, fichero=None, pgn=None, jugadaInicial=None, siGrabar=
if self.bloqueApertura:
self.partida.reset()
self.partida.leerPV(self.bloqueApertura.a1h8)
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
if "PARTIDA" in dic:
self.partida.reset()
self.partida.recuperaDeTexto(dic["PARTIDA"])
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
cp = self.partida.iniPosicion # Para ver si las blancas abajo
self.ponToolBar(siExterno, siGrabar)
@@ -383,7 +383,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
@@ -585,9 +585,11 @@ def file(self):
menu = QTVarios.LCMenu(self.pantalla)
if self.ultimoFichero:
menuR = menu.submenu(_("Save"), Iconos.Grabar())
- rpath = os.path.relpath(self.ultimoFichero)
- if rpath.count("..") > 0:
- rpath = self.ultimoFichero
+ rpath = self.ultimoFichero
+ if os.curdir[:1] == rpath[:1]:
+ rpath = os.path.relpath(rpath)
+ if rpath.count("..") > 0:
+ rpath = self.ultimoFichero
menuR.opcion("save", "%s: %s" %( _("Save"), rpath), Iconos.Grabar())
menuR.separador()
menuR.opcion("saveas", _("Save as"), Iconos.GrabarComo())
@@ -926,7 +928,7 @@ def atras(self):
if self.partida.numJugadas():
self.partida.anulaSoloUltimoMovimiento()
if not self.fen:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponteAlFinal()
self.estado = kJugando
self.refresh()
diff --git a/Code/GestorTorneo.py b/Code/GestorTorneo.py
index be55974..07a627a 100644
--- a/Code/GestorTorneo.py
+++ b/Code/GestorTorneo.py
@@ -4,7 +4,6 @@
from Code import Partida
from Code.QT import PantallaTorneos
from Code import Util
-from Code import VarGen
from Code import XGestorMotor
from Code.Constantes import *
@@ -17,7 +16,6 @@ def inicio(self, torneo, liGames):
self.torneo = torneo
self.torneoTMP = torneo.clone()
self.torneoTMP._liGames = liGames
- self.fenInicial = self.torneo.fenNorman()
self.liGames = liGames
self.pantalla.ponActivarTutor(False)
self.ponPiezasAbajo(True)
@@ -33,6 +31,7 @@ def inicio(self, torneo, liGames):
numGames = len(self.liGames)
for ng, gm in enumerate(self.liGames):
self.siguienteJuego(gm, ng + 1, numGames)
+ self.procesador.pararMotores()
if self.siTerminar:
break
if self.wresult:
@@ -43,6 +42,7 @@ def inicio(self, torneo, liGames):
def siguienteJuego(self, gm, ngame, numGames):
self.estado = kJugando
+ self.fenInicial = self.torneo.fenNorman()
self.gm = gm
self.maxSegundos = self.gm.minutos() * 60.0
@@ -71,8 +71,8 @@ def siguienteJuego(self, gm, ngame, numGames):
bk = rv.book()
if bk == "*":
- bk = VarGen.tbook
- elif bk == "-":
+ bk = self.torneo.book()
+ if bk == "-": # Puede que el torneo tenga "-"
bk = None
if bk:
self.book[color] = Books.Libro("P", bk, bk, True)
@@ -118,8 +118,6 @@ def guiDispatch(self, rm):
txt = "[%s] (%s) %s" % (rm.nombre, rm.abrTexto(), p.pgnSP())
self.ponRotulo3(txt)
self.showPV(rm.pv, 3)
- # self.ponFlechaSC( rm.pv[:2], rm.pv[2:4] )
- # QTUtil.refreshGUI()
self.refresh()
return not self.siTerminar
@@ -300,7 +298,7 @@ def masJugada(self, jg):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
diff --git a/Code/GestorTurnOnLights.py b/Code/GestorTurnOnLights.py
index 4cb51e9..b4bba1e 100644
--- a/Code/GestorTurnOnLights.py
+++ b/Code/GestorTurnOnLights.py
@@ -26,6 +26,7 @@ def inicio(self, num_theme, num_block, tol):
self.calculation_mode = self.tol.is_calculation_mode()
self.penaltyError = self.block.penaltyError(self.calculation_mode)
self.penaltyHelp = self.block.penaltyHelp(self.calculation_mode)
+ # self.factorDistancia = self.block.factorDistancia() # No se usa es menor que 1.0
self.av_seconds = self.block.av_seconds()
if self.av_seconds:
@@ -167,8 +168,9 @@ def siguienteJugada(self):
else:
self.siJuegaHumano = True
+ self.base_time = time.time()
if not (self.calculation_mode and self.ini_time is None): # Se inicia salvo que sea el principio de la linea
- self.ini_time = time.time()
+ self.ini_time = self.base_time
self.activaColor(siBlancas)
if self.calculation_mode:
self.tablero.setDispatchMove(self.dispatchMove)
@@ -250,6 +252,8 @@ def finLinea(self):
self.pantalla.ponToolBar(liOpciones)
def mueveHumano(self, desde, hasta, coronacion=None):
+ if self.ini_time is None:
+ self.ini_time = self.base_time
end_time = time.time()
jg = self.checkMueveHumano(desde, hasta, coronacion)
if not jg:
diff --git a/Code/GestorVariantes.py b/Code/GestorVariantes.py
index 304397d..fcbf28c 100644
--- a/Code/GestorVariantes.py
+++ b/Code/GestorVariantes.py
@@ -136,7 +136,7 @@ def atras(self):
if self.partida.numJugadas():
self.partida.anulaSoloUltimoMovimiento()
if not self.fen:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponteAlFinal()
self.refresh()
self.siguienteJugada()
@@ -211,7 +211,7 @@ def masJugada(self, jg):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
diff --git a/Code/GestorWashing.py b/Code/GestorWashing.py
index 721fa57..bc5904d 100644
--- a/Code/GestorWashing.py
+++ b/Code/GestorWashing.py
@@ -216,7 +216,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponFlechaSC(jg.desde, jg.hasta)
self.beepExtendido(siNuestra)
@@ -728,7 +728,7 @@ def masJugada(self, jg, siNuestra):
self.partida.append_jg(jg)
if self.partida.pendienteApertura:
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
resp = self.partida.si3repetidas()
if resp:
@@ -815,7 +815,7 @@ def atras(self):
if self.partida.numJugadas():
self.analizaTerminar()
self.partida.anulaUltimoMovimiento(self.siJugamosConBlancas)
- self.listaAperturasStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
self.ponteAlFinal()
self.apertura = Apertura.AperturaPol(30, self.engine.elo)
self.siAnalizadoTutor = False
diff --git a/Code/Init.py b/Code/Init.py
index c3cbca0..7aab268 100644
--- a/Code/Init.py
+++ b/Code/Init.py
@@ -9,7 +9,7 @@
from Code.Constantes import *
DEBUG = False
-VERSION = "11.05b"
+VERSION = "11.06"
if DEBUG:
prlkn("DEBUG " * 20)
diff --git a/Code/Jugada.py b/Code/Jugada.py
index 094e7a4..eadc61d 100644
--- a/Code/Jugada.py
+++ b/Code/Jugada.py
@@ -113,14 +113,18 @@ def pgnSP(self):
def pgnFigurinesSP(self):
return self.pgnBase + self.resultadoSP()
- def pgnHTML(self):
+ def pgnHTML(self, siFigurines):
siBlancas = self.siBlancas()
- li = []
- for c in self.pgnBase:
- if c in "NBRQK":
- c = dicHTMLFigs[c if siBlancas else c.lower()]
- li.append(c)
- resp = "".join(li) + self.resto()
+ if siFigurines:
+ li = []
+ for c in self.pgnBase:
+ if c in "NBRQK":
+ c = dicHTMLFigs[c if siBlancas else c.lower()]
+ li.append(c)
+ resp = "".join(li)
+ else:
+ resp = self.pgnBaseSP()
+ resp += self.resto()
result = self.resultado()
if result:
resp += " " + result
@@ -427,6 +431,9 @@ def calc_elo(self, perfomance):
self.bad_move = False
self.verybad_move = False
+ def distancia(self):
+ return ControlPosicion.distancia(self.desde, self.hasta)
+
def dameJugada(posicionBase, desde, hasta, coronacion):
posicion = posicionBase.copia()
diff --git a/Code/LibChess.py b/Code/LibChess.py
index fc7f546..ba0d14d 100644
--- a/Code/LibChess.py
+++ b/Code/LibChess.py
@@ -1,6 +1,6 @@
import random
-import LCEngine
+import LCEngineV1 as LCEngine
import chess
import chess.syzygy
diff --git a/Code/Memoria.py b/Code/Memoria.py
index 537ba65..bf91196 100644
--- a/Code/Memoria.py
+++ b/Code/Memoria.py
@@ -84,7 +84,6 @@ def lanzaNivel(self, numcategoria, nivel):
return False
def dameListaFen(self, piezas):
-
me = self.procesador.unMomento()
li = []
diff --git a/Code/OpeningGuide.py b/Code/OpeningGuide.py
index 743430e..b1e773c 100644
--- a/Code/OpeningGuide.py
+++ b/Code/OpeningGuide.py
@@ -2,7 +2,7 @@
import os
import sqlite3
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import AperturasStd
from Code import Books
diff --git a/Code/OpeningLines.py b/Code/OpeningLines.py
index 2f05bec..72de83a 100644
--- a/Code/OpeningLines.py
+++ b/Code/OpeningLines.py
@@ -1,26 +1,47 @@
import os
import sqlite3
-import atexit
+import random
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import Util
from Code import Partida
from Code import PGNreader
from Code import Books
+from Code import DBgames
from Code.QT import QTVarios
from Code.QT import QTUtil2
-
class ListaOpenings:
def __init__(self, configuracion):
self.folder = configuracion.folderOpenings
- self.fichero = os.path.join(self.folder, "index.pk")
+ self.fichero = os.path.join(self.folder, "openinglines.pk")
self.lista = Util.recuperaVar(self.fichero)
if self.lista is None:
- self.lista = self.read()
+ self.lista = self.read() # file, lines, title, pv
self.save()
+ else:
+ self.testdates()
+
+ def testdates(self):
+ index_date = Util.datefile(self.fichero)
+
+ for pos, dic in enumerate(self.lista):
+ pathfile = os.path.join(self.folder, dic["file"])
+ file_date = Util.datefile(pathfile)
+ if file_date is None:
+ self.reiniciar()
+ break
+ if file_date > index_date:
+ op = Opening(pathfile)
+ self.lista[pos]["lines"] = len(op)
+ op.close()
+ self.save()
+
+ def reiniciar(self):
+ self.lista = self.read()
+ self.save()
def __len__(self):
return len(self.lista)
@@ -29,9 +50,9 @@ def __getitem__(self, item):
return self.lista[item] if self.lista and item < len(self.lista) else None
def __delitem__(self, item):
- name, pv, tit = self.lista[item]
+ dicline = self.lista[item]
del self.lista[item]
- os.remove(os.path.join(self.folder, name))
+ os.remove(os.path.join(self.folder, dicline["file"]))
self.save()
def arriba(self, item):
@@ -50,36 +71,20 @@ def abajo(self, item):
else:
return False
- def refresh(self):
- dic = {}
- for entry in Util.listdir(self.folder):
- if entry.name.endswith(".opk"):
- op = Opening(entry.path)
- dic[entry.name] = (entry.name, op.basePV, op.title)
- op.close()
- liborrar = []
- st_esta = set()
- for n, (fichero, basePV, title) in enumerate(self.lista):
- if fichero in dic:
- self.lista[n] = dic[fichero]
- st_esta.add(fichero)
- else:
- liborrar.append(n)
- for x in range(len(liborrar)-1, -1, -1):
- del self.lista[x]
-
- for fichero in dic:
- if fichero not in st_esta:
- self.lista.append(dic[fichero])
- self.save()
-
def read(self):
li = []
for entry in Util.listdir(self.folder):
fichero = entry.name
if fichero.endswith(".opk"):
op = Opening(entry.path)
- li.append((fichero, op.basePV, op.title))
+ dicline = {
+ "file": fichero,
+ "pv": op.basePV,
+ "title": op.title,
+ "lines": len(op),
+ "withtrainings": op.withTrainings()
+ }
+ li.append(dicline)
op.close()
return li
@@ -88,9 +93,8 @@ def save(self):
def select_filename(self, name):
name = name.strip().replace(" ", "_")
- name = Util.validNomFichero(name)
- while "__" in name:
- name = name.replace("__", "_")
+ name = Util.asciiNomFichero(name)
+
plant = name + "%d.opk"
file = name + ".opk"
num = 0
@@ -100,10 +104,17 @@ def select_filename(self, name):
return file
def filepath(self, num):
- return os.path.join(self.folder, self.lista[num][0])
+ return os.path.join(self.folder, self.lista[num]["file"])
def new(self, file, basepv, title):
- self.lista.append((file, basepv, title))
+ dicline = {
+ "file": file,
+ "pv": basepv,
+ "title": title,
+ "lines": 0,
+ "withtrainings": False
+ }
+ self.lista.append(dicline)
op = Opening(self.filepath(len(self.lista)-1))
op.setbasepv(basepv)
op.settitle(title)
@@ -114,11 +125,14 @@ def change_title(self, num, title):
op = Opening(self.filepath(num))
op.settitle(title)
op.close()
- file, pv, ant_title = self.lista[num]
- self.lista[num] = (file, pv, title)
+ self.lista[num]["title"] = title
- def remove(self, lines):
- pass
+ def add_training_file(self, file):
+ for dicline in self.lista:
+ if file == dicline["file"]:
+ dicline["withtrainings"] = True
+ self.save()
+ return
class Opening:
@@ -126,7 +140,6 @@ def __init__(self, nomFichero):
self.nomFichero = nomFichero
self._conexion = sqlite3.connect(nomFichero)
- atexit.register(self.close)
self.cache = {}
self.max_cache = 4000
@@ -141,10 +154,16 @@ def __init__(self, nomFichero):
self.basePV = self.getconfig("BASEPV", "")
self.title = self.getconfig("TITLE", os.path.basename(nomFichero).split(".")[0])
- def getOtras(self, configuracion):
+ self.tablero = None
+
+ def setdbVisual_Tablero(self, tablero):
+ self.tablero = tablero
+
+ def getOtras(self, configuracion, partida):
liOp = ListaOpenings(configuracion)
fich = os.path.basename(self.nomFichero)
- liOp = [(fichero, titulo) for fichero, pv, titulo in liOp.lista if fichero != fich and pv.startswith(self.basePV)]
+ pvbase = partida.pv()
+ liOp = [(dic["file"], dic["title"]) for dic in liOp.lista if dic["file"] != fich and (pvbase.startswith(dic["pv"]) or dic["pv"].startswith(pvbase))]
return liOp
def getfenvalue(self, fenM2):
@@ -154,12 +173,200 @@ def getfenvalue(self, fenM2):
def setfenvalue(self, fenM2, dic):
self.db_fenvalues[fenM2] = dic
+ def removeAnalisis(self, tmpBP, mensaje):
+ for n, fenM2 in enumerate(self.db_fenvalues.keys()):
+ tmpBP.inc()
+ tmpBP.mensaje(mensaje%n)
+ if tmpBP.siCancelado():
+ break
+ dic = self.getfenvalue(fenM2)
+ if "ANALISIS" in dic:
+ del dic["ANALISIS"]
+ self.setfenvalue(fenM2, dic)
+ self.packAlTerminar()
+
def getconfig(self, key, default=None):
return self.db_config.get(key, default)
def setconfig(self, key, value):
self.db_config[key] = value
+ def training(self):
+ return self.getconfig("TRAINING")
+
+ def setTraining(self, reg):
+ return self.setconfig("TRAINING", reg)
+
+ def preparaTraining(self, reg):
+ lilipv = [LCEngine.xpv2pv(xpv).split(" ") for xpv in self.li_xpv]
+ maxmoves = reg["MAXMOVES"]
+ if maxmoves:
+ for num, lipv in enumerate(lilipv):
+ if len(lipv) > maxmoves:
+ lilipv[num] = lipv[:maxmoves]
+
+ siBlancas = reg["COLOR"] == "WHITE"
+
+ if reg["RANDOM"]:
+ random.shuffle(lilipv)
+
+ ligamesST = []
+ ligamesSQ = []
+ stPV = set()
+ dicFENm2 = {}
+ for lipv in lilipv:
+ # Siempre termina el usuario
+ if len(lipv) % 2 == (0 if siBlancas else 1):
+ lipv = lipv[:-1]
+
+ # Duplicados
+ pv = "".join(lipv)
+ if pv in stPV:
+ continue
+ stPV.add(pv)
+
+ game = {}
+ game["LIPV"] = lipv
+ game["NOERROR"] = 0
+ game["TRIES"] = []
+
+ ligamesST.append(game)
+ game = dict(game)
+ ligamesSQ.append(game)
+ LCEngine.setFenInicial()
+ for pv in lipv:
+ fen = LCEngine.getFen()
+ fenM2 = LCEngine.fen2fenM2(fen)
+ if fenM2 not in dicFENm2:
+ dicFENm2[fenM2] = set()
+ dicFENm2[fenM2].add(pv)
+ LCEngine.makeMove(pv)
+
+ reg["LIGAMES_STATIC"] = ligamesST
+ if reg["RANDOM"]:
+ random.shuffle(ligamesSQ)
+ reg["LIGAMES_SEQUENTIAL"] = ligamesSQ
+ reg["DICFENM2"] = dicFENm2
+
+ bcolor = " w " if siBlancas else " b "
+ liTrainPositions = []
+ for fenM2 in dicFENm2:
+ if bcolor in fenM2:
+ data = {}
+ data["FENM2"] = fenM2
+ data["MOVES"] = dicFENm2[fenM2]
+ data["NOERROR"] = 0
+ data["TRIES"] = []
+ liTrainPositions.append(data)
+ random.shuffle(liTrainPositions)
+ reg["LITRAINPOSITIONS"] = liTrainPositions
+
+ def createTraining(self, reg, configuracion):
+ self.preparaTraining(reg)
+
+ reg["DATECREATION"] = Util.hoy()
+ self.setconfig("TRAINING", reg)
+ self.setconfig("ULT_PACK", 100) # Se le obliga al VACUUM
+
+ lo = ListaOpenings(configuracion)
+ lo.add_training_file(os.path.basename(self.nomFichero))
+
+ def withTrainings(self):
+ return "TRAINING" in self.db_config
+
+ def updateTraining(self):
+ reg = self.training()
+ reg1 = {}
+ for key in ("MAXMOVES", "COLOR", "RANDOM"):
+ reg1[key] = reg[key]
+ self.preparaTraining(reg1)
+
+ for tipo in ("LIGAMES_SEQUENTIAL", "LIGAMES_STATIC"):
+ # Los que estan pero no son, los borramos
+ liBorrados = []
+ for pos, game in enumerate(reg[tipo]):
+ pv = " ".join(game["LIPV"])
+ ok = False
+ for game1 in reg1[tipo]:
+ pv1 = " ".join(game1["LIPV"])
+ if pv == pv1:
+ ok = True
+ break
+ if not ok:
+ liBorrados.append(pos)
+ if liBorrados:
+ li = reg[tipo]
+ liBorrados.sort(reverse=True)
+ for x in liBorrados:
+ del li[x]
+ reg[tipo] = li
+
+ # Los que son pero no estan
+ liMas = []
+ for game1 in reg1[tipo]:
+ pv1 = " ".join(game1["LIPV"])
+ ok = False
+ for game in reg[tipo]:
+ pv = " ".join(game["LIPV"])
+ if pv == pv1:
+ ok = True
+ break
+ if not ok:
+ liMas.append(game1)
+ if liMas:
+ li = reg[tipo]
+ liMas.sort(reverse=True)
+ for game in liMas:
+ li.insert(0, game)
+ reg[tipo] = li
+
+ reg["DICFENM2"] = reg1["DICFENM2"]
+
+ # Posiciones
+
+ # Estan pero no son
+ liBorrados = []
+ tipo = "LITRAINPOSITIONS"
+ for pos, data in enumerate(reg[tipo]):
+ fen = data["FENM2"]
+ ok = False
+ for data1 in reg1[tipo]:
+ fen1 = data1["FENM2"]
+ if fen == fen1:
+ ok = True
+ break
+ if not ok:
+ liBorrados.append(pos)
+ if liBorrados:
+ li = reg[tipo]
+ liBorrados.sort(reverse=True)
+ for x in liBorrados:
+ del li[x]
+ reg[tipo] = li
+
+ # Los que son pero no estan
+ liMas = []
+ for data1 in reg1[tipo]:
+ fen1 = data1["FENM2"]
+ ok = False
+ for data in reg[tipo]:
+ fen = data["FENM2"]
+ if fen == fen1:
+ ok = True
+ break
+ if not ok:
+ liMas.append(data)
+ if liMas:
+ li = reg[tipo]
+ li.insert(0, liMas)
+ reg[tipo] = li
+
+ self.setconfig("TRAINING", reg)
+ self.packAlTerminar()
+
+ def packAlTerminar(self):
+ self.setconfig("ULT_PACK", 100) # Se le obliga al VACUUM
+
def settitle(self, title):
self.setconfig("TITLE", title)
@@ -199,6 +406,7 @@ def init_database(self):
sql = "select XPV from LINES ORDER BY XPV"
cursor.execute(sql)
li_xpv = [ raw[0] for raw in cursor.fetchall()]
+ cursor.close()
return li_xpv
def append(self, partida):
@@ -246,6 +454,7 @@ def __setitem__(self, num, partida_nue):
cursor.execute(sql, (xpv_nue, partida_nue.save2blob(), xpv_ant))
self._conexion.commit()
self.add_cache(xpv_nue, partida_nue)
+ cursor.close()
return num
def __getitem__(self, num):
@@ -260,6 +469,7 @@ def __getitem__(self, num):
partida = Partida.Partida()
partida.blob2restore(blob)
self.add_cache(xpv, partida)
+ cursor.close()
return partida
def __delitem__(self, num):
@@ -271,6 +481,7 @@ def __delitem__(self, num):
del self.cache[xpv]
del self.li_xpv[num]
self._conexion.commit()
+ cursor.close()
def __len__(self):
return len(self.li_xpv)
@@ -285,6 +496,13 @@ def close(self):
self.db_config.close()
self.db_config = None
+ self.db_fenvalues.close()
+ self.db_fenvalues = None
+
+ if self.tablero:
+ self.tablero.dbVisual_close()
+ self.tablero = None
+
if si_pack:
cursor = conexion.cursor()
cursor.execute("VACUUM")
@@ -293,17 +511,15 @@ def close(self):
conexion.close()
- def grabarPGN(self, owner, ficheroPGN, maxDepth):
+ def importarPGN(self, owner, partidabase, ficheroPGN, maxDepth):
erroneos = duplicados = importados = 0
dlTmp = QTVarios.ImportarFicheroPGN(owner)
dlTmp.hideDuplicados()
dlTmp.show()
- sql = "INSERT INTO LINES( XPV, LINE ) VALUES( ?, ? )"
cursor = self._conexion.cursor()
base = self.getconfig("BASEPV")
- partidabase = self.getpartidabase()
njugbase = partidabase.numJugadas()
n = 0
@@ -320,9 +536,9 @@ def grabarPGN(self, owner, ficheroPGN, maxDepth):
continue
def haz_partida(partida, liMoves):
- njg = partida.numJugadas()
+ njg = len(partida)
if len(liMoves) + njg > maxDepth:
- liMoves = liMoves[:maxDepth+njg]
+ liMoves = liMoves[:maxDepth - njg]
pv = " ".join([move.pv for move in liMoves])
partida.leerPV(pv)
pv = partida.pv()
@@ -351,7 +567,7 @@ def haz_partida(partida, liMoves):
partida = Partida.Partida()
haz_partida(partida, g.moves.liMoves)
- if n %1000:
+ if n % 50:
self._conexion.commit()
cursor.close()
@@ -361,7 +577,32 @@ def haz_partida(partida, liMoves):
dlTmp.actualiza(n, erroneos, duplicados, importados)
dlTmp.ponContinuar()
- def grabarPolyglot(self, ventana, ficheroBIN, depth, whiteBest, blackBest):
+ def guardaPartidas(self, liPartidas):
+ partidabase = self.getpartidabase()
+ sql_insert = "INSERT INTO LINES( XPV, LINE ) VALUES( ?, ? )"
+ sql_update = "UPDATE LINES SET XPV=?, LINE=? WHERE XPV=?"
+ cursor = self._conexion.cursor()
+ for partida in liPartidas:
+ if partida.numJugadas() > partidabase.numJugadas():
+ xpv = LCEngine.pv2xpv(partida.pv())
+ if xpv not in self.li_xpv:
+ line_blob = partida.save2blob()
+ updated = False
+ for npos, xpv_ant in enumerate(self.li_xpv):
+ if xpv.startswith(xpv_ant):
+ cursor.execute(sql_update, (xpv, line_blob, xpv_ant))
+ self.li_xpv[npos] = xpv
+ updated = True
+ break
+ if not updated:
+ cursor.execute(sql_insert, (xpv, line_blob))
+ self.li_xpv.append(xpv)
+
+ cursor.close()
+ self._conexion.commit()
+ self.li_xpv.sort()
+
+ def importarPolyglot(self, ventana, partidabase, ficheroBIN, depth, siWhite):
titulo = _("Import a polyglot book")
bp = QTUtil2.BarraProgreso1(ventana, titulo)
bp.ponTotal(0)
@@ -371,9 +612,6 @@ def grabarPolyglot(self, ventana, ficheroBIN, depth, whiteBest, blackBest):
book = Books.Libro("P", ficheroBIN, ficheroBIN, True)
book.polyglot()
- stFenM2 = set() # para que no se produzca un circulo vicioso
-
- partidabase = self.getpartidabase()
cp = partidabase.ultPosicion
liPartidas = []
@@ -381,71 +619,112 @@ def grabarPolyglot(self, ventana, ficheroBIN, depth, whiteBest, blackBest):
setFen = LCEngine.setFen
makeMove = LCEngine.makeMove
getFen = LCEngine.getFen
- fen2fenM2 = LCEngine.fen2fenM2
-
- def hazFEN(fen, ply, lipv_ant):
- plyN = ply + 1
- siWhite = " w " in fen
- siMax = False
- if whiteBest:
- siMax = siWhite
- if blackBest:
- siMax = siMax or not siWhite
-
- liPV = book.miraListaPV(fen, siMax)
- if liPV:
- sigue = False
+
+ def hazFEN(fen, lipv_ant):
+ if bp.siCancelado():
+ return
+ siWhite1 = " w " in fen
+
+ liPV = book.miraListaPV(fen, siWhite1 == siWhite)
+ if liPV and len(lipv_ant) < depth:
for pv in liPV:
setFen(fen)
makeMove(pv)
fenN = getFen()
-
lipv_nue = lipv_ant[:]
lipv_nue.append(pv)
- if plyN < depth:
- fenM2 = fen2fenM2(fenN)
- if fenM2 not in stFenM2:
- stFenM2.add(fenM2)
- hazFEN(fenN, plyN, lipv_nue)
- sigue = True
+ hazFEN(fenN, lipv_nue)
else:
- sigue = False
- if not sigue:
p = Partida.Partida()
- p.leerPV(" ".join(lipv_ant))
+ p.leerLIPV(lipv_ant)
liPartidas.append(p)
bp.ponTotal(len(liPartidas))
bp.pon(len(liPartidas))
- hazFEN(cp.fen(), 0, partidabase.lipv())
+ hazFEN(cp.fen(), partidabase.lipv())
bp.ponRotulo(_("Writing..."))
+ self.guardaPartidas(liPartidas)
+ bp.cerrar()
- sql_insert = "INSERT INTO LINES( XPV, LINE ) VALUES( ?, ? )"
- sql_update = "UPDATE LINES SET XPV=?, LINE=? WHERE XPV=?"
- cursor = self._conexion.cursor()
- for partida in liPartidas:
- if partida.numJugadas() > partidabase.numJugadas():
- xpv = LCEngine.pv2xpv(partida.pv())
- if xpv not in self.li_xpv:
- line_blob = partida.save2blob()
- updated = False
- for npos, xpv_ant in enumerate(self.li_xpv):
- if xpv.startswith(xpv_ant):
- cursor.execute(sql_update, (xpv, line_blob, xpv_ant))
- self.li_xpv[npos] = xpv
- updated = True
- break
- if not updated:
- cursor.execute(sql_insert, (xpv, line_blob))
- self.li_xpv.append(xpv)
+ return True
- cursor.close()
- self._conexion.commit()
- self.li_xpv.sort()
+ def importarSummary(self, ventana, partidabase, ficheroSummary, depth, siWhite):
+ titulo = _("Importing the summary of a database")
+ bp = QTUtil2.BarraProgreso1(ventana, titulo)
+ bp.ponTotal(0)
+ bp.ponRotulo(_X(_("Reading %1"), os.path.basename(ficheroSummary)))
+ bp.mostrar()
+ dbSTAT = DBgames.TreeSTAT(ficheroSummary)
+
+ if depth == 0:
+ depth = 99999
+
+ pvBase = partidabase.pv()
+ len_partidabase = len(partidabase)
+
+ liPartidas = []
+
+ def hazPV(lipv_ant):
+ if bp.siCancelado():
+ return
+ siWhite1 = len(lipv_ant) % 2 == 0
+
+ pv_ant = " ".join(lipv_ant)
+ liChildren = dbSTAT.children(pv_ant, False)
+
+ if len(liChildren) == 0 or len(lipv_ant) > depth:
+ p = Partida.Partida()
+ p.leerLIPV(lipv_ant)
+ if len(p) > len_partidabase:
+ liPartidas.append(p)
+ bp.ponTotal(len(liPartidas))
+ bp.pon(len(liPartidas))
+ return
+
+ if siWhite1 == siWhite:
+ alm_max = None
+ tt_max = 0
+ for alm in liChildren:
+ tt = alm.W + alm.B + alm.O + alm.D
+ if tt > tt_max:
+ tt_max = tt
+ alm_max = alm
+ liChildren = [] if tt_max == 0 else [alm_max,]
+
+ for alm in liChildren:
+ li = lipv_ant[:]
+ li.append(alm.move)
+ hazPV(li)
+
+ hazPV(pvBase.split(" "))
+
+ bp.ponRotulo(_("Writing..."))
+ self.guardaPartidas(liPartidas)
bp.cerrar()
return True
-
+ def importarOtra(self, pathFichero, partida):
+ xpvbase = LCEngine.pv2xpv(partida.pv())
+ tambase = len(xpvbase)
+ otra = Opening(pathFichero)
+ liPartidas = []
+ for n, xpv in enumerate(otra.li_xpv):
+ if xpv.startswith(xpvbase) and tambase < len(xpv):
+ liPartidas.append(otra[n])
+ otra.close()
+ self.guardaPartidas(liPartidas)
+
+ def getAllFen(self):
+ stFENm2 = set()
+ lilipv = [LCEngine.xpv2pv(xpv).split(" ") for xpv in self.li_xpv]
+ for lipv in lilipv:
+ LCEngine.setFenInicial()
+ for pv in lipv:
+ fen = LCEngine.getFen()
+ fenM2 = LCEngine.fen2fenM2(fen)
+ stFENm2.add(fenM2)
+ LCEngine.makeMove(pv)
+ return stFENm2
diff --git a/Code/PGNreader.py b/Code/PGNreader.py
index cbacb41..e35ca3f 100644
--- a/Code/PGNreader.py
+++ b/Code/PGNreader.py
@@ -1,4 +1,4 @@
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import Util
diff --git a/Code/Partida.py b/Code/Partida.py
index 5ac10d2..0a5a854 100644
--- a/Code/Partida.py
+++ b/Code/Partida.py
@@ -42,7 +42,7 @@ def jugada(self, num):
try:
return self.liJugadas[num]
except:
- return None
+ return self.liJugadas[-1] if len(self) > 0 else None
def append_jg(self, jg):
self.liJugadas.append(jg)
@@ -115,9 +115,12 @@ def si3repetidas(self):
return None
def leerPV(self, pvBloque):
+ return self.leerLIPV(pvBloque.split(" "))
+
+ def leerLIPV(self, lipv):
posicion = self.ultPosicion
pv = []
- for mov in pvBloque.split(" "):
+ for mov in lipv:
if len(mov) >= 4 and mov[0] in "abcdefgh" and mov[1] in "12345678" and mov[2] in "abcdefgh" \
and mov[3] in "12345678":
pv.append(mov)
@@ -266,7 +269,7 @@ def pgnHTML(self, numJugada=None, hastaJugada=9999, siFigurines=True):
numJugada += 1
else:
x = ""
- liResp.append(x + (jg.pgnHTML() if siFigurines else jg.pgnSP()))
+ liResp.append(x + (jg.pgnHTML(siFigurines)))
return " ".join(liResp)
def siTerminada(self):
@@ -474,6 +477,27 @@ def calc_elos(self, configuracion):
return elos
+ def asignaApertura(self):
+ AperturasStd.ap.asignaApertura(self)
+
+ def asignaTransposition(self):
+ AperturasStd.ap.asignaTransposition(self)
+
+ def rotuloApertura(self):
+ return self.apertura.trNombre if hasattr(self, "apertura") and self.apertura is not None else None
+
+ def rotuloTransposition(self):
+ if hasattr(self, "transposition"):
+ ap = self.transposition
+ if ap is not None:
+ return "%s %s" % (self.jg_transposition.pgnSP(), ap.trNombre)
+ return None
+
+ def test_apertura(self):
+ if not hasattr(self, "apertura") or self.pendienteApertura:
+ self.asignaApertura()
+ self.asignaTransposition()
+
def pv_san(fen, pv):
p = Partida(fen=fen)
@@ -529,17 +553,11 @@ def readPGN(self, configuracion, pgn):
if not unpgn.leeTexto(pgn):
return None
self.recuperaDeTexto(unpgn.partida.guardaEnTexto())
- self.asignaApertura(configuracion)
+ self.asignaApertura()
self.liTags = unpgn.listaCabeceras()
return self
- def asignaApertura_raw(self, ap):
- ap.asignaApertura(self)
-
- def asignaApertura(self, configuracion):
- AperturasStd.ap.asignaApertura(self)
-
def pgn(self):
li = ['[%s "%s"]\n'%(k,v) for k,v in self.liTags]
txt = "".join(li)
diff --git a/Code/Presentacion.py b/Code/Presentacion.py
index 1634612..4cd4e7e 100644
--- a/Code/Presentacion.py
+++ b/Code/Presentacion.py
@@ -2,7 +2,7 @@
import time
import codecs
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import Util
from Code import ControlPosicion
diff --git a/Code/Procesador.py b/Code/Procesador.py
index 37a9a0d..85f8ed2 100644
--- a/Code/Procesador.py
+++ b/Code/Procesador.py
@@ -24,6 +24,7 @@
from Code import GestorMateMap
from Code import GestorMicElo
from Code import GestorCompeticion
+from Code import GestorOpeningLines
from Code import GestorPGN
from Code import GestorPerson
from Code import GestorRoutes
@@ -32,6 +33,7 @@
from Code import GestorPartida
from Code import GestorTorneo
from Code import Presentacion
+from Code import OpeningLines
from Code import GestorWashing
from Code import GestorPlayPGN
from Code.QT import DatosNueva
@@ -62,7 +64,7 @@
from Code.QT import QTVarios
from Code.QT import PantallaDatabase
from Code.QT import PantallaManualSave
-from Code.QT import WBDatabaseFEN
+from Code.QT import PantallaDatabaseFEN
from Code.QT import WOpeningGuide
from Code.QT import PantallaKibitzers
from Code.QT import POLines
@@ -180,6 +182,8 @@ def reset(self):
self.pantalla.activaJuego(False, False)
self.tablero.exePulsadoNum = None
self.tablero.ponPosicion(self.posicionInicial)
+ self.tablero.borraMovibles()
+ self.tablero.quitaFlechas()
self.pantalla.ajustaTam()
self.pantalla.ponTitulo()
self.pararMotores()
@@ -707,8 +711,6 @@ def trainingMap(self, mapa):
self.gestor.inicio(resp)
def tools(self):
- # self.openings()
- # return
menu = QTVarios.LCMenu(self.pantalla)
menu.opcion("juega_solo", _("Create your own game"), Iconos.JuegaSolo())
@@ -742,7 +744,7 @@ def tools(self):
menu1.separador()
menu1.opcion("bookguide", _("Personal Opening Guide"), Iconos.BookGuide())
menu1.separador()
- menu1.opcion("openings", _("Opening lines") + " [WORK IN PROGRESS]", Iconos.OpeningLines())
+ menu1.opcion("openings", _("Opening lines"), Iconos.OpeningLines())
menu.separador()
menu1 = menu.submenu(_("Engines"), Iconos.Motores())
@@ -790,12 +792,42 @@ def tools(self):
self.openings()
def openings(self):
- result = POLines.openingLines(self)
- if result:
- fichero, basepv, title = result
- POLines.study(self, fichero)
+ dicline = POLines.openingLines(self)
+ if dicline:
+ if "TRAIN" in dicline:
+ resp = "tr_%s" % dicline["TRAIN"]
+ else:
+ resp = POLines.study(self, dicline["file"])
+ if resp is None:
+ self.openings()
+ else:
+ pathFichero = os.path.join(self.configuracion.folderOpenings, dicline["file"])
+ if resp == "tr_sequential":
+ self.openingsTrainingSequential(pathFichero)
+ elif resp == "tr_static":
+ self.openingsTrainingStatic(pathFichero)
+ elif resp == "tr_positions":
+ self.openingsTrainingPositions(pathFichero)
+
+
+ def openingsTrainingSequential(self, pathFichero):
+ self.gestor = GestorOpeningLines.GestorOpeningLines(self)
+ self.gestor.inicio(pathFichero, "sequential", 0)
+
+ def openingsTrainingStatic(self, pathFichero):
+ dbop = OpeningLines.Opening(pathFichero)
+ num_linea = POLines.selectLine(self, dbop)
+ dbop.close()
+ if num_linea is not None:
+ self.gestor = GestorOpeningLines.GestorOpeningLines(self)
+ self.gestor.inicio(pathFichero, "static", num_linea)
+ else:
self.openings()
+ def openingsTrainingPositions(self, pathFichero):
+ self.gestor = GestorOpeningLines.GestorOpeningLinesPositions(self)
+ self.gestor.inicio(pathFichero)
+
def kibitzers(self):
w = PantallaKibitzers.WKibitzers(self.pantalla, self)
w.exec_()
@@ -819,7 +851,7 @@ def database(self):
# self.procesarAccion(k_terminar)
def databaseFEN(self): # TODO
- w = WBDatabaseFEN.WBDatabaseFEN(self.pantalla, self)
+ w = PantallaDatabaseFEN.WBDatabaseFEN(self.pantalla, self)
w.exec_()
def manual_save(self):
diff --git a/Code/QT/Delegados.py b/Code/QT/Delegados.py
index 115c22a..939989c 100644
--- a/Code/QT/Delegados.py
+++ b/Code/QT/Delegados.py
@@ -302,6 +302,31 @@ def paint(self, painter, option, index):
painter.restore()
+class PmIconosWeather(QtGui.QStyledItemDelegate):
+ def __init__(self, parent=None):
+ QtGui.QStyledItemDelegate.__init__(self, parent)
+
+ self.dicIconos = {
+ "0": Iconos.pmInvierno(),
+ "1": Iconos.pmLluvia(),
+ "2": Iconos.pmSolNubesLluvia(),
+ "3": Iconos.pmSolNubes(),
+ "4": Iconos.pmSol(),
+ }
+
+ def paint(self, painter, option, index):
+ pos = str(index.model().data(index, QtCore.Qt.DisplayRole))
+ if pos not in self.dicIconos:
+ if pos.isdigit():
+ pos = "4" if int(pos)> 4 else "0"
+ else:
+ return
+ painter.save()
+ painter.translate(option.rect.x(), option.rect.y())
+ painter.drawPixmap(4, 4, self.dicIconos[pos])
+ painter.restore()
+
+
class HTMLDelegate(QtGui.QStyledItemDelegate):
def paint(self, painter, option, index):
options = QtGui.QStyleOptionViewItemV4(option)
diff --git a/Code/QT/Iconos.py b/Code/QT/Iconos.py
index aab1f15..d6368d5 100644
--- a/Code/QT/Iconos.py
+++ b/Code/QT/Iconos.py
@@ -2057,31 +2057,37 @@ def Maps():
return QtGui.QIcon(pmMaps())
def pmSol():
- return PM(860091,866443)
+ return PM(860091,861017)
def Sol():
return QtGui.QIcon(pmSol())
def pmSolNubes():
- return PM(866443,872300)
+ return PM(861017,861880)
def SolNubes():
return QtGui.QIcon(pmSolNubes())
-def pmNubes():
- return PM(872300,875432)
+def pmSolNubesLluvia():
+ return PM(861880,862840)
-def Nubes():
- return QtGui.QIcon(pmNubes())
+def SolNubesLluvia():
+ return QtGui.QIcon(pmSolNubesLluvia())
-def pmTormenta():
- return PM(875432,880083)
+def pmLluvia():
+ return PM(862840,863679)
-def Tormenta():
- return QtGui.QIcon(pmTormenta())
+def Lluvia():
+ return QtGui.QIcon(pmLluvia())
+
+def pmInvierno():
+ return PM(863679,865255)
+
+def Invierno():
+ return QtGui.QIcon(pmInvierno())
def pmWords():
- return PM(880083,883868)
+ return PM(865255,869040)
def Words():
return QtGui.QIcon(pmWords())
@@ -2099,31 +2105,31 @@ def FixedElo():
return QtGui.QIcon(pmFixedElo())
def pmX_Microfono():
- return PM(883868,886321)
+ return PM(869040,871493)
def X_Microfono():
return QtGui.QIcon(pmX_Microfono())
def pmSoundTool():
- return PM(886321,888780)
+ return PM(871493,873952)
def SoundTool():
return QtGui.QIcon(pmSoundTool())
def pmImportar():
- return PM(888780,891448)
+ return PM(873952,876620)
def Importar():
return QtGui.QIcon(pmImportar())
def pmVoyager1():
- return PM(891448,893898)
+ return PM(876620,879070)
def Voyager1():
return QtGui.QIcon(pmVoyager1())
def pmTrain():
- return PM(893898,895268)
+ return PM(879070,880440)
def Train():
return QtGui.QIcon(pmTrain())
@@ -2141,67 +2147,67 @@ def Measure():
return QtGui.QIcon(pmMeasure())
def pmPlayGame():
- return PM(895268,899626)
+ return PM(880440,884798)
def PlayGame():
return QtGui.QIcon(pmPlayGame())
def pmScanner():
- return PM(899626,899967)
+ return PM(884798,885139)
def Scanner():
return QtGui.QIcon(pmScanner())
def pmMenos():
- return PM(899967,900492)
+ return PM(885139,885664)
def Menos():
return QtGui.QIcon(pmMenos())
def pmSchool():
- return PM(900492,901033)
+ return PM(885664,886205)
def School():
return QtGui.QIcon(pmSchool())
def pmLaw():
- return PM(901033,901649)
+ return PM(886205,886821)
def Law():
return QtGui.QIcon(pmLaw())
def pmLearnGame():
- return PM(901649,902082)
+ return PM(886821,887254)
def LearnGame():
return QtGui.QIcon(pmLearnGame())
def pmUniversity():
- return PM(902082,902502)
+ return PM(887254,887674)
def University():
return QtGui.QIcon(pmUniversity())
def pmLonghaul():
- return PM(902502,903428)
+ return PM(887674,888600)
def Longhaul():
return QtGui.QIcon(pmLonghaul())
def pmTrekking():
- return PM(903428,904122)
+ return PM(888600,889294)
def Trekking():
return QtGui.QIcon(pmTrekking())
def pmPassword():
- return PM(904122,904575)
+ return PM(889294,889747)
def Password():
return QtGui.QIcon(pmPassword())
def pmSQL_RAW():
- return PM(895268,899626)
+ return PM(880440,884798)
def SQL_RAW():
return QtGui.QIcon(pmSQL_RAW())
@@ -2219,128 +2225,158 @@ def Light():
return QtGui.QIcon(pmLight())
def pmLight32():
- return PM(904575,906275)
+ return PM(889747,891447)
def Light32():
return QtGui.QIcon(pmLight32())
def pmTOL():
- return PM(906275,906984)
+ return PM(891447,892156)
def TOL():
return QtGui.QIcon(pmTOL())
def pmUned():
- return PM(902082,902502)
+ return PM(887254,887674)
def Uned():
return QtGui.QIcon(pmUned())
def pmUwe():
- return PM(906984,907953)
+ return PM(892156,893125)
def Uwe():
return QtGui.QIcon(pmUwe())
def pmThinking():
- return PM(907953,908325)
+ return PM(893125,893497)
def Thinking():
return QtGui.QIcon(pmThinking())
def pmWashingMachine():
- return PM(908325,908988)
+ return PM(893497,894160)
def WashingMachine():
return QtGui.QIcon(pmWashingMachine())
def pmTerminal():
- return PM(908988,912532)
+ return PM(894160,897704)
def Terminal():
return QtGui.QIcon(pmTerminal())
def pmManualSave():
- return PM(912532,913115)
+ return PM(897704,898287)
def ManualSave():
return QtGui.QIcon(pmManualSave())
def pmSettings():
- return PM(913115,913553)
+ return PM(898287,898725)
def Settings():
return QtGui.QIcon(pmSettings())
def pmStrength():
- return PM(913553,914224)
+ return PM(898725,899396)
def Strength():
return QtGui.QIcon(pmStrength())
def pmSingular():
- return PM(914224,915079)
+ return PM(899396,900251)
def Singular():
return QtGui.QIcon(pmSingular())
def pmScript():
- return PM(915079,915648)
+ return PM(900251,900820)
def Script():
return QtGui.QIcon(pmScript())
def pmScriptFree():
- return PM(915648,916208)
+ return PM(900820,901380)
def ScriptFree():
return QtGui.QIcon(pmScriptFree())
def pmTexto():
- return PM(916208,919053)
+ return PM(901380,904225)
def Texto():
return QtGui.QIcon(pmTexto())
def pmLampara():
- return PM(919053,919762)
+ return PM(904225,904934)
def Lampara():
return QtGui.QIcon(pmLampara())
def pmFile():
- return PM(919762,922062)
+ return PM(904934,907234)
def File():
return QtGui.QIcon(pmFile())
def pmCalculo():
- return PM(922062,922988)
+ return PM(907234,908160)
def Calculo():
return QtGui.QIcon(pmCalculo())
def pmOpeningLines():
- return PM(922988,923666)
+ return PM(908160,908838)
def OpeningLines():
return QtGui.QIcon(pmOpeningLines())
def pmStudy():
- return PM(923666,924703)
+ return PM(908838,909875)
def Study():
return QtGui.QIcon(pmStudy())
def pmLichess():
- return PM(924703,925593)
+ return PM(909875,910765)
def Lichess():
return QtGui.QIcon(pmLichess())
def pmMiniatura():
- return PM(925593,926520)
+ return PM(910765,911692)
def Miniatura():
return QtGui.QIcon(pmMiniatura())
+def pmLocomotora():
+ return PM(911692,912473)
+
+def Locomotora():
+ return QtGui.QIcon(pmLocomotora())
+
+def pmPositions():
+ return PM(912473,914064)
+
+def Positions():
+ return QtGui.QIcon(pmPositions())
+
+def pmTrainSequential():
+ return PM(914064,915009)
+
+def TrainSequential():
+ return QtGui.QIcon(pmTrainSequential())
+
+def pmTrainStatic():
+ return PM(915009,915979)
+
+def TrainStatic():
+ return QtGui.QIcon(pmTrainStatic())
+
+def pmTrainPositions():
+ return PM(915979,916833)
+
+def TrainPositions():
+ return QtGui.QIcon(pmTrainPositions())
+
diff --git a/Code/QT/InfoBase.py b/Code/QT/InfoBase.py
index 7e35e1b..7a1f80d 100644
--- a/Code/QT/InfoBase.py
+++ b/Code/QT/InfoBase.py
@@ -61,8 +61,8 @@ def listaMotores(self, bloque):
["Rybka 2.3.2a 32-bit", "Vasik Rajlich", "http://rybkachess.com/"],
["Critter 1.6a 32bits", "Richard Vida", "http://www.vlasak.biz/critter/"],
["Texel 1.07", "Peter Österlund", "http://hem.bredband.net/petero2b/javachess/index.html#texel"],
- ["Stockfish 8", "Tord Romstad, Marco Costalba, Joona Kiiski", "http://stockfishchess.org/"],
- ["McBrain 4.0", "Michael Byrne (based on stockfish)", "https://github.com/MichaelB7/Stockfish/releases"],
+ ["Stockfish 9", "Tord Romstad, Marco Costalba, Joona Kiiski", "http://stockfishchess.org/"],
+ ["McBrain 9", "Michael Byrne", "https://github.com/MichaelB7/Stockfish/releases"],
["Gull 3", "Vadim Demichev", "https://sourceforge.net/projects/gullchess/"],
["Delfi 5.4", "Fabio Cavicchio", "http://www.msbsoftware.it/delfi/"],
# ["SmartThink 1.97", "Sergei S. Markoff", "http://genes1s.net/smarthink.php"],
@@ -124,7 +124,7 @@ def version(num, liBase, liResto):
return txt
# Version 11
- liBase = ["Alfonso Solbes", "Max Aloyau", "tico-tico", "Nils Andersson", "Bernhard", "Ed Smith", "Rob", "Giovanni di Maria", "vga", "Remes", "Péter Rabi"]
+ liBase = ["Alfonso Solbes", "Max Aloyau", "tico-tico", "Nils Andersson", "Bernhard", "Ed Smith", "Rob", "Giovanni di Maria", "vga", "Remes", "Péter Rabi", "Iñaki Rodriguez"]
liResto = ["Immortalchess forum",]
txt += version(11, liBase, liResto)
@@ -391,7 +391,7 @@ def Engines(self, orden):
txt += "
"
if "McBrain" in nombre:
txt += '%s (%s) | ' % (nombre, _("default"))
- txt += '%s | ' % autor
+ txt += '%s | ' % autor
else:
txt += "%s | " % nombre
txt += "%s | " % autor
@@ -425,7 +425,6 @@ def Programming(self):
(_("GUI"), "PyQt4 - GPL", "http://www.riverbankcomputing.co.uk"),
(_("Audio"), "PyAudio v0.2.4 - MIT License", "http://people.csail.mit.edu/hubert/pyaudio/"),
("psutil", _X(_("Created by %1"), "Giampaolo Rodola"), "http://code.google.com/p/psutil/"),
- ("pygal", _X(_("Created by %1"), "Kozea"), "http://pygal.org"),
("chardet", _X(_("Created by %1"), "Ian Cordasco"), "https://github.com/chardet/chardet"),
(_("Polyglot books"), _X(_("Based on work by %1"), "Michel Van den Bergh"), "http://alpha.uhasselt.be/Research/Algebra/Toga/book_format.html"),
("Polyglot1.4w", _X(_("Created by %1"), "Fabien Letouzy") + ". " + _X(_("Modified by %1"), "Fonzy Bluemers"), "http://www.geenvis.net/"),
diff --git a/Code/QT/POLAnalisis.py b/Code/QT/POLAnalisis.py
index 77d7f61..8a11eca 100644
--- a/Code/QT/POLAnalisis.py
+++ b/Code/QT/POLAnalisis.py
@@ -1,6 +1,6 @@
import os
-import LCEngine
+import LCEngineV1 as LCEngine
from PyQt4 import QtGui, QtCore
@@ -27,6 +27,9 @@ def __init__(self, tabsAnalisis, procesador, configuracion):
self.posicion = None
self.li_analysis = []
self.gestor_motor = None
+ self.current_mrm = None
+
+ self.dbop = tabsAnalisis.dbop
self.procesador = procesador
self.configuracion = configuracion
@@ -38,11 +41,16 @@ def __init__(self, tabsAnalisis, procesador, configuracion):
self.bt_stop.hide()
self.lb_engine = Controles.LB(self, _("Engine") + ":")
- liMotores = configuracion.comboMotoresCompleto()
- self.cb_engine = Controles.CB(self, liMotores, configuracion.tutor.clave).capturaCambiado(self.reset_motor)
-
+ liMotores = configuracion.comboMotoresCompleto() # (nombre, clave)
+ default = configuracion.tutor.clave
+ engine = self.dbop.getconfig("ENGINE", default)
+ if len([clave for nombre,clave in liMotores if clave==engine]) == 0:
+ engine = default
+ self.cb_engine = Controles.CB(self, liMotores, engine).capturaCambiado(self.reset_motor)
+
+ multipv = self.dbop.getconfig("ENGINE_MULTIPV", 10)
lb_multipv = Controles.LB(self, _("Multi PV")+": ")
- self.sb_multipv = Controles.SB(self, 10, 1, 500).tamMaximo(50)
+ self.sb_multipv = Controles.SB(self, multipv, 1, 500).tamMaximo(50)
self.lb_analisis = Controles.LB(self, "").ponFondoN("#C9D2D7").ponTipoLetra(puntos=configuracion.puntosPGN)
@@ -66,7 +74,19 @@ def __init__(self, tabsAnalisis, procesador, configuracion):
self.reset_motor()
+ def saveCurrent(self):
+ if self.current_mrm:
+ fenM2 = self.current_posicion.fenM2()
+ dic = self.dbop.getfenvalue(fenM2)
+ if "ANALISIS" in dic:
+ mrm_ant = dic["ANALISIS"]
+ if mrm_ant.getdepth0() > self.current_mrm.getdepth0():
+ return
+ dic["ANALISIS"] = self.current_mrm
+ self.dbop.setfenvalue(fenM2, dic)
+
def setData(self, label, posicion):
+ self.saveCurrent()
self.posicion = posicion
self.lb_analisis.ponTexto(label)
if self.analyzing:
@@ -76,8 +96,18 @@ def setData(self, label, posicion):
self.gestor_motor.ac_inicio(partida)
self.analyzing = True
QtCore.QTimer.singleShot(1000, self.lee_analisis)
+ else:
+ fenM2 = posicion.fenM2()
+ dic = self.dbop.getfenvalue(fenM2)
+ if "ANALISIS" in dic:
+ self.show_analisis(dic["ANALISIS"])
+ else:
+ self.li_analysis = []
+ self.grid_analysis.refresh()
def start(self):
+ self.current_mrm = None
+ self.current_posicion = None
self.sb_multipv.setDisabled(True)
self.cb_engine.setDisabled(True)
self.analyzing = True
@@ -98,6 +128,8 @@ def show_stop(self):
self.bt_stop.show()
def show_analisis(self, mrm):
+ self.current_mrm = mrm
+ self.current_posicion = self.posicion
li = []
for rm in mrm.liMultiPV:
partida = Partida.Partida(self.posicion)
@@ -112,7 +144,10 @@ def show_analisis(self, mrm):
pgn0 = lit[1]
pgn1 = " ".join(lit[2:])
- partida.ms_sol = pgn0, siBlancas, None, None, None, None, False, False
+ if self.siFigurines:
+ partida.ms_sol = pgn0, siBlancas, None, None, None, None, False, False
+ else:
+ partida.ms_sol = pgn0
partida.ms_pgn = pgn1
partida.ms_pdt = rm.abrTextoPDT()
li.append(partida)
@@ -126,6 +161,7 @@ def lee_analisis(self):
QtCore.QTimer.singleShot(2000, self.lee_analisis)
def stop(self):
+ self.saveCurrent()
self.sb_multipv.setDisabled(False)
self.cb_engine.setDisabled(False)
self.analyzing = False
@@ -134,6 +170,7 @@ def stop(self):
self.gestor_motor.ac_final(0)
def reset_motor(self):
+ self.saveCurrent()
clave = self.cb_engine.valor()
if not clave:
return
@@ -157,6 +194,10 @@ def gridDato(self, grid, fila, oColumna):
else:
return self.li_analysis[fila].ms_pgn
+ def saveConfig(self):
+ self.dbop.setconfig("ENGINE", self.cb_engine.valor())
+ self.dbop.setconfig("ENGINE_MULTIPV", self.sb_multipv.valor())
+
class TabBook(QtGui.QWidget):
def __init__(self, tabsanalisis, book, configuracion):
@@ -170,8 +211,10 @@ def __init__(self, tabsanalisis, book, configuracion):
book.polyglot()
self.li_moves = []
+ self.siFigurines = configuracion.figurinesPGN
+
oColumnas = Columnas.ListaColumnas()
- delegado = Delegados.EtiquetaPOS(True, siLineas=False) if configuracion.figurinesPGN else None
+ delegado = Delegados.EtiquetaPOS(True, siLineas=False) if self.siFigurines else None
for x in range(20):
oColumnas.nueva(x, "", 80, siCentrado=True, edicion = delegado)
self.grid_moves = Grid.Grid(self, oColumnas, siSelecFilas=True, siCabeceraMovible=False, siCabeceraVisible=False)
@@ -190,8 +233,11 @@ def gridDato(self, grid, fila, oColumna):
li = mv.dato
key = int(oColumna.clave)
pgn = li[key]
- siBlancas = " w " in mv.fen
- return pgn, siBlancas, None, None, None, None, False, True
+ if self.siFigurines:
+ siBlancas = " w " in mv.fen
+ return pgn, siBlancas, None, None, None, None, False, True
+ else:
+ return pgn
def gridDobleClick(self, grid, fila, oColumna):
self.lee_subnivel(fila)
@@ -201,7 +247,6 @@ def gridBotonDerecho(self, grid, fila, columna, modificadores):
self.borra_subnivel(fila)
self.grid_moves.refresh()
-
def setData(self, posicion):
self.posicion = posicion
self.start()
@@ -327,7 +372,7 @@ def __init__(self, panelOpening, procesador, configuracion):
self.tabs.tabCloseRequested.connect(self.tabCloseRequested)
layout = Colocacion.V()
- layout.control(self.tabs).margen(3)
+ layout.control(self.tabs).margen(0)
self.setLayout(layout)
def changedNextMove(self):
@@ -363,6 +408,7 @@ def creaTab(self):
pos = len(self.liTabs)-1
self.tabs.nuevaTab(tabbook, book.nombre, pos)
self.tabs.setTabIcon(pos, Iconos.Libros())
+ self.setPosicion(self.partida, self.njg, pos)
elif resp == "dbase":
nomfichgames = QTVarios.selectDB(self, self.configuracion, False, True)
if nomfichgames:
@@ -371,11 +417,14 @@ def creaTab(self):
self.liTabs.append((resp, tabdb))
pos = len(self.liTabs) - 1
self.setPosicion(self.partida, self.njg, pos)
- self.tabs.nuevaTab(tabdb, _("Database"), pos)
+ nombre = os.path.basename(nomfichgames)[:-4]
+ self.tabs.nuevaTab(tabdb, nombre, pos)
self.tabs.setTabIcon(pos, Iconos.Database())
self.tabs.activa(pos)
def setPosicion(self, partida, njg, numTab=None):
+ if partida is None:
+ return
jg = partida.jugada(njg)
self.partida = partida
self.njg = njg
@@ -403,7 +452,6 @@ def setPosicion(self, partida, njg, numTab=None):
tab.setData(data)
tab.start()
-
def seleccionaLibro(self):
listaLibros = Books.ListaLibros()
listaLibros.recuperaVar(self.configuracion.ficheroBooks)
@@ -426,7 +474,13 @@ def seleccionaLibro(self):
nombre = os.path.basename(fbin)[:-4]
book = Books.Libro("P", nombre, fbin, True)
listaLibros.nuevo(book)
+ listaLibros.guardaVar(self.configuracion.ficheroBooks)
else:
book = None
return book
+ def saveConfig(self):
+ for tipo, wtab in self.liTabs:
+ if tipo == "engine":
+ wtab.saveConfig()
+
diff --git a/Code/QT/POLBoard.py b/Code/QT/POLBoard.py
index df30935..d3d30f1 100644
--- a/Code/QT/POLBoard.py
+++ b/Code/QT/POLBoard.py
@@ -24,21 +24,31 @@ def __init__(self, panelOpening, configuracion):
self.panelOpening = panelOpening
self.dbop = panelOpening.dbop
+ self.partidabase = panelOpening.partidabase
+ self.num_jg_inicial = len(self.partidabase)
+ self.posJugada = self.num_jg_inicial
+
confTablero = configuracion.confTablero("POSLINES", 32)
self.tablero = Tablero.Tablero(self, confTablero)
self.tablero.crea()
self.tablero.ponerPiezasAbajo(True)
self.tablero.ponMensajero(self.mueveHumano)
self.tablero.dispatchSize(self.ajustaAncho)
+ self.tablero.dbVisual_setFichero(self.dbop.nomFichero)
+ self.tablero.dbVisual_setShowAllways(True)
+
+ self.dbop.setdbVisual_Tablero(self.tablero) # To close
self.intervalo = 1400
+ tipoLetra = Controles.TipoLetra(puntos=configuracion.puntosPGN)
+
lybt, bt = QTVarios.lyBotonesMovimiento(self, "", siTiempo=True, siLibre=False, tamIcon=24)
self.lbPGN = Controles.LB(self).ponWrap()
self.lbPGN.colocate = self.colocatePartida
self.lbPGN.setStyleSheet("QLabel{ border-style: groove; border-width: 2px; border-color: LightSlateGray; padding: 8px;}")
- self.lbPGN.ponTipoLetra(puntos=configuracion.puntosPGN)
+ self.lbPGN.ponFuente(tipoLetra)
self.lbPGN.setOpenExternalLinks(False)
def muestraPos(txt):
self.colocatePartida(int(txt))
@@ -68,19 +78,24 @@ def muestraPos(txt):
# Valoracion
liOpciones = [(tit[0], k, tit[1]) for k, tit in self.dicValoracion.iteritems()]
- self.lbValoracion = Controles.LB(self, _("Rating") + ":")
self.cbValoracion = Controles.CB(self, liOpciones, 0).capturaCambiado(self.cambiadoValoracion)
+ self.cbValoracion.ponFuente(tipoLetra)
# Ventaja
liOpciones = [(tit, k, icon) for k, (tit, icon) in self.dicVentaja.iteritems()]
self.cbVentaja = Controles.CB(self, liOpciones, 0).capturaCambiado(self.cambiadoVentaja)
+ self.cbVentaja.ponFuente(tipoLetra)
# Comentario
self.emComentario = Controles.EM(self, siHTML=False).capturaCambios(self.cambiadoComentario)
-
- lyVal = Colocacion.H().control(self.lbValoracion).control(self.cbValoracion).control(self.cbVentaja).relleno()
+ self.emComentario.ponFuente(tipoLetra)
+ self.emComentario.altoFijo(5*configuracion.altoFilaPGN)
+ lyVal = Colocacion.H().control(self.cbValoracion).control(self.cbVentaja)
lyEd = Colocacion.V().otro(lyVal).control(self.emComentario)
+ # Apertura
+ self.lbApertura = Controles.LB(self).alinCentrado().ponFuente(tipoLetra).ponWrap()
+
lyt = Colocacion.H().relleno().control(self.tablero).relleno()
lya = Colocacion.H().relleno().control(self.lbPGN).relleno()
@@ -90,6 +105,7 @@ def muestraPos(txt):
layout.otro(lybt)
layout.otro(lya)
layout.otro(lyEd)
+ layout.control(self.lbApertura)
layout.relleno()
self.setLayout(layout)
@@ -97,6 +113,8 @@ def muestraPos(txt):
self.siReloj = False
+ self.ponPartida(self.partidabase)
+
def analisis(self):
x = self.gb_analysis.isChecked()
if not x:
@@ -104,23 +122,17 @@ def analisis(self):
else:
self.wanalisis.show()
- def gridNumDatos(self, grid):
- return 0
-
- def reset_motor(self):
- pass
-
- def start(self):
- pass
-
- def stop(self):
- pass
-
- def ponPartidaBase(self, partida):
- self.num_jg_inicial = partida.numJugadas()-1
-
def ponPartida(self, partida):
+ partida.test_apertura()
self.partida = partida
+ rotulo = partida.rotuloApertura()
+ if rotulo is not None:
+ trans = partida.rotuloTransposition()
+ if trans is not None:
+ rotulo += "\n%s: %s" % (_("Transposition"), trans)
+ else:
+ rotulo = ""
+ self.lbApertura.ponTexto(rotulo)
def procesarTB(self):
getattr(self, self.sender().clave)()
@@ -153,7 +165,7 @@ def camposEdicion(self, siVisible):
self.emComentario.setVisible(siVisible)
def mueveHumano(self, desde, hasta, coronacion=""):
- cpActual = self.partida.jugada(self.posJugada).posicion
+ cpActual = self.partida.jugada(self.posJugada).posicion if self.posJugada >= 0 else self.partida.iniPosicion
if cpActual.siPeonCoronando(desde, hasta):
coronacion = self.tablero.peonCoronando(cpActual.siBlancas)
if coronacion is None:
@@ -177,20 +189,24 @@ def resetValues(self):
def colocatePartida(self, pos):
self.fenM2 = None
- if not self.partida.numJugadas():
+ num_jugadas = self.partida.numJugadas()
+ if num_jugadas == 0:
+ self.posJugada = -1
self.lbPGN.ponTexto("")
self.tablero.ponPosicion(self.partida.iniPosicion)
self.resetValues()
+ self.activaPiezas()
return
- lh = self.partida.numJugadas() - 1
- if pos >= lh:
+ if pos >= num_jugadas:
self.siReloj = False
- pos = lh
+ pos = num_jugadas - 1
+ elif pos < self.num_jg_inicial-1:
+ pos = self.num_jg_inicial-1
p = self.partida
- numJugada = p.primeraJugada()
+ numJugada = 1
pgn = ""
style_number = "color:teal; font-weight: bold;"
style_moves = "color:black;"
@@ -201,7 +217,7 @@ def colocatePartida(self, pos):
pgn += '%d.' % (style_number, numJugada)
numJugada += 1
- xp = jg.pgnHTML() if self.siFigurines else jg.pgnSP()
+ xp = jg.pgnHTML(self.siFigurines)
if n == pos:
xp = '%s' % (style_select, xp)
else:
@@ -216,13 +232,15 @@ def colocatePartida(self, pos):
if pos < 0:
self.tablero.ponPosicion(self.partida.iniPosicion)
self.resetValues()
+ self.activaPiezas()
return
jugada = self.partida.jugada(self.posJugada)
- posicion = jugada.posicion
+ posicion = jugada.posicion if jugada else self.partida.iniPosicion
self.tablero.ponPosicion(posicion)
- self.tablero.ponFlechaSC(jugada.desde, jugada.hasta)
+ if jugada:
+ self.tablero.ponFlechaSC(jugada.desde, jugada.hasta)
self.fenM2 = posicion.fenM2()
dic = self.dbop.getfenvalue(self.fenM2)
@@ -242,14 +260,16 @@ def colocatePartida(self, pos):
def activaPiezas(self):
self.tablero.desactivaTodas()
- if not self.siReloj and self.posJugada >= self.num_jg_inicial:
- jg = self.partida.jugada(self.posJugada)
- self.tablero.activaColor(not jg.siBlancas())
+ if not self.siReloj and self.posJugada >= self.num_jg_inicial-1:
+ if self.posJugada >= 0:
+ jg = self.partida.jugada(self.posJugada)
+ color = not jg.siBlancas()
+ else:
+ color = True
+ self.tablero.activaColor(color)
def MoverInicio(self):
- self.posJugada = -1
- posicion = self.partida.iniPosicion
- self.tablero.ponPosicion(posicion)
+ self.colocatePartida(0)
def MoverAtras(self):
self.colocatePartida(self.posJugada - 1)
diff --git a/Code/QT/POLines.py b/Code/QT/POLines.py
index 4e1de80..2c7b6f7 100644
--- a/Code/QT/POLines.py
+++ b/Code/QT/POLines.py
@@ -1,13 +1,14 @@
import os.path
+import copy
-from PyQt4 import QtCore
+from PyQt4 import QtCore, QtGui
+from Code import Util
from Code import Partida
from Code import OpeningLines
from Code.QT import Colocacion
from Code.QT import Columnas
from Code.QT import Controles
-from Code.QT import FormLayout
from Code.QT import Grid
from Code.QT import Iconos
from Code.QT import PantallaAperturas
@@ -18,6 +19,7 @@
from Code.QT import POLBoard
from Code.QT import POLAnalisis
from Code.QT import Voyager
+from Code.QT import FormLayout
class WOpeningLines(QTVarios.WDialogo):
@@ -34,9 +36,9 @@ def __init__(self, procesador):
oColumnas = Columnas.ListaColumnas()
oColumnas.nueva("TITLE", _("Name"), 240)
oColumnas.nueva("BASEPV", _("First moves"), 280)
+ oColumnas.nueva("NUMLINES", _("Lines"), 80, siCentrado=True)
oColumnas.nueva("FILE", _("File"), 200)
self.glista = Grid.Grid(self, oColumnas, siSelecFilas=True)
- self.glista.setMinimumWidth(self.glista.anchoColumnas() + 20)
liAcciones = (
(_("Close"), Iconos.MainMenu(), self.terminar), None,
@@ -45,17 +47,58 @@ def __init__(self, procesador):
(_("Up"), Iconos.Arriba(), self.arriba),
(_("Down"), Iconos.Abajo(), self.abajo), None,
(_("Remove"), Iconos.Borrar(), self.borrar), None,
+ (_("Reinit"), Iconos.Reiniciar(), self.reiniciar), None,
)
tb = Controles.TBrutina(self, liAcciones)
+ sp = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
+ tb.setSizePolicy(sp)
+
+ liAcciones = (
+ (_("Sequential"), Iconos.TrainSequential(), self.tr_sequential), None,
+ (_("Static"), Iconos.TrainStatic(), self.tr_static), None,
+ (_("Positions"), Iconos.TrainPositions(), self.tr_positions),
+ )
+ tbtrain = Controles.TBrutina(self, liAcciones, siTexto=False)
+
+ lbtrain = Controles.LB(self, _("Trainings")).alinCentrado().ponFondoN("lightgray")
+ lytrain = Colocacion.V().control(lbtrain).control(tbtrain).margen(0)
+ self.wtrain = QtGui.QWidget()
+ self.wtrain.setLayout(lytrain)
+
# Colocamos
- ly = Colocacion.V().control(tb).control(self.glista).margen(3)
+
+ lytb = Colocacion.H().control(tb).control(self.wtrain)
+ ly = Colocacion.V().otro(lytb).control(self.glista).margen(3)
self.setLayout(ly)
self.registrarGrid(self.glista)
self.recuperarVideo()
+ self.wtrain.setVisible(False)
+ self.glista.gotop()
+
+ def tr_(self, tipo):
+ recno = self.glista.recno()
+ op = self.listaOpenings[recno]
+ op["TRAIN"] = tipo
+ self.resultado = op
+ self.guardarVideo()
+ self.accept()
+
+ def tr_sequential(self):
+ self.tr_("sequential")
+
+ def tr_static(self):
+ self.tr_("static")
+
+ def tr_positions(self):
+ self.tr_("positions")
+
+ def reiniciar(self):
+ self.listaOpenings.reiniciar()
+ self.glista.refresh()
self.glista.gotop()
def arriba(self):
@@ -98,24 +141,19 @@ def new(self):
if si_expl:
QTUtil2.mensaje(self, _("Secondly you have to choose a name for this opening studio."))
- while True:
- liGen = [(None, None)]
- liGen.append((_("Opening studio name") + ":", name))
- resultado = FormLayout.fedit(liGen, title=_("Opening studio name"), parent=self, icon=Iconos.OpeningLines(), anchoMinimo=460)
- if resultado:
- accion, liResp = resultado
- name = liResp[0]
- if name:
- file = self.listaOpenings.select_filename(name)
- break
- else:
- return
- else:
- return
- self.listaOpenings.new(file, pv, name)
- self.glista.gobottom()
- self.glista.refresh()
+ liGen = [(None, None)]
+ liGen.append((_("Opening studio name") + ":", name))
+ resultado = FormLayout.fedit(liGen, title=_("Opening studio name"), parent=self, icon=Iconos.OpeningLines(), anchoMinimo=460)
+ if resultado:
+ accion, liResp = resultado
+ name = liResp[0]
+ if name:
+ file = self.listaOpenings.select_filename(name)
+ self.listaOpenings.new(file, pv, name)
+ self.resultado = self.listaOpenings[-1]
+ self.guardarVideo()
+ self.accept()
def borrar(self):
li = self.glista.recnosSeleccionados()
@@ -123,7 +161,7 @@ def borrar(self):
mens = _("Do you want to delete all selected records?")
mens += "\n"
for num, fila in enumerate(li, 1):
- mens += "\n%d. %s" % (num, self.listaOpenings[fila][2])
+ mens += "\n%d. %s" % (num, self.listaOpenings[fila]["title"])
if QTUtil2.pregunta(self, mens):
li.sort(reverse=True)
for fila in li:
@@ -137,14 +175,16 @@ def gridDato(self, grid, fila, oColumna):
col = oColumna.clave
op = self.listaOpenings[fila]
if col == "TITLE":
- return op[2]
+ return op["title"]
elif col == "FILE":
- return op[0]
+ return op["file"]
+ elif col == "NUMLINES":
+ return op["lines"]
elif col == "BASEPV":
- pv = op[1]
+ pv = op["pv"]
if pv:
p = Partida.Partida()
- p.leerPV(op[1])
+ p.leerPV(pv)
return p.pgnBaseRAW()
else:
return ""
@@ -154,6 +194,14 @@ def gridPonValor(self, grid, fila, columna, valor):
if valor:
self.listaOpenings.change_title(fila, valor)
+ def gridCambiadoRegistro(self, grid, fila, columna):
+ ok = False
+ if fila >= 0:
+ op = self.listaOpenings[fila]
+ ok = op["withtrainings"]
+
+ self.wtrain.setVisible(ok)
+
def closeEvent(self, event): # Cierre con X
self.guardarVideo()
@@ -162,30 +210,31 @@ def terminar(self):
self.reject()
-class WStudy(QTVarios.WDialogo):
+class WLines(QTVarios.WDialogo):
def __init__(self, procesador, dbop):
-
self.dbop = dbop
title = dbop.gettitle()
- QTVarios.WDialogo.__init__(self, procesador.pantalla, title, Iconos.Study(), "studyOpening")
+ QTVarios.WDialogo.__init__(self, procesador.pantalla, title, Iconos.OpeningLines(), "studyOpening")
self.procesador = procesador
self.configuracion = procesador.configuracion
self.partidabase = self.dbop.getpartidabase()
self.num_jg_inicial = self.partidabase.numJugadas()
+ self.num_jg_actual = None
self.partida = None
+
+ self.resultado = None
siFigurinesPGN = self.configuracion.figurinesPGN
liAcciones = (
(_("Close"), Iconos.MainMenu(), self.terminar), None,
- # (_("New"), Iconos.Nuevo(), self.new), None,
(_("Remove"), Iconos.Borrar(), self.borrar), None,
- # (_("Train"), Iconos.Study(), self.train), None,
- (_("Voyager 2"), Iconos.Voyager1(), self.voyager2), None,
- (_("Import"), Iconos.Mezclar(), self.importar), None
+ (_("Import"), Iconos.Mezclar(), self.importar), None,
+ (_("Utilities"), Iconos.Utilidades(), self.utilidades), None,
+ (_("Train"), Iconos.Study(), self.train), None,
)
- self.tb = tb = Controles.TBrutina(self, liAcciones)
+ self.tb = Controles.TBrutina(self, liAcciones)
oColumnas = Columnas.ListaColumnas()
oColumnas.nueva("LINE", _("Line"), 35, edicion=Delegados.EtiquetaPOS(False, True))
@@ -199,110 +248,352 @@ def __init__(self, procesador, dbop):
self.glines.ponAltoFila(self.configuracion.altoFilaPGN)
self.pboard = POLBoard.BoardLines(self, self.configuracion)
- self.pboard.ponPartidaBase(self.partidabase)
- self.pboard.ponPartida(self.partidabase)
self.tabsanalisis = POLAnalisis.TabsAnalisis(self, self.procesador, self.configuracion)
- lyg = Colocacion.H().control(self.tabsanalisis).margen(3)
- self.gb_analysis = Controles.GB(self, _("Analysis"), lyg)
- self.gb_analysis.conectar(self.analisis)
- self.gb_analysis.setChecked(True)
-
- lyLV = Colocacion.V().control(self.glines).control(self.gb_analysis)
- ly1 = Colocacion.H().control(self.pboard).otro(lyLV)
- layout = Colocacion.V().control(tb).otro(ly1)
+
+ splitter = QtGui.QSplitter(self)
+ splitter.setOrientation(QtCore.Qt.Vertical)
+ splitter.addWidget(self.glines)
+ splitter.addWidget(self.tabsanalisis)
+
+ sp = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
+ splitter.setSizePolicy(sp)
+
+ self.registrarSplitter(splitter, "SPLITTER")
+
+ lyLV = Colocacion.V().control(splitter)
+ lyTB = Colocacion.V().control(self.tb).control(self.pboard)
+ layout = Colocacion.H().otro(lyTB).otro(lyLV).margen(3)
self.setLayout(layout)
self.colorPar = QTUtil.qtColor("#DBDAD9")
self.colorNon = QTUtil.qtColor("#F1EFE9")
self.colorLine = QTUtil.qtColor("#CDCCCB")
- self.analisis()
self.partida = self.partidabase
+
self.pboard.MoverFinal()
self.recuperarVideo()
- def voyager2(self):
+ def utilidades(self):
+ menu = QTVarios.LCMenu(self)
+ submenu = menu.submenu(_("Analysis"), Iconos.Analizar())
+ submenu.opcion(self.ta_massive, _("Mass analysis"), Iconos.Analizar())
+ submenu.separador()
+ submenu.opcion(self.ta_remove, _("Delete all previous analysis"), Iconos.Delete())
+ menu.separador()
+ resp = menu.lanza()
+ if resp:
+ resp()
+
+ def ta_massive(self):
+ dicVar = self.configuracion.leeVariables("MASSIVE_OLINES")
+
+ liGen = [FormLayout.separador]
+
+ config = FormLayout.Combobox(_("Engine"), self.configuracion.comboMotoresMultiPV10(4))
+ liGen.append((config, dicVar.get("ENGINE", self.configuracion.tutor)))
+
+ liGen.append((_("Duration of engine analysis (secs)") + ":", dicVar.get("SEGUNDOS", float(self.configuracion.tiempoTutor / 1000.0))))
+ liDepths = [("--", 0)]
+ for x in range(1, 51):
+ liDepths.append((str(x), x))
+ config = FormLayout.Combobox(_("Depth"), liDepths)
+ liGen.append((config, dicVar.get("DEPTH", self.configuracion.depthTutor)))
+
+ li = [(_("Maximum"), 0)]
+ for x in (1, 3, 5, 10, 15, 20, 30, 40, 50, 75, 100, 150, 200):
+ li.append((str(x), x))
+ config = FormLayout.Combobox(_("Number of moves evaluated by engine(MultiPV)"), li)
+ liGen.append((config, dicVar.get("MULTIPV", self.configuracion.tutorMultiPV)))
+
+ liGen.append(FormLayout.separador)
+ liGen.append((_("Redo any existing prior analyses (if they exist)") + ":", dicVar.get("REDO", False)))
+
+ resultado = FormLayout.fedit(liGen, title=_("Mass analysis"), parent=self, anchoMinimo=460,
+ icon=Iconos.Analizar())
+ if resultado is None:
+ return
+
+ claveMotor, tiempo, depth, multiPV, redo = resultado[1]
+ ms = int(tiempo * 1000)
+ if ms == 0 and depth == 0:
+ return
+
+ dicVar["ENGINE"] = claveMotor
+ dicVar["SEGUNDOS"] = tiempo
+ dicVar["DEPTH"] = depth
+ dicVar["MULTIPV"] = multiPV
+ dicVar["REDO"] = redo
+ self.configuracion.escVariables("MASSIVE_OLINES", dicVar)
+
+ um = QTUtil2.unMomento(self)
+ stFensM2 = self.dbop.getAllFen()
+ if redo == False:
+ liBorrar = []
+ for fenM2 in stFensM2:
+ dic = self.dbop.getfenvalue(fenM2)
+ if "ANALISIS" in dic:
+ liBorrar.append(fenM2)
+ for fenM2 in liBorrar:
+ stFensM2.remove(fenM2)
+
+ conf_engine = copy.deepcopy(self.configuracion.buscaMotor(claveMotor))
+ conf_engine.actMultiPV(multiPV)
+ xgestor = self.procesador.creaGestorMotor(conf_engine, ms, depth, True)
+
+ um.final()
+
+ mensaje = _("Move") + " %d/" + str(len(stFensM2))
+ tmpBP = QTUtil2.BarraProgreso(self, _("Mass analysis"), "", len(stFensM2))
+
+ done = 0
+
+ for n, fenM2 in enumerate(stFensM2, 1):
+
+ if tmpBP.siCancelado():
+ break
+
+ tmpBP.inc()
+ tmpBP.mensaje(mensaje % n)
+
+ mrm = xgestor.analiza(fenM2 + " 0 1")
+ dic = self.dbop.getfenvalue(fenM2)
+ dic["ANALISIS"] = mrm
+ self.dbop.setfenvalue(fenM2, dic)
+ done += 1
+
+ tmpBP.cerrar()
+
+ def ta_remove(self):
+ if QTUtil2.pregunta(self, _("Are you sure?")):
+ total = len(self.dbop.db_fenvalues)
+ mensaje = _("Move") + " %d/" + str(total)
+ tmpBP = QTUtil2.BarraProgreso(self, "", "", total)
+ self.dbop.removeAnalisis(tmpBP, mensaje)
+ tmpBP.cerrar()
+ self.glines.refresh()
+
+
+ def train(self):
+ if self.train_test():
+ menu = QTVarios.LCMenu(self)
+ menu.opcion("tr_sequential", _("Sequential"), Iconos.TrainSequential())
+ menu.separador()
+ menu.opcion("tr_static", _("Static"), Iconos.TrainStatic())
+ menu.separador()
+ menu.opcion("tr_positions", _("Positions"), Iconos.TrainPositions())
+ menu.separador()
+ submenu = menu.submenu(_("Configuration"), Iconos.Configurar())
+ submenu.opcion("update", _("Update current trainings"), Iconos.Reindexar())
+ submenu.separador()
+ submenu.opcion("new", _("Re-create all trainings"), Iconos.Modificar())
+ resp = menu.lanza()
+ if resp is None:
+ return
+ if resp.startswith("tr_"):
+ self.resultado = resp
+ self.accept()
+ elif resp == "new":
+ self.trainNew()
+ elif resp == "update":
+ self.trainUpdate()
+
+ def train_test(self):
+ if len(self.dbop) == 0:
+ return False
+ training = self.dbop.training()
+ if training is None:
+ return self.trainNew()
+ return True
+
+ def trainNew(self):
+ training = self.dbop.training()
+ if training is None:
+ color = "WHITE"
+ random_order = False
+ max_moves = 0
+ else:
+ color = training["COLOR"]
+ random_order = training["RANDOM"]
+ max_moves = training["MAXMOVES"]
+
+ liGen = [(None, None)]
+
+ liJ = [(_("White"), "WHITE"), (_("Black"), "BLACK")]
+ config = FormLayout.Combobox(_("Play with"), liJ)
+ liGen.append((config, color))
+
+ liGen.append((None, None))
+ liGen.append((_("Random order"), random_order))
+
+ liGen.append((None, None))
+ liGen.append((_("Maximum number of moves (0=all)"), max_moves))
+
+ resultado = FormLayout.fedit(liGen, title=_("New training"), parent=self, anchoMinimo=360, icon=Iconos.Study())
+ if resultado is None:
+ return
+
+ accion, liResp = resultado
+
+ reg = {}
+
+ reg["COLOR"], reg["RANDOM"], reg["MAXMOVES"] = liResp
+
+ self.dbop.createTraining(reg, self.configuracion)
+
+ QTUtil2.mensaje(self, _("The trainings of this opening has been created"))
+
+ def trainUpdate(self):
+ self.dbop.updateTraining()
+ QTUtil2.mensaje(self, _("The trainings have been updated"))
+
+ def addPartida(self, partida):
+ if partida.pv().startswith(self.partidabase.pv()):
+ siNueva, num_linea, siAppend = self.dbop.posPartida(partida)
+ if siNueva:
+ self.dbop.append(partida)
+ else:
+ if siAppend:
+ self.dbop[num_linea] = partida
+ self.glines.refresh()
+ else:
+ QTUtil2.mensError(self, _X("New line must begin with %1", self.partidabase.pgnSP()))
+
+ def partidaActual(self):
partida = Partida.Partida()
- partida.leeOtra(self.partidabase)
- ptxt = Voyager.voyagerPartida(self.owner, partida)
+ numcol = self.glines.posActualN()[1]
+ partida.leeOtra(self.partida if self.partida and numcol> 0 else self.partidabase)
+ if self.num_jg_actual is not None \
+ and self.num_jg_inicial <= self.num_jg_actual < len(partida):
+ partida.liJugadas = partida.liJugadas[:self.num_jg_actual+1]
+ partida.ultPosicion = partida.jugada(-1).posicion
+ return partida
+
+ def voyager2(self, partida):
+ ptxt = Voyager.voyagerPartida(self, partida)
if ptxt:
partida = Partida.Partida()
partida.recuperaDeTexto(ptxt)
- if self.partidabase.pv() in partida.pv():
- siNueva, num_linea, siAppend = self.dbop.posPartida(partida)
- if siNueva:
- self.dbop.append(partida)
- else:
- if siAppend:
- self.dbop[num_linea] = partida
- self.glines.refresh()
- else:
- QTUtil2.mensError(self, _X("New line must begin with %1", self.partidabase.pgnSP()))
+ self.addPartida(partida)
def importar(self):
menu = QTVarios.LCMenu(self)
- liOp = self.dbop.getOtras(self.configuracion)
- if liOp:
- otra = menu.submenu(_("Other line openings"), Iconos.OpeningLines())
- for fichero, titulo in liOp:
- otra.opcion(("ol", fichero), titulo, Iconos.PuntoVerde())
+ def haz_menu(frommenu, part):
+ liOp = self.dbop.getOtras(self.configuracion, part)
+ if liOp:
+ otra = frommenu.submenu(_("Other opening lines"), Iconos.OpeningLines())
+ for fichero, titulo in liOp:
+ otra.opcion(("ol", (fichero, part)), titulo, Iconos.PuntoVerde())
+ frommenu.separador()
+ frommenu.opcion(("pgn", part), _("PGN with variants"), Iconos.Tablero())
+ frommenu.separador()
+ frommenu.opcion(("polyglot", part), _("Polyglot book"), Iconos.Libros())
+ frommenu.separador()
+ frommenu.opcion(("summary", part), _("Database summary"), Iconos.DatabaseC())
+ frommenu.separador()
+ frommenu.opcion(("voyager2", part), _("Voyager 2"), Iconos.Voyager1())
+ frommenu.separador()
+ frommenu.opcion(("opening", part), _("Opening"), Iconos.Apertura())
+
+ partida = self.partidaActual()
+ if len(partida) > len(self.partidabase):
+ sub1 = menu.submenu(_("From current position"), Iconos.MoverLibre())
+ haz_menu(sub1, partida)
menu.separador()
- menu.opcion(("pgn", None), _("PGN with variants"), Iconos.Tablero())
- menu.separador()
- menu.opcion(("polyglot", None), _("Polyglot book"), Iconos.Libros())
- menu.separador()
- menu.opcion(("summary", None), _("Database summary"), Iconos.DatabaseC())
- menu.separador()
+ sub2 = menu.submenu(_("From base position"), Iconos.MoverInicio())
+ haz_menu(sub2, self.partidabase)
+ else:
+ haz_menu(menu, self.partidabase)
+
resp = menu.lanza()
if resp is None:
return
- tipo, arg = resp
+ tipo, partida = resp
if tipo == "pgn" :
- self.importarPGN()
+ self.importarPGN(partida)
elif tipo == "polyglot":
- self.importarPolyglot()
+ self.importarPolyglot(partida)
elif tipo == "summary":
- pass
+ self.importarSummary(partida)
+ elif tipo == "voyager2":
+ self.voyager2(partida)
+ elif tipo == "opening":
+ self.importarApertura(partida)
elif tipo == "ol":
- pass
-
- def importarPolyglot(self):
- previo = self.configuracion.leeVariables("WBG_MOVES")
- carpeta = previo.get("CARPETABIN", "")
+ fichero, partida = partida
+ self.importarOtra(fichero, partida)
+
+ def importarOtra(self, fichero, partida):
+ um = QTUtil2.unMomento(self)
+ pathFichero = os.path.join(self.configuracion.folderOpenings, fichero)
+ self.dbop.importarOtra(pathFichero, partida)
+ um.final()
+ self.glines.refresh()
+ self.glines.gotop()
- ficheroBIN = QTUtil2.leeFichero(self, carpeta, "%s (*.bin)" % _("Polyglot book"), titulo=_("File to import"))
- if not ficheroBIN:
- return
- previo["CARPETABIN"] = os.path.dirname(ficheroBIN)
- self.configuracion.escVariables("WBG_MOVES", previo)
+ def importarApertura(self, partida):
+ partida.asignaApertura()
+ w = PantallaAperturas.WAperturas(self, self.configuracion, partida.apertura)
+ if w.exec_():
+ ap = w.resultado()
+ partida = Partida.Partida()
+ partida.leerPV(ap.a1h8)
+ self.addPartida(partida)
+ def importarLeeParam(self, titulo, dicData):
liGen = [(None, None)]
liGen.append((None, _("Select a maximum number of moves (plies)
to consider from each game")))
-
- liGen.append((FormLayout.Spinbox(_("Depth"), 3, 99, 50), 30))
- liGen.append((None, None))
-
- liGen.append((_("Only white best moves"), False))
+ liGen.append((FormLayout.Spinbox(_("Depth"), 3, 99, 50), dicData.get("DEPTH", 30)))
liGen.append((None, None))
- liGen.append((_("Only black best moves"), False))
+ li = [(_("Only white best moves"), True), (_("Only black best moves"), False)]
+ config = FormLayout.Combobox(_("Moves"), li)
+ liGen.append((config, dicData.get("SIWHITE", True)))
liGen.append((None, None))
- resultado = FormLayout.fedit(liGen, title=os.path.basename(ficheroBIN), parent=self, anchoMinimo=360,
- icon=Iconos.PuntoNaranja())
-
+ resultado = FormLayout.fedit(liGen, title=titulo, parent=self, anchoMinimo=360, icon=Iconos.PuntoNaranja())
if resultado:
accion, liResp = resultado
- depth, whiteBest, blackBest = liResp
- self.dbop.grabarPolyglot(self, ficheroBIN, depth, whiteBest, blackBest)
+ depth, siWhite = liResp
+ dicData["DEPTH"] = depth
+ dicData["SIWHITE"] = siWhite
+ self.configuracion.escVariables("WBG_MOVES", dicData)
+ return dicData
+ return None
+
+ def importarSummary(self, partida):
+ nomfichgames = QTVarios.selectDB(self, self.configuracion, False, True)
+ if nomfichgames:
+ previo = self.configuracion.leeVariables("OPENINGLINES")
+ dicData = self.importarLeeParam(_("Database summary"), previo)
+ if dicData:
+ ficheroSummary = nomfichgames + "_s1"
+ depth, siWhite = dicData["DEPTH"], dicData["SIWHITE"]
+ self.dbop.importarSummary(self, partida, ficheroSummary, depth, siWhite)
+ self.glines.refresh()
+ self.glines.gotop()
+
+ def importarPolyglot(self):
+ dicData = self.configuracion.leeVariables("OPENINGLINES")
+ carpeta = dicData.get("CARPETABIN", "")
+
+ ficheroBIN = QTUtil2.leeFichero(self, carpeta, "%s (*.bin)" % _("Polyglot book"), titulo=_("File to import"))
+ if not ficheroBIN:
+ return
+
+ dicData["CARPETABIN"] = os.path.dirname(ficheroBIN)
+ dicData = self.importarLeeParam(dicData)
+ if dicData:
+ depth, siWhite = dicData["DEPTH"], dicData["SIWHITE"]
+ self.dbop.importarPolyglot(self, ficheroBIN, depth, siWhite)
self.glines.refresh()
self.glines.gotop()
- def importarPGN(self):
+ def importarPGN(self, partida):
previo = self.configuracion.leeVariables("OPENINGLINES")
carpeta = previo.get("CARPETAPGN", "")
@@ -326,23 +617,16 @@ def importarPGN(self):
accion, liResp = resultado
depth = liResp[0]
- self.dbop.grabarPGN(self, ficheroPGN, depth)
+ self.dbop.importarPGN(self, partida, ficheroPGN, depth)
self.glines.refresh()
self.glines.gotop()
- def analisis(self):
- x = self.gb_analysis.isChecked()
- if not x:
- self.tabsanalisis.hide()
- else:
- self.tabsanalisis.show()
-
def gridColorFondo(self, grid, fila, oColumna):
col = oColumna.clave
- linea = fila//2
if col == "LINE":
return self.colorLine
else:
+ linea = fila // 2
return self.colorPar if linea % 2 == 0 else self.colorNon
def gridCambiadoRegistro(self, grid, fila, oColumna):
@@ -355,7 +639,8 @@ def gridCambiadoRegistro(self, grid, fila, oColumna):
if not iswhite:
njug += 1
else:
- njug = self.partida.numJugadas()-1
+ njug = None
+ self.num_jg_actual = njug
self.pboard.ponPartida(self.partida)
self.pboard.colocatePartida(njug)
self.glines.setFocus()
@@ -415,8 +700,12 @@ def gridNumDatos(self, grid):
return len(self.dbop)*2
def gridTeclaControl(self, grid, k, siShift, siControl, siAlt):
- if k == QtCore.Qt.Key_Delete:
- self.borrar_move()
+ if k in (QtCore.Qt.Key_Delete, QtCore.Qt.Key_Backspace):
+ fila, col = self.glines.posActual()
+ if col.clave == "LINE":
+ self.borrar()
+ else:
+ self.borrar_move()
def borrar_move(self):
fila, col = self.glines.posActual()
@@ -438,7 +727,8 @@ def borrar_move(self):
if njug == self.num_jg_inicial:
return self.borrar()
- if QTUtil2.pregunta(self, _("Do you want to eliminate this move?")):
+ siUltimo = njug == len(partida)-1 # si es el ultimo no se pregunta
+ if siUltimo or QTUtil2.pregunta(self, _("Do you want to eliminate this move?")):
partida.liJugadas = partida.liJugadas[:njug]
partida.ultPosicion = partida.jugada(-1).posicion
self.dbop[linea] = partida
@@ -446,12 +736,75 @@ def borrar_move(self):
self.goto_finlinea()
def borrar(self):
- fila = self.glines.recno()
- linea = fila//2
- if 0 <= linea < len(self.dbop):
- if QTUtil2.pregunta(self, _X("Do you want to remove line %1", str(linea+1))):
- del self.dbop[linea]
- self.goto_finlinea()
+ tam_dbop = len(self.dbop)
+ if tam_dbop == 0:
+ return
+ current = self.glines.recno()//2
+ li = []
+ if 0 <= current < tam_dbop:
+ li.append(["current", _("Remove line %d") % (current+1,), Iconos.Mover()])
+ if tam_dbop > 1:
+ li.append(["lines", _("Remove a list of lines"), Iconos.MoverLibre()])
+
+ if len(li) > 0:
+ menu = QTVarios.LCMenu(self)
+ for key, title, ico in li:
+ menu.opcion(key, title, ico)
+ menu.separador()
+ resp = menu.lanza()
+
+ if resp == "current":
+ del self.dbop[current]
+ self.goto_inilinea()
+
+ else:
+ liGen = [FormLayout.separador]
+ config = FormLayout.Editbox("" + _("Lines") + "
" +
+ _("By example:") + " -5,8-12,14,19-",
+ rx="[0-9,\-,\,]*")
+ liGen.append((config, ""))
+ resultado = FormLayout.fedit(liGen, title=_("Remove a list of lines"), parent=self, anchoMinimo=460, icon=Iconos.OpeningLines())
+ if resultado:
+ accion, liResp = resultado
+ clista = liResp[0]
+ if clista:
+ ln = Util.ListaNumerosImpresion(clista)
+ li = ln.selected(range(1, tam_dbop+1))
+ sli = []
+ cad = ""
+ for num in li:
+ if cad:
+ cad += "," + str(num)
+ else:
+ cad = str(num)
+ if len(cad) > 80:
+ sli.append(cad)
+ cad = ""
+ if cad:
+ sli.append(cad)
+ cli = "\n".join(sli)
+ if QTUtil2.pregunta(self, _("Do you want to remove the next lines ?") + "\n\n" + cli):
+ li.sort(reverse=True)
+ um = QTUtil2.unMomento(self, _("Working..."))
+ for num in li:
+ del self.dbop[num-1]
+ self.glines.refresh()
+ self.goto_inilinea()
+ um.final()
+
+ def goto_inilinea(self):
+ nlines = len(self.dbop)
+ if nlines == 0:
+ return
+
+ linea = self.glines.recno() // 2
+ if linea >= nlines:
+ linea = nlines-1
+
+ fila = linea*2
+ ncol = 0
+ self.glines.goto(fila, ncol)
+ self.glines.refresh()
def goto_finlinea(self):
nlines = len(self.dbop)
@@ -478,6 +831,7 @@ def goto_finlinea(self):
self.glines.refresh()
def terminar(self):
+ self.tabsanalisis.saveConfig()
self.guardarVideo()
self.accept()
@@ -485,9 +839,12 @@ def mueveHumano(self, partida):
# Estamos en la misma linea ?
# recno = self.glines.recno()
# Buscamos en las lineas si hay alguna que el pv sea parcial o totalmente igual
+ partida.pendienteApertura = True
siNueva, num_linea, siAppend = self.dbop.posPartida(partida)
siBlancas = partida.jugada(-1).siBlancas()
- ncol = (partida.numJugadas() - self.num_jg_inicial) // 2 + 1
+ ncol = (partida.numJugadas() - self.num_jg_inicial + 1) // 2
+ if self.num_jg_inicial%2 == 1 and siBlancas:
+ ncol += 1
if siNueva:
self.dbop.append(partida)
else:
@@ -504,6 +861,86 @@ def mueveHumano(self, partida):
self.glines.refresh()
+class WStaticTraining(QTVarios.WDialogo):
+ def __init__(self, procesador, dbop):
+ self.training = dbop.training()
+ self.ligames = self.training["LIGAMES_STATIC"]
+ self.num_games = len(self.ligames)
+ self.elems_fila = 10
+ if self.num_games < self.elems_fila:
+ self.elems_fila = self.num_games
+ self.num_filas = (self.num_games-1) / self.elems_fila + 1
+ self.seleccionado = None
+
+ titulo = "%s - %s" % (_("Opening lines"), _("Static training"))
+
+ extparam = "openlines_static_%s" % dbop.nomFichero
+
+ QTVarios.WDialogo.__init__(self, procesador.pantalla, titulo, Iconos.TrainStatic(), extparam)
+
+ lb = Controles.LB(self, dbop.gettitle())
+ lb.ponFondoN("#BDDBE8").alinCentrado().ponTipoLetra(puntos=14)
+
+ # Toolbar
+ tb = Controles.TBrutina(self)
+ tb.new(_("Close"), Iconos.MainMenu(), self.terminar)
+
+ # Lista
+ ancho = 42
+ oColumnas = Columnas.ListaColumnas()
+ oColumnas.nueva("FILA", "", 36, siCentrado=True)
+ for x in range(self.elems_fila):
+ oColumnas.nueva("COL%d" % x, "%d" % (x+1,), ancho, siCentrado=True, edicion=Delegados.PmIconosWeather())
+
+ self.grid = Grid.Grid(self, oColumnas, altoFila=ancho, background="white")
+ self.grid.setAlternatingRowColors(False)
+ self.grid.tipoLetra(puntos=10, peso=500)
+ nAnchoPgn = self.grid.anchoColumnas() + 20
+ self.grid.setMinimumWidth(nAnchoPgn)
+
+ ly = Colocacion.V().control(lb).control(tb).control(self.grid)
+ self.setLayout(ly)
+
+ alto = self.num_filas*ancho + 146
+ self.recuperarVideo(siTam=True, altoDefecto=alto, anchoDefecto=nAnchoPgn)
+
+ def terminar(self):
+
+ self.guardarVideo()
+ self.reject()
+
+ def gridNumDatos(self, grid):
+ return self.num_filas
+
+ def gridDato(self, grid, fila, oColumna):
+ col = oColumna.clave
+ if col == "FILA":
+ return "%d" % (fila + 1)
+ elif col.startswith("COL"):
+ num = fila*self.elems_fila + int(col[3:])
+ if num >= self.num_games:
+ return None
+ game = self.ligames[num]
+ sinerror = game["NOERROR"]
+ return str(sinerror) if sinerror < 4 else "4"
+
+ def gridDobleClick(self, grid, fila, oColumna):
+ col = oColumna.clave
+ if col.startswith("COL"):
+ num = fila*self.elems_fila + int(col[3:])
+ if num >= self.num_games:
+ return
+ self.seleccionado = num
+ self.guardarVideo()
+ self.accept()
+
+
+def selectLine(procesador, dbop):
+ w = WStaticTraining(procesador, dbop)
+ w.exec_()
+ return w.seleccionado
+
+
def openingLines(procesador):
w = WOpeningLines(procesador)
return w.resultado if w.exec_() else None
@@ -512,7 +949,8 @@ def openingLines(procesador):
def study(procesador, fichero):
with QTUtil.EscondeWindow(procesador.pantalla):
dbop = OpeningLines.Opening(os.path.join(procesador.configuracion.folderOpenings, fichero))
- w = WStudy(procesador, dbop)
+ w = WLines(procesador, dbop)
w.exec_()
dbop.close()
+ return w.resultado
diff --git a/Code/QT/PantallaAnalisis.py b/Code/QT/PantallaAnalisis.py
index daca169..1ecc15c 100644
--- a/Code/QT/PantallaAnalisis.py
+++ b/Code/QT/PantallaAnalisis.py
@@ -74,7 +74,7 @@ def xcol():
confTablero = VarGen.configuracion.confTablero("ANALISISGRAPH", 48)
self.tablero = Tablero.Tablero(self, confTablero)
self.tablero.crea()
- self.tablero.ponerPiezasAbajo(True)
+ self.tablero.ponerPiezasAbajo(alm.siBlancasAbajo)
self.tablero.dispatchSize(self.tableroSizeChanged)
self.capturas = WCapturas.CapturaLista(self, self.tablero)
@@ -431,7 +431,8 @@ def grabarTodos(self):
if resp:
for pos, tp in enumerate(self.um.listaRM):
rm = tp[0]
- partida = Partida.Partida(self.um.jg.posicionBase).leerPV(rm.pv)
+ partida = Partida.Partida(self.um.jg.posicionBase)
+ partida.leerPV(rm.pv)
self.um.grabarBase(partida, rm, resp)
self.um.ponVistaGestor()
diff --git a/Code/QT/PantallaAnalisisParam.py b/Code/QT/PantallaAnalisisParam.py
index 5dd4ea8..ef3439c 100644
--- a/Code/QT/PantallaAnalisisParam.py
+++ b/Code/QT/PantallaAnalisisParam.py
@@ -6,7 +6,7 @@
from Code import Util
from Code import EngineThread
-SEPARADOR = (None, None)
+SEPARADOR = FormLayout.separador
def leeDicParametros(configuracion):
diff --git a/Code/QT/PantallaAperturas.py b/Code/QT/PantallaAperturas.py
index 6614d1f..de00cfb 100644
--- a/Code/QT/PantallaAperturas.py
+++ b/Code/QT/PantallaAperturas.py
@@ -150,7 +150,7 @@ def ponActivas(self):
self.tablero.ponPosicion(self.partida.ultPosicion)
- self.apStd.asignaApertura(self.partida)
+ self.partida.asignaApertura()
txt = self.partida.pgnSP()
if self.partida.apertura:
txt = '
%s%s' % (self.partida.apertura.nombre, txt)
@@ -333,7 +333,7 @@ def leeBloques(self, liPV):
for pv in liPV:
p = Partida.Partida()
p.leerPV(pv)
- self.listaAperturasStd.asignaApertura(p)
+ p.asignaApertura()
ap = p.apertura
if ap is None:
ap = AperturasStd.AperturasStd(_("Unknown"))
diff --git a/Code/QT/PantallaArbol.py b/Code/QT/PantallaArbol.py
index 015dc15..ea4699b 100644
--- a/Code/QT/PantallaArbol.py
+++ b/Code/QT/PantallaArbol.py
@@ -1,6 +1,6 @@
import collections
-import LCEngine
+import LCEngineV1 as LCEngine
from PyQt4 import QtGui, QtCore
diff --git a/Code/QT/PantallaColores.py b/Code/QT/PantallaColores.py
index f7641b1..56b0da2 100644
--- a/Code/QT/PantallaColores.py
+++ b/Code/QT/PantallaColores.py
@@ -438,18 +438,13 @@ def l2mas1(lyG, fila, a, b, c):
self.tablero.ponPosicion(cp)
self.rehazFlechas()
- liAcciones = [(_("Accept"), Iconos.Aceptar(), "aceptar"),
- None,
- (_("Cancel"), Iconos.Cancelar(), "cancelar"),
- None,
- (_("Your themes"), Iconos.Temas(), "temas"),
- None,
- (_("Import"), Iconos.Mezclar(), "importar"),
- None,
- (_("Export"), Iconos.Grabar(), "exportar"),
- None,
+ liAcciones = [(_("Accept"), Iconos.Aceptar(), self.aceptar), None,
+ (_("Cancel"), Iconos.Cancelar(), self.cancelar), None,
+ (_("Your themes"), Iconos.Temas(), self.temas), None,
+ (_("Import"), Iconos.Mezclar(), self.importar), None,
+ (_("Export"), Iconos.Grabar(), self.exportar), None,
]
- tb = Controles.TB(self, liAcciones)
+ tb = Controles.TBrutina(self, liAcciones)
# tam tablero
self.lbTamTablero = Controles.LB(self, "%d px" % self.tablero.width())
@@ -495,10 +490,10 @@ def extendedColor(self):
def rehazFlechas(self):
self.tablero.quitaFlechas()
- self.tablero.creaFlechaTmp("b8", "b4", True)
- self.tablero.creaFlechaTmp("f5", "c2", False)
- self.tablero.creaFlechaMov("d1", "h5", "ms100")
- self.tablero.creaFlechaMov("d8", "d5", "mt100")
+ self.tablero.creaFlechaTmp("f2", "f4", True)
+ self.tablero.creaFlechaTmp("d1", "d4", False)
+ self.tablero.creaFlechaMov("f5", "d7", "ms100")
+ self.tablero.creaFlechaMov("d6", "b4", "mt100")
def cambiadoTema(self):
fichTema = self.cbTemas.valor()
@@ -573,27 +568,16 @@ def defectoTemas(self):
self.actualizaTablero()
- def procesarTB(self):
- accion = self.sender().clave
- if accion == "aceptar":
+ def aceptar(self):
+ self.confTablero.guardaEnDisco()
+ self.tableroOriginal.reset(self.confTablero)
- self.confTablero.guardaEnDisco()
- self.tableroOriginal.reset(self.confTablero)
+ self.guardarVideo()
+ self.accept()
- self.guardarVideo()
- self.accept()
- elif accion == "cancelar":
- self.guardarVideo()
- self.reject()
-
- elif accion == "temas":
- self.temas()
-
- elif accion == "importar":
- self.importar()
-
- elif accion == "exportar":
- self.exportar()
+ def cancelar(self):
+ self.guardarVideo()
+ self.reject()
def importar(self):
# import os
diff --git a/Code/QT/PantallaConfig.py b/Code/QT/PantallaConfig.py
index 049caf1..9e76ee9 100644
--- a/Code/QT/PantallaConfig.py
+++ b/Code/QT/PantallaConfig.py
@@ -116,6 +116,16 @@ def opciones(parent, configuracion):
liTT.append(separador)
liTT.append((_("Tutor enabled"), configuracion.tutorActivoPorDefecto))
liTT.append(separador)
+
+ # Mostrando el tutor
+ # kTutorH, kTutorH2_1, kTutorH1_2, kTutorV
+ liPosTutor = [configuracion.vistaTutor, (kTutorH, _("Horizontal")),
+ (kTutorH2_1, _("Horizontal") + " 2+1"),
+ (kTutorH1_2, _("Horizontal") + " 1+2"),
+ (kTutorV, _("Vertical"))]
+ liTT.append((_("Tutor boards position") + ":", liPosTutor))
+ liTT.append(separador)
+ liTT.append(separador)
liTT.append((None, _("Sensitivity")))
liTT.append((FormLayout.Spinbox(_("Minimum difference in points"), 0, 1000, 70), configuracion.tutorDifPts))
liTT.append((FormLayout.Spinbox(_("Minimum difference in %"), 0, 1000, 70), configuracion.tutorDifPorc))
@@ -158,56 +168,49 @@ def d(num):
liSA.append((config, configuracion.salvarCSV))
# Boards
- liT = [separador]
+ liB = [separador]
- # Mostrando el tutor
- # kTutorH, kTutorH2_1, kTutorH1_2, kTutorV
- liPosTutor = [configuracion.vistaTutor, (kTutorH, _("Horizontal")),
- (kTutorH2_1, _("Horizontal") + " 2+1"),
- (kTutorH1_2, _("Horizontal") + " 1+2"),
- (kTutorV, _("Vertical"))]
- liT.append((_("Tutor boards position") + ":", liPosTutor))
- liT.append(separador)
- liT.append((_("Visual effects") + ":", configuracion.efectosVisuales))
+ liB.append((_("Visual effects") + ":", configuracion.efectosVisuales))
drap = {1: 100, 2: 150, 3: 200, 4: 250, 5: 300, 6: 350, 7: 400, 8: 450, 9: 500}
drapV = {}
for x in drap:
drapV[drap[x]] = x
- liT.append((FormLayout.Dial("%s (%s=1)" % (_("Speed"), _("Default")), 1, len(drap), siporc=False),
+ liB.append((FormLayout.Dial("%s (%s=1)" % (_("Speed"), _("Default")), 1, len(drap), siporc=False),
drapV.get(configuracion.rapidezMovPiezas, 100)))
- liT.append(separador)
+ liB.append(separador)
liMouseSH = [configuracion.siAtajosRaton,
(False, _("Type fixed: you must always indicate origin and destination")),
(True, _("Type predictive: program tries to guess your intention"))]
- liT.append((_("Mouse shortcuts") + ":", liMouseSH))
- liT.append((_("Show candidates") + ":", configuracion.showCandidates))
- liT.append((_("Show arrows of variants") + ":", configuracion.showVariantes))
- liT.append((_("Always promote to queen\nALT key allows to change") + ":", configuracion.autocoronacion))
- liT.append((_("Show cursor when engine is thinking") + ":", configuracion.cursorThinking))
- liT.append(separador)
- liT.append((_("Enable captured material window by default") + ":", configuracion.siActivarCapturas))
+ liB.append((_("Mouse shortcuts") + ":", liMouseSH))
+ liB.append((_("Show candidates") + ":", configuracion.showCandidates))
+ liB.append((_("Show arrows of variants") + ":", configuracion.showVariantes))
+ liB.append((_("Always promote to queen\nALT key allows to change") + ":", configuracion.autocoronacion))
+ liB.append((_("Show cursor when engine is thinking") + ":", configuracion.cursorThinking))
+ liB.append(separador)
+ liB.append((_("Enable captured material window by default") + ":", configuracion.siActivarCapturas))
liMat = [configuracion.tipoMaterial, ("D", _("Difference material")), ("C", _("Captured material at beginning")), ("M", _("Material advantage"))]
- liT.append((_("Show material") + ":", liMat))
- liT.append(separador)
- liT.append((_("Enable information panel by default") + ":", configuracion.siActivarInformacion))
- liT.append(separador)
- liT.append((_X(_("Enable %1"), _("DGT board")) + ":", configuracion.siDGT))
- liT.append(separador)
+ liB.append((_("Show material") + ":", liMat))
+ liB.append(separador)
+ liB.append((_("Enable information panel by default") + ":", configuracion.siActivarInformacion))
+ liB.append(separador)
+ liB.append((_X(_("Enable %1"), _("DGT board")) + ":", configuracion.siDGT))
+ liB.append(separador)
# liT.append((FormLayout.Dial(_("Opacity of tool icon"), 1, 9, siporc=False), configuracion.opacityToolBoard))
- liT.append((_("Show configuration icon"), configuracion.opacityToolBoard > 6))
+ liB.append((_("Show configuration icon"), configuracion.opacityToolBoard > 6))
liPos = [configuracion.positionToolBoard, ("B", _("Bottom")), ("T", _("Top"))]
- liT.append((_("Configuration icon position") + ":", liPos))
- liT.append(separador)
- liT.append((_("Show icon when position has graphic information"), configuracion.directorIcon))
- liT.append(separador)
+ liB.append((_("Configuration icon position") + ":", liPos))
+ liB.append(separador)
+ liB.append((_("Show icon when position has graphic information"), configuracion.directorIcon))
+
+ liB.append(separador)
lista = []
lista.append((liGen, _("General"), ""))
lista.append((liSon, _("Sounds"), ""))
lista.append((liTT, _("Tutor"), ""))
- lista.append((liT, _("Boards"), ""))
+ lista.append((liB, _("Boards"), ""))
lista.append((liEng, _("Engines"), ""))
lista.append((liAsp, _("Appearance"), ""))
lista.append((liPR, _("Performance"), ""))
@@ -220,7 +223,7 @@ def d(num):
if resultado:
accion, resp = resultado
- liGen, liSon, liTT, liT, liEng, liAsp, liPR, liSA, liNC = resp
+ liGen, liSon, liTT, liB, liEng, liAsp, liPR, liSA, liNC = resp
(configuracion.jugador, configuracion.estilo, configuracion.traductor, configuracion.checkforupdate) = liGen
@@ -237,23 +240,25 @@ def d(num):
if configuracion.familia == "System":
configuracion.familia = ""
- (configuracion.siSuenaBeep, configuracion.siSuenaResultados, configuracion.siSuenaJugada, configuracion.siSuenaNuestro) = liSon
+ (configuracion.siSuenaBeep, configuracion.siSuenaResultados,
+ configuracion.siSuenaJugada, configuracion.siSuenaNuestro) = liSon
(configuracion.tutor.clave, tiempoTutor, configuracion.depthTutor, configuracion.tutorMultiPV,
- configuracion.tutorActivoPorDefecto, configuracion.tutorDifPts, configuracion.tutorDifPorc) = liTT
+ configuracion.tutorActivoPorDefecto, configuracion.vistaTutor,
+ configuracion.tutorDifPts, configuracion.tutorDifPorc ) = liTT
configuracion.tiempoTutor = int(tiempoTutor * 1000)
- (configuracion.eloNC, configuracion.micheloNC, configuracion.ficsNC, configuracion.fideNC, configuracion.lichessNC) = liNC
+ (configuracion.eloNC, configuracion.micheloNC, configuracion.ficsNC,
+ configuracion.fideNC, configuracion.lichessNC) = liNC
(configuracion.centipawns, configuracion.bmi2, configuracion.notbackground, configuracion.siLogEngines) = liEng
- (configuracion.vistaTutor,
- configuracion.efectosVisuales, rapidezMovPiezas,
+ (configuracion.efectosVisuales, rapidezMovPiezas,
configuracion.siAtajosRaton, configuracion.showCandidates, configuracion.showVariantes,
configuracion.autocoronacion,
configuracion.cursorThinking, configuracion.siActivarCapturas, configuracion.tipoMaterial,
configuracion.siActivarInformacion, siDGT, toolIcon, configuracion.positionToolBoard,
- configuracion.directorIcon) = liT
+ configuracion.directorIcon) = liB
configuracion.opacityToolBoard = 10 if toolIcon else 1
configuracion.rapidezMovPiezas = drap[rapidezMovPiezas]
if configuracion.siDGT != siDGT:
diff --git a/Code/QT/PantallaDailyTest.py b/Code/QT/PantallaDailyTest.py
index 5349c87..9fc0a17 100644
--- a/Code/QT/PantallaDailyTest.py
+++ b/Code/QT/PantallaDailyTest.py
@@ -62,7 +62,7 @@ def __init__(self, procesador):
def leeParametros(self):
param = Util.DicSQL(self.configuracion.ficheroDailyTest, tabla="parametros")
- motor = param.get("MOTOR", "stockfish")
+ motor = param.get("MOTOR", "mcbrain")
segundos = param.get("SEGUNDOS", 7)
pruebas = param.get("PRUEBAS", 5)
fns = param.get("FNS", "")
@@ -216,7 +216,7 @@ def __init__(self, owner, liFens, motor, segundos, fns):
if motor.startswith("*"):
motor = motor[1:]
- confMotor = self.configuracion.buscaTutor(motor, "stockfish")
+ confMotor = self.configuracion.buscaTutor(motor, "mcbrain")
self.xtutor = self.procesador.creaGestorMotor(confMotor, segundos * 1000, None)
self.xtutor.maximizaMultiPV()
diff --git a/Code/QT/WBDatabaseFEN.py b/Code/QT/PantallaDatabaseFEN.py
similarity index 100%
rename from Code/QT/WBDatabaseFEN.py
rename to Code/QT/PantallaDatabaseFEN.py
diff --git a/Code/QT/PantallaEverest.py b/Code/QT/PantallaEverest.py
index de5f0c8..75f14aa 100644
--- a/Code/QT/PantallaEverest.py
+++ b/Code/QT/PantallaEverest.py
@@ -1,7 +1,7 @@
import os.path
import random
-import LCEngine
+import LCEngineV1 as LCEngine
from PyQt4 import QtSvg, QtCore
from Code import Everest
diff --git a/Code/QT/PantallaGM.py b/Code/QT/PantallaGM.py
index 2a61bd7..533ca73 100644
--- a/Code/QT/PantallaGM.py
+++ b/Code/QT/PantallaGM.py
@@ -192,7 +192,10 @@ def __init__(self, procesador, siWoman):
self.recuperarVideo(anchoDefecto=450)
def cambiadoDepth(self, num):
- self.edJtiempo.ponFloat(0.0 if num > 0 else 3.0)
+ tiempo = self.edJtiempo.textoFloat()
+ if int(tiempo)*10 == 0:
+ tiempo = 3.0
+ self.edJtiempo.ponFloat(0.0 if num > 0 else tiempo)
self.edJtiempo.setEnabled(num == 0)
def closeEvent(self, event):
@@ -606,7 +609,7 @@ def importarGM(ownerGM, siWoman):
# Primero nos tenemos que traer la lista de la web
fichz = "_listaGM.zip"
ficht = "_listaGM.txt"
- fichtg = "gm/listaGM.txt"
+ fichtg = "GM/listaGM.txt"
if siWoman:
fichtg = "w" + fichtg
try:
@@ -647,7 +650,7 @@ def importarGM(ownerGM, siWoman):
linea = linea.strip()
if linea:
gm, nombre, ctam, cpart = linea.split(VarGen.XSEP)
- fichero = "gm/%s.xgm" % gm
+ fichero = "GM/%s.xgm" % gm
if siWoman:
fichero = "w" + fichero
if Util.tamFichero(fichero) != int(ctam): # si no existe tam = -1
@@ -673,7 +676,7 @@ def importarGM(ownerGM, siWoman):
zfobj = zipfile.ZipFile(fzip)
for name in zfobj.namelist():
- fichero = "gm/%s" % name
+ fichero = "GM/%s" % name
if siWoman:
fichero = "w" + fichero
outfile = open(fichero, 'wb')
diff --git a/Code/QT/PantallaHorses.py b/Code/QT/PantallaHorses.py
index a6adbe8..24d64db 100644
--- a/Code/QT/PantallaHorses.py
+++ b/Code/QT/PantallaHorses.py
@@ -3,7 +3,7 @@
import random
import time
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import ControlPosicion
from Code.QT import Colocacion
diff --git a/Code/QT/PantallaJuicio.py b/Code/QT/PantallaJuicio.py
index 74b0382..025c74d 100644
--- a/Code/QT/PantallaJuicio.py
+++ b/Code/QT/PantallaJuicio.py
@@ -180,7 +180,8 @@ def gridColorFondo(self, grid, fila, oColumna):
return None
def gridCambiadoRegistro(self, grid, fila, columna):
- self.partida = Partida.Partida(self.posicion).leerPV(self.listaRM[fila].rm.pv)
+ self.partida = Partida.Partida(self.posicion)
+ self.partida.leerPV(self.listaRM[fila].rm.pv)
self.maxMoves = self.partida.numJugadas()
self.mueve(siInicio=True)
diff --git a/Code/QT/PantallaManualSave.py b/Code/QT/PantallaManualSave.py
index 0e308b6..7165a7a 100644
--- a/Code/QT/PantallaManualSave.py
+++ b/Code/QT/PantallaManualSave.py
@@ -193,7 +193,7 @@ def inicializa(self):
self.sb_number.ponValor(dic_vars.get("NUMBER",0))
- self.cb_engine.ponValor(dic_vars.get("ENGINE", "stockfish"))
+ self.cb_engine.ponValor(dic_vars.get("ENGINE", "mcbrain"))
self.sb_multipv.ponValor(dic_vars.get("MULTIPV", 1))
diff --git a/Code/QT/PantallaMotores.py b/Code/QT/PantallaMotores.py
index 07b95a6..8eacbdf 100644
--- a/Code/QT/PantallaMotores.py
+++ b/Code/QT/PantallaMotores.py
@@ -297,7 +297,7 @@ def __init__(self, wParent, listaMotores, motorExterno, siTorneo=False):
# # Comprobamos que todos esten accesibles
self.listaLibros.comprueba()
li = [(x.nombre, x.path) for x in self.listaLibros.lista]
- li.insert(0, ("* " + _("Engine book"), "-"))
+ li.insert(0, ("* " + _("None"), "-"))
li.insert(0, ("* " + _("Default"), "*"))
self.cbBooks = Controles.CB(self, li, motorExterno.book())
btNuevoBook = Controles.PB(self, "", self.nuevoBook, plano=False).ponIcono(Iconos.Nuevo(), tamIcon=16)
diff --git a/Code/QT/PantallaTabDirVisual.py b/Code/QT/PantallaTabDirVisual.py
index 8d930eb..c080673 100644
--- a/Code/QT/PantallaTabDirVisual.py
+++ b/Code/QT/PantallaTabDirVisual.py
@@ -44,19 +44,21 @@ def __init__(self, owner, tablero):
self.guion = TabVisual.Guion(tablero, self)
# Guion
- liAcciones = [(_("Close"), Iconos.MainMenu(), self.terminar),
- (_("Cancel"), Iconos.Cancelar(), self.cancelar),
- (_("Save"), Iconos.Grabar(), self.grabar),
- (_("New"), Iconos.Nuevo(), self.gnuevo),
- (_("Insert"), Iconos.Insertar(), self.ginsertar),
- (_("Remove"), Iconos.Borrar(), self.gborrar), None,
- (_("Up"), Iconos.Arriba(), self.garriba),
- (_("Down"), Iconos.Abajo(), self.gabajo), None,
- (_("Mark"), Iconos.Marcar(), self.gmarcar), None,
- (_("File"), Iconos.Recuperar(), self.gfile), None
- ]
+ liAcciones = [
+ (_("Close"), Iconos.MainMenu(), self.terminar),
+ (_("Cancel"), Iconos.Cancelar(), self.cancelar),
+ (_("Save"), Iconos.Grabar(), self.grabar),
+ (_("New"), Iconos.Nuevo(), self.gnuevo),
+ (_("Insert"), Iconos.Insertar(), self.ginsertar),
+ (_("Remove"), Iconos.Borrar(), self.gborrar), None,
+ (_("Up"), Iconos.Arriba(), self.garriba),
+ (_("Down"), Iconos.Abajo(), self.gabajo), None,
+ (_("Mark"), Iconos.Marcar(), self.gmarcar), None,
+ (_("File"), Iconos.Recuperar(), self.gfile), None
+ ]
self.tb = Controles.TBrutina(self, liAcciones, siTexto=False, tamIcon=24)
self.tb.setAccionVisible(self.grabar, False)
+
oColumnas = Columnas.ListaColumnas()
oColumnas.nueva("NUMERO", _("N."), 20, siCentrado=True)
oColumnas.nueva("MARCADO", "", 20, siCentrado=True, siChecked=True)
@@ -74,9 +76,9 @@ def __init__(self, owner, tablero):
self.selectBanda = PantallaTab.SelectBanda(self)
lyG = Colocacion.V().control(self.g_guion).control(self.chbSaveWhenFinished)
-
lySG = Colocacion.H().control(self.selectBanda).otro(lyG).relleno(1)
layout = Colocacion.V().control(self.tb).otro(lySG).margen(3)
+
self.setLayout(layout)
self.recuperarVideo()
@@ -247,11 +249,11 @@ def creaTarea(self, tp, xid, a1h8, fila):
if tarea is None:
return None, None
tarea.registro((tp, xid, a1h8))
+
self.g_guion.goto(fila, 0)
self.ponMarcado(fila, True)
- self.refresh_guion()
return tarea, fila
def editaNombre(self, nombre):
@@ -637,22 +639,6 @@ def editarBanda(self, cid):
if len(self.guion):
self.ponSiGrabar()
- def cierraRecursos(self):
- if self.guion is not None:
- self.guion.cierraPizarra()
- self.dbConfig["SELECTBANDA"] = self.selectBanda.guardar()
- self.dbConfig["SELECTBANDANUM"] = self.selectBanda.numSeleccionada()
- self.dbConfig["SAVEWHENFINISHED"] = self.chbSaveWhenFinished.valor()
- self.dbConfig.close()
- self.dbFlechas.close()
- self.dbMarcos.close()
- self.dbSVGs.close()
- self.dbMarkers.close()
-
- self.guardarVideo()
- self.guion.restoreTablero()
- self.guion = None
-
def test_siGrabar(self):
if self.siGrabar:
if self.chbSaveWhenFinished.valor():
@@ -743,6 +729,22 @@ def leeRecursos(self):
self.dbSVGs = Util.DicSQL(fdb, tabla="SVGs")
self.dbMarkers = Util.DicSQL(fdb, tabla="Markers")
+ def cierraRecursos(self):
+ if self.guion is not None:
+ self.guion.cierraPizarra()
+ self.dbConfig["SELECTBANDA"] = self.selectBanda.guardar()
+ self.dbConfig["SELECTBANDANUM"] = self.selectBanda.numSeleccionada()
+ self.dbConfig["SAVEWHENFINISHED"] = self.chbSaveWhenFinished.valor()
+ self.dbConfig.close()
+ self.dbFlechas.close()
+ self.dbMarcos.close()
+ self.dbSVGs.close()
+ self.dbMarkers.close()
+
+ self.guardarVideo()
+ self.guion.restoreTablero()
+ self.guion = None
+
def actualizaBandas(self):
self.selectBanda.iniActualizacion()
@@ -855,7 +857,7 @@ def tableroRemove(self, itemSC):
self.gborrar()
-class DirVisual():
+class DirVisual:
def __init__(self, tablero):
self.tablero = tablero
self.ultTareaSelect = None
@@ -905,72 +907,50 @@ def keyPressEvent(self, event):
return False
def mousePressEvent(self, event):
+ siRight = event.button() == QtCore.Qt.RightButton
p = event.pos()
a1h8 = self.punto2a1h8(p)
- if event.button() == QtCore.Qt.LeftButton:
- m = int(event.modifiers())
- siCtrl = (m & QtCore.Qt.ControlModifier) > 0
- if siCtrl:
- li_tareas = self.guion.tareasPosicion(p)
- if li_tareas:
- pos_guion, tarea = li_tareas[0]
- self.w.g_guion.goto(pos_guion, 0)
- self.w.gborrar([pos_guion,])
- return
- a1h8 = self.punto2a1h8(p)
- pz_borrar = self.tablero.dameNomPiezaEn(a1h8)
+ m = int(event.modifiers())
+ if siRight and (m & QtCore.Qt.ControlModifier) > 0:
+ self.terminar()
+ return True
+
+ li_tareas = self.guion.tareasPosicion(p)
+
+ if siRight:
+ pz_borrar = self.tablero.dameNomPiezaEn(a1h8)
+ menu = Controles.Menu(self.tablero)
+ dicPieces = TrListas.dicNomPiezas()
+ icoPiece = self.tablero.piezas.icono
+
+ if pz_borrar or len(li_tareas):
+ mrem = menu.submenu(_("Remove"), Iconos.Delete())
if pz_borrar:
+ rotulo = dicPieces[pz_borrar.upper()]
+ mrem.opcion(("rem_pz", None), rotulo, icoPiece(pz_borrar))
+ mrem.separador()
+ for pos_guion, tarea in li_tareas:
+ rotulo = "%s - %s - %s" % (tarea.txt_tipo(), tarea.nombre(), tarea.info())
+ mrem.opcion(("rem_gr", pos_guion), rotulo, Iconos.Delete())
+ mrem.separador()
+ menu.separador()
+
+ for pz in "KQRBNPkqrbnp":
+ if pz != pz_borrar:
+ if pz == "k":
+ menu.separador()
+ menu.opcion(("create", pz), dicPieces[pz.upper()], icoPiece(pz))
+ resp = menu.lanza()
+ if resp is not None:
+ orden, arg = resp
+ if orden == "rem_gr":
+ self.w.g_guion.goto(arg, 0)
+ self.w.gborrar()
+ elif orden == "rem_pz":
self.w.creaTarea("B", pz_borrar, a1h8, -1)
- return
-
- elif event.button() == QtCore.Qt.RightButton:
- m = int(event.modifiers())
- siCtrl = (m & QtCore.Qt.ControlModifier) > 0
- li_tareas = self.guion.tareasPosicion(p)
- if siCtrl and len(li_tareas) > 0:
- pos_guion, tarea = li_tareas[0]
- self.w.gborrar([pos_guion,])
- return
-
- siAlt = (m & QtCore.Qt.AltModifier) > 0
-
- if siAlt:
- pz_borrar = self.tablero.dameNomPiezaEn(a1h8)
- menu = Controles.Menu(self.tablero)
- dicPieces = TrListas.dicNomPiezas()
- icoPiece = self.tablero.piezas.icono
-
- if pz_borrar or len(li_tareas):
- mrem = menu.submenu(_("Remove"), Iconos.Delete())
- if pz_borrar:
- rotulo = dicPieces[pz_borrar.upper()]
- mrem.opcion(("rem_pz", None), rotulo, icoPiece(pz_borrar))
- mrem.separador()
- for pos_guion, tarea in li_tareas:
- rotulo = "%s - %s - %s" % (tarea.txt_tipo(), tarea.nombre(), tarea.info())
- mrem.opcion(("rem_gr", pos_guion), rotulo, Iconos.Delete())
- mrem.separador()
- menu.separador()
-
- for pz in "KQRBNPkqrbnp":
- if pz != pz_borrar:
- if pz == "k":
- menu.separador()
- menu.opcion(("create", pz), dicPieces[pz.upper()], icoPiece(pz))
- resp = menu.lanza()
- if resp is not None:
- orden, arg = resp
- if orden == "rem_gr":
- self.w.g_guion.goto(arg, 0)
- self.w.gborrar()
- elif orden == "rem_pz":
- self.w.creaTarea("B", pz_borrar, a1h8, -1)
-
- elif orden == "create":
- self.w.creaTarea("C", arg, a1h8, -1)
- else:
- self.terminar()
+ elif orden == "create":
+ self.w.creaTarea("C", arg, a1h8, -1)
return True
if self.director:
@@ -1059,5 +1039,4 @@ def mouseReleaseEvent(self, event):
def terminar(self):
if self.w:
self.w.terminar()
- self.w = None
-
+ self.w = None
\ No newline at end of file
diff --git a/Code/QT/PantallaTorneos.py b/Code/QT/PantallaTorneos.py
index 17a8bc1..01562e3 100644
--- a/Code/QT/PantallaTorneos.py
+++ b/Code/QT/PantallaTorneos.py
@@ -132,7 +132,7 @@ def __init__(self, wParent, torneo):
titulo = _("Competition")
icono = Iconos.Torneos()
- extparam = "untorneo"
+ extparam = "untorneo_v1"
QTVarios.WDialogo.__init__(self, wParent, titulo, icono, extparam)
self.configuracion = VarGen.configuracion
@@ -175,7 +175,7 @@ def __init__(self, wParent, torneo):
# Comprobamos que todos esten accesibles
self.listaLibros.comprueba()
li = [(x.nombre, x.path) for x in self.listaLibros.lista]
- li.insert(0, ("* " + _("Default"), ""))
+ li.insert(0, ("* " + _("None"), "-"))
self.cbBooks = Controles.CB(self, li, torneo.book())
btNuevoBook = Controles.PB(self, "", self.nuevoBook, plano=False).ponIcono(Iconos.Nuevo(), tamIcon=16)
lyBook = Colocacion.H().control(self.cbBooks).control(btNuevoBook).relleno()
@@ -291,8 +291,8 @@ def __init__(self, wParent, torneo):
oColumnas.nueva("NUMERO", _("N."), 35, siCentrado=True)
oColumnas.nueva("MOTOR", _("Engine"), 190, siCentrado=True)
oColumnas.nueva("GANADOS", _("Wins"), 120, siCentrado=True)
- oColumnas.nueva("PERDIDOS", _("Lost"), 120, siCentrado=True)
oColumnas.nueva("TABLAS", _("Draw"), 120, siCentrado=True)
+ oColumnas.nueva("PERDIDOS", _("Lost"), 120, siCentrado=True)
oColumnas.nueva("PUNTOS", _("Points"), 120, siCentrado=True)
self.gridResult = Grid.Grid(self, oColumnas, siSelecFilas=True, xid="R")
self.registrarGrid(self.gridResult)
@@ -402,6 +402,11 @@ def gridDatoEnginesValores(self, fila, columna):
def borraResult(self):
self.liResult = None
+ def resultLabel(self, lirs):
+ w, b = lirs
+ t = w + b
+ return "0" if t == 0 else "%d (%s:%d - %s:%d)" % (t, _("White"), w, _("Black"), b)
+
def gridDatoResult(self, fila, columna):
if self.liResult is None:
self.liResult = self.torneo.rehacerResult()
@@ -410,21 +415,15 @@ def gridDatoResult(self, fila, columna):
return str(fila + 1)
elif columna == "MOTOR":
return rs["EN"].alias
- elif columna == "GANADOS":
- w, b = rs["WIN"]
- t = w + b
- return "0" if t == 0 else "%d (%d-%d)" % (t, w, b)
- elif columna == "PERDIDOS":
- w, b = rs["LOST"]
- t = w + b
- return "0" if t == 0 else "%d (%d-%d)" % (t, w, b)
- elif columna == "TABLAS":
- w, b = rs["DRAW"]
- t = w + b
- return "0" if t == 0 else "%d (%d-%d)" % (t, w, b)
elif columna == "PUNTOS":
p = rs["PTS"]
return "%d.%d" % (p / 10, p % 10)
+ elif columna == "GANADOS":
+ return self.resultLabel(rs["WIN"])
+ elif columna == "PERDIDOS":
+ return self.resultLabel(rs["LOST"])
+ elif columna == "TABLAS":
+ return self.resultLabel(rs["DRAW"])
def gridDatoGames(self, fila, columna):
gm = self.torneo.liGames()[fila]
diff --git a/Code/QT/PantallaVisualiza.py b/Code/QT/PantallaVisualiza.py
index 21b8afc..07b8d2c 100644
--- a/Code/QT/PantallaVisualiza.py
+++ b/Code/QT/PantallaVisualiza.py
@@ -1,7 +1,7 @@
import os.path
import time
-import LCEngine
+import LCEngineV1 as LCEngine
from PyQt4 import QtCore
from Code import ControlPosicion
diff --git a/Code/QT/TabElementos.py b/Code/QT/TabElementos.py
index 576b597..0740461 100644
--- a/Code/QT/TabElementos.py
+++ b/Code/QT/TabElementos.py
@@ -1,3 +1,5 @@
+import base64
+
from PyQt4 import QtCore, QtGui
from Code.QT import Controles
@@ -384,9 +386,8 @@ def __init__(self, escena, bloqueImagen, pixmap=None, rutina = None):
self.pixmap = pixmap
else:
self.pixmap = QtGui.QPixmap()
- import base64
-
self.pixmap.loadFromData(base64.b64decode(bloqueImagen.pixmap), "PNG")
+
r = self.pixmap.rect()
self.pmRect = QtCore.QRectF(0, 0, r.width(), r.height())
diff --git a/Code/QT/Tablero.py b/Code/QT/Tablero.py
index db168b4..da765b1 100644
--- a/Code/QT/Tablero.py
+++ b/Code/QT/Tablero.py
@@ -664,7 +664,7 @@ def lanzaMenuVisual(self, siIzquierdo=False):
menu.separador()
if self.siDirector:
- menu.opcion("director", _("Director") + " [F1..F10]", Iconos.Director())
+ menu.opcion("director", _("Director") + " [%s] " %_("F1-F10 or Ctrl Right button"), Iconos.Director())
menu.separador()
if self.siPosibleRotarTablero:
@@ -830,6 +830,10 @@ def mousePressEvent(self, event):
siDentro = (minimo < x < maximo) and (minimo < y < maximo)
if event.button() == QtCore.Qt.RightButton:
if siDentro:
+ if not self.dirvisual:
+ m = int(event.modifiers())
+ if (m & QtCore.Qt.ControlModifier) == 0:
+ return
self.lanzaDirector()
# if siDentro and hasattr(self.pantalla, "boardRightMouse") and not self.dirvisual:
# m = int(event.modifiers())
@@ -1000,7 +1004,7 @@ def dbVisual_open(self):
return self.dbVisual
def dbVisual_close(self):
- if self.dbVisual:
+ if self.dbVisual is not None:
self.dbVisual.close()
self.dbVisual = None
@@ -1013,6 +1017,30 @@ def dbVisual_lista(self, fenM2):
def dbVisual_save(self, fenM2, lista):
self.dbVisual_open()[fenM2] = lista
+ def saveVisual(self):
+ alm = self.almSaveVisual = Util.Almacen()
+ alm.siMenuVisual = self.siMenuVisual
+ alm.siDirector = self.siDirector
+ alm.siDirectorIcon = self.siDirectorIcon
+ alm.dirvisual = self.dirvisual
+ alm.guion = self.guion
+ alm.lastFenM2 = self.lastFenM2
+ alm.dbVisual = self.dbVisual
+ alm.nomdbVisual = self.nomdbVisual
+ alm.dbVisual_showAllways = self.dbVisual_showAllways
+
+ def restoreVisual(self):
+ alm = self.almSaveVisual
+ self.siMenuVisual = alm.siMenuVisual
+ self.siDirector = alm.siDirector
+ self.siDirectorIcon = alm.siDirectorIcon
+ self.dirvisual = alm.dirvisual
+ self.guion = alm.guion
+ self.lastFenM2 = alm.lastFenM2
+ self.dbVisual = alm.dbVisual
+ self.nomdbVisual = alm.nomdbVisual
+ self.dbVisual_showAllways = alm.dbVisual_showAllways
+
def setUltPosicion(self, posicion):
self.cierraGuion()
self.ultPosicion = posicion
diff --git a/Code/QT/WBG_InfoMove.py b/Code/QT/WBG_InfoMove.py
index 538f287..4289b7b 100644
--- a/Code/QT/WBG_InfoMove.py
+++ b/Code/QT/WBG_InfoMove.py
@@ -243,7 +243,7 @@ def colocatePartida(self, pos):
pgn += '
%d.' % (style_number, numJugada)
numJugada += 1
- xp = jg.pgnHTML() if self.siFigurines else jg.pgnSP()
+ xp = jg.pgnHTML(self.siFigurines)
if n == pos:
xp = '
%s' % (style_select, xp)
else:
diff --git a/Code/QT/WBG_Summary.py b/Code/QT/WBG_Summary.py
index f735277..e0aabcf 100644
--- a/Code/QT/WBG_Summary.py
+++ b/Code/QT/WBG_Summary.py
@@ -502,7 +502,7 @@ def cambiaInfoMove(self):
p = Partida.Partida()
p.leerPV(pv)
p.siTerminada()
- self.aperturasStd.asignaApertura(p)
+ p.asignaApertura()
self.infoMove.modoPartida(p, 9999)
self.setFocus()
self.grid.setFocus()
diff --git a/Code/Torneo.py b/Code/Torneo.py
index 86b821c..d1d1480 100644
--- a/Code/Torneo.py
+++ b/Code/Torneo.py
@@ -16,7 +16,7 @@ def __init__(self):
self._depth = 0
self._time = 0
- self._book = "*" # "*":por defecto "-":el propio del motor otro:path to libro polyglot
+ self._book = "-" # "*":por defecto "-":el propio del motor otro:path to libro polyglot
self._bookRR = "ap"
def ponHuella(self, liEngines):
diff --git a/Code/TurnOnLights.py b/Code/TurnOnLights.py
index 48e8ed5..0c1d954 100644
--- a/Code/TurnOnLights.py
+++ b/Code/TurnOnLights.py
@@ -3,6 +3,7 @@
import random
import datetime
+from Code import ControlPosicion
from Code import PGNreader
from Code import Util
from Code import VarGen
@@ -58,6 +59,17 @@ def penaltyHelp(self, think_mode):
else:
return 10.0
+ def factorDistancia(self):
+ nummoves = 0
+ distancia = 0.0
+ for line in self.lines:
+ d, n = line.distancia_moves()
+ nummoves += n
+ distancia += d
+ base_dist = ControlPosicion.distancia("a1", "a4")
+
+ return (distancia/nummoves)/base_dist
+
def add_line(self, line):
self.lines.append(line)
@@ -136,6 +148,10 @@ def get_move(self, num_move):
def total_moves(self):
return len(self.limoves)
+ def distancia_moves(self):
+ dt = sum( ControlPosicion.distancia(pv[:2], pv[2:4]) for pv in self.limoves )
+ return dt, len(self.limoves)
+
class TOL_level:
def __init__(self, lines_per_block, num_level):
diff --git a/Code/Tutor.py b/Code/Tutor.py
index ac5fdb0..4fb426a 100644
--- a/Code/Tutor.py
+++ b/Code/Tutor.py
@@ -1,7 +1,7 @@
import codecs
import os
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import Analisis
from Code import Partida
@@ -97,7 +97,8 @@ def elegir(self, siPuntos, liApPosibles=None):
pvBloque = ""
if pvBloque:
- self.partidaRival = Partida.Partida(self.ultPosicion).leerPV(pvBloque)
+ self.partidaRival = Partida.Partida(self.ultPosicion)
+ self.partidaRival.leerPV(pvBloque)
self.posRival = 0
self.maxRival = len(self.partidaRival.liJugadas) - 1
if self.maxRival >= 0:
@@ -165,7 +166,8 @@ def hazListaRM(self, posUsuario):
def cambiadoRM(self, pos):
self.posRM = pos
rm = self.listaRM[pos][0]
- self.partidaTutor = Partida.Partida(self.ultPosicion).leerPV(rm.getPV())
+ self.partidaTutor = Partida.Partida(self.ultPosicion)
+ self.partidaTutor.leerPV(rm.getPV())
self.w.ponPuntuacionTutor(rm.texto())
@@ -319,7 +321,8 @@ def ponTablerosGUI(self, tableroTutor, tableroUsuario, tableroRival, tableroAper
self.tableroAperturas = tableroAperturas
def cambiarApertura(self, numero):
- self.partidaAperturas = Partida.Partida(self.ultPosicion).leerPV(self.liApPosibles[numero].a1h8)
+ self.partidaAperturas = Partida.Partida(self.ultPosicion)
+ self.partidaAperturas.leerPV(self.liApPosibles[numero].a1h8)
self.tableroAperturas.ponPosicion(self.partidaAperturas.jugada(0).posicion)
self.maxApertura = len(self.partidaAperturas)
self.mueveApertura(siInicio=True)
diff --git a/Code/Util.py b/Code/Util.py
index 2c7b282..aa219f3 100644
--- a/Code/Util.py
+++ b/Code/Util.py
@@ -566,6 +566,28 @@ def validNomFichero(nombre):
return nombre
+def asciiNomFichero(nombre):
+ nombre = validNomFichero(nombre)
+ li = []
+ for x in nombre:
+ if not(31 < ord(x) < 127):
+ li.append("_")
+ else:
+ li.append(x)
+ nombre = "".join(li)
+ while "__" in nombre:
+ nombre = nombre.replace("__", "_")
+ return nombre
+
+
+def datefile(pathfile):
+ try:
+ mtime = os.path.getmtime(pathfile)
+ return datetime.datetime.fromtimestamp(mtime)
+ except:
+ return None
+
+
class Timer:
def __init__(self, tiempoPendiente):
diff --git a/Code/XGestorMotor.py b/Code/XGestorMotor.py
index 91bf1ce..e3cd47b 100644
--- a/Code/XGestorMotor.py
+++ b/Code/XGestorMotor.py
@@ -1,6 +1,6 @@
import os
-import LCEngine
+import LCEngineV1 as LCEngine
from Code import VarGen
from Code import XMotor
diff --git a/Code/XMotorRespuesta.py b/Code/XMotorRespuesta.py
index 9e0b55c..657c7c4 100644
--- a/Code/XMotorRespuesta.py
+++ b/Code/XMotorRespuesta.py
@@ -624,6 +624,9 @@ def bestmoves(self):
break
return li
+ def getdepth0(self):
+ return self.liMultiPV[0].depth if self.liMultiPV else 0
+
def mejorMovDetectaBlunders(self, fdbg, mindifpuntos, maxmate):
rm0 = self.liMultiPV[0]
if maxmate:
@@ -688,7 +691,8 @@ def x(clave):
# Miramos todas las propuestas
for num, rm in enumerate(self.liMultiPV):
- partida = Partida.Partida(cp).leerPV(rm.pv)
+ partida = Partida.Partida(cp)
+ partida.leerPV(rm.pv)
jg0 = partida.jugada(0)
ps0 = partida.iniPosicion
psZ = partida.ultPosicion
@@ -802,7 +806,8 @@ def x(clave):
if dbg:
fdbg.write("Result :\n")
for num, rm in enumerate(self.liMultiPV):
- partida = Partida.Partida(cp).leerPV(rm.pv)
+ partida = Partida.Partida(cp)
+ partida.leerPV(rm.pv)
pgn = ""
si = False
diff --git a/Engines/Linux32/mcbrain/.DS_Store b/Engines/Linux32/mcbrain/.DS_Store
deleted file mode 100644
index 01c2e2c..0000000
Binary files a/Engines/Linux32/mcbrain/.DS_Store and /dev/null differ
diff --git a/Engines/Linux32/mcbrain/.travis.yml b/Engines/Linux32/mcbrain/.travis.yml
index 87a3e7d..0a214d1 100644
--- a/Engines/Linux32/mcbrain/.travis.yml
+++ b/Engines/Linux32/mcbrain/.travis.yml
@@ -18,11 +18,12 @@ matrix:
compiler: clang
addons:
apt:
- sources: ['ubuntu-toolchain-r-test']
- packages: ['clang', 'g++-multilib', 'valgrind', 'expect']
+ sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0']
+ packages: ['clang-5.0', 'llvm-5.0-dev', 'g++-multilib', 'valgrind', 'expect']
env:
- - COMPILER=clang++
+ - COMPILER=clang++-5.0
- COMP=clang
+ - LDFLAGS=-fuse-ld=gold
- os: osx
compiler: gcc
@@ -44,30 +45,30 @@ before_script:
- cd src
script:
- #
- # checking bench for various build types
- #
- # obtain reference from git log
- - git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9][0-9]*\)/\1/g" > git_sig
+ # Obtain bench reference from git log
+ - git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9]*\).*/\1/g" > git_sig
- export benchref=$(cat git_sig)
- echo "Reference bench:" $benchref
- # verify against reference
- - make clean && make ARCH=x86-64 build > /dev/null && ../tests/signature.sh $benchref
- - make clean && make ARCH=x86-32 build > /dev/null && ../tests/signature.sh $benchref
- #
- # perft
- #
- - make clean && make ARCH=x86-64 build > /dev/null && ../tests/perft.sh
#
- # reproducible search
+ # Verify bench number against various builds
+ - export CXXFLAGS=-Werror
+ - make clean && make -j2 ARCH=x86-64 optimize=no debug=yes build && ../tests/signature.sh $benchref
+ - make clean && make -j2 ARCH=x86-32 optimize=no debug=yes build && ../tests/signature.sh $benchref
+ - make clean && make -j2 ARCH=x86-32 build && ../tests/signature.sh $benchref
+ - make clean && make -j2 ARCH=x86-64 build && ../tests/signature.sh $benchref
#
- - make clean && make ARCH=x86-64 build > /dev/null && ../tests/reprosearch.sh
+ # Check perft and reproducible search
+ - ../tests/perft.sh
+ - ../tests/reprosearch.sh
#
- # valgrind
+ # Valgrind
#
- - if [ -x "$(command -v valgrind )" ]; then make clean && make ARCH=x86-64 debug=yes optimize=no build > /dev/null && ../tests/instrumented.sh --valgrind; fi
+ - export CXXFLAGS=-O1
+ - if [ -x "$(command -v valgrind )" ]; then make clean && make -j2 ARCH=x86-64 debug=yes optimize=no build > /dev/null && ../tests/instrumented.sh --valgrind; fi
+ - if [ -x "$(command -v valgrind )" ]; then ../tests/instrumented.sh --valgrind-thread; fi
#
- # sanitizer
+ # Sanitizer
#
- # use g++-6 as a proxy for having sanitizers, might need revision as they become available for more recent versions of clang/gcc
- - if [[ "$COMPILER" == "g++-6" ]]; then make clean && make ARCH=x86-64 sanitize=yes build > /dev/null && ../tests/instrumented.sh --sanitizer; fi
+ # Use g++-6 as a proxy for having sanitizers, might need revision as they become available for more recent versions of clang/gcc
+ - if [[ "$COMPILER" == "g++-6" ]]; then make clean && make -j2 ARCH=x86-64 sanitize=undefined optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-undefined; fi
+ - if [[ "$COMPILER" == "g++-6" ]]; then make clean && make -j2 ARCH=x86-64 sanitize=thread optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-thread; fi
diff --git a/Engines/Linux32/mcbrain/AUTHORS b/Engines/Linux32/mcbrain/AUTHORS
index 3095efc..9b91b93 100644
--- a/Engines/Linux32/mcbrain/AUTHORS
+++ b/Engines/Linux32/mcbrain/AUTHORS
@@ -1,6 +1,5 @@
# Generated with 'git shortlog -sn | cut -c8-', which sorts by commits, manually ordered the first four authors, merged duplicates
-Michael Byrne (McBrain)
Tord Romstad
Marco Costalba (mcostalba)
Joona Kiiski (zamar)
@@ -95,4 +94,5 @@ ppigazzini
renouve
sf-x
thaspel
+unknown
diff --git a/Engines/Linux32/mcbrain/McBrain-9_x32_linux b/Engines/Linux32/mcbrain/McBrain-9_x32_linux
new file mode 100644
index 0000000..241f2bb
Binary files /dev/null and b/Engines/Linux32/mcbrain/McBrain-9_x32_linux differ
diff --git a/Engines/Linux32/mcbrain/Readme.md b/Engines/Linux32/mcbrain/Readme.md
index e3b36cc..46f2609 100644
--- a/Engines/Linux32/mcbrain/Readme.md
+++ b/Engines/Linux32/mcbrain/Readme.md
@@ -98,9 +98,9 @@ for a quick reference.
### Resource For Understanding the Code Base
-* [Chessprogramingwiki](https://chessprogramming.wikispaces.com) has good overall chess engines explanations
+* [Chess Programming Wiki](https://chessprogramming.wikispaces.com) has good overall chess engines explanations
(techniques used here are well explained like hash maps etc), it was
-also recommended by the [support at stockfish.](http://support.stockfishchess.org/discussions/questions/1132-how-to-understand-stockfish-sources)
+also recommended by the [support team at stockfish.](http://support.stockfishchess.org/discussions/questions/1132-how-to-understand-stockfish-sources)
* [Here](https://chessprogramming.wikispaces.com/Stockfish) you can find a set of features and techniques used by stockfish and each of them is explained at the wiki, however, it's a generic way rather than focusing on stockfish's own implementation, but it will still help you.
diff --git a/Engines/Linux32/mcbrain/Top CPU Contributors.txt b/Engines/Linux32/mcbrain/Top CPU Contributors.txt
index 0bb2a92..4c2aa47 100644
--- a/Engines/Linux32/mcbrain/Top CPU Contributors.txt
+++ b/Engines/Linux32/mcbrain/Top CPU Contributors.txt
@@ -1,93 +1,132 @@
-Contributors with >10,000 CPU hours as of November 3, 2016
+Contributors with >10,000 CPU hours as of January 23, 2018
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
+Username CPU Hours Games played
+mibere 518300 41835669
+crunchy 375564 29121434
+cw 371664 28748719
+fastgm 299773 20765374
+JojoM 220590 15299913
+glinscott 204517 13932027
+bking_US 187568 12233168
+ctoks 169342 13475495
+spams 149531 10940322
+Thanar 137015 11714855
+velislav 127305 10047749
+vdbergh 121741 9056874
+malala 117291 8126488
+vdv 117218 8289983
+leszek 114825 8331897
+dsmith 114010 7622414
+CSU_Dynasty 113516 9582758
+sqrt2 112407 8782694
+marrco 111143 8222921
+drabel 108168 9061580
+BrunoBanani 104938 7448565
+Data 94621 8433010
+CoffeeOne 90394 3964243
+BRAVONE 80811 5341681
+psk 77195 6156031
+brabos 70284 5685893
+Fisherman 66650 5572406
+nssy 64587 5369140
+Pking_cda 64499 5704075
+sterni1971 63488 5070004
+mgrabiak 62385 5420812
+tvijlbrief 58957 4154234
+jromang 58854 4704502
+dv8silencer 57421 3961325
+sunu 56620 4609155
+tinker 56039 4204914
+biffhero 55743 4810039
+teddybaer 52982 4740444
+bcross 50548 5071599
+renouve 50318 3544864
+Freja 50296 3805120
+robnjr 47504 4131742
+eva42 46542 4044694
+davar 46538 4030604
+finfish 46244 3481661
+rap 46201 3219490
+ttruscott 45037 3645430
+solarlight 44155 4074841
+TueRens 41372 3891510
+ElbertoOne 41321 3920894
+Antihistamine 39218 2792761
+mhunt 38991 2697512
+bigpen0r 37820 3149955
+homyur 35569 3009637
+VoyagerOne 35137 3302650
+mhoram 34770 2684128
+racerschmacer 33022 3231055
+speedycpu 32043 2531964
+EthanOConnor 31638 2143255
+oryx 29574 2767730
+Pyafue 28885 1986098
+jkiiski 28014 1923255
+Garf 27579 2770144
+slakovv 27017 2031279
+Bobo1239 27000 2488707
+pb00067 26817 2306694
+robal 26337 2316795
+hyperbolic.tom 26248 2200777
+rkl 24898 2236013
+SC 23988 2126825
+nabildanial 23524 1586321
+achambord 23495 1942546
+Sharaf_DG 22975 1790697
+chriswk 22876 1947731
+anst 22568 2013953
+Patrick_G 22435 1682293
+cuistot 22201 1383031
+gri 21901 1820968
+Prcuvu 21182 1890546
+Zirie 21171 1493227
+JanErik 20596 1791991
+Isidor 20560 1730290
+xor12 20535 1819280
+team-oh 20364 1653708
+nesoneg 20264 1493435
+rstoesser 19802 1335177
+grandphish2 19402 1834196
+sg4032 18427 1671742
+dew 18263 1423326
+ianh2105 18133 1668562
+MazeOfGalious 18022 1644593
+ville 17900 1539130
+j3corre 17607 975954
+eudhan 17502 1424648
+iisiraider 17175 1118788
+jundery 17172 1115855
+SFTUser 16635 1363975
+purplefishies 16621 1106850
+DragonLord 16599 1252348
+chris 15274 1575333
+xoto 14900 1486261
+dju 14861 901552
+dex 14647 1228763
+nordlandia 14551 1369718
+ronaldjerum 14361 1210607
+OssumOpossum 14149 1029265
+IgorLeMasson 13844 1228391
+enedene 13762 935618
+ako027ako 13442 1250249
+AdrianSA 13324 924980
+bpfliegel 13318 886523
+ncfish1 13056 932344
+wei 12863 1369596
+jpulman 12776 854815
+horst.prack 12436 1151505
+joster 12424 986622
+cisco2015 12265 1205019
+fatmurphy 12015 901134
+modolief 11228 926456
+Dark_wizzie 11214 1017910
+mschmidt 10973 818594
+eastorwest 10970 1117836
+infinity 10762 746397
+SapphireBrand 10692 1024604
+Thomas A. 10553 736094
+pgontarz 10294 878746
+Andrew Grant 10195 922933
+stocky 10083 718114
diff --git a/Engines/Linux32/mcbrain/appveyor.yml b/Engines/Linux32/mcbrain/appveyor.yml
index a46a0f3..c711dd6 100644
--- a/Engines/Linux32/mcbrain/appveyor.yml
+++ b/Engines/Linux32/mcbrain/appveyor.yml
@@ -1,5 +1,5 @@
version: 1.0.{build}
-clone_depth: 5
+clone_depth: 50
branches:
only:
@@ -13,10 +13,11 @@ os: Visual Studio 2015
platform:
- x86
- x64
- - Any CPU
# build Configuration, i.e. Debug, Release, etc.
-configuration: Debug
+configuration:
+ - Debug
+ - Release
matrix:
# The build fail immediately once one of the job fails
@@ -28,18 +29,43 @@ init:
- msbuild /version
before_build:
- - cd src
- - echo project (Stockfish) >> CMakeLists.txt
- - echo add_executable(stockfish benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp >> CMakeLists.txt
- - echo main.cpp material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp >> CMakeLists.txt
- - echo search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp syzygy/tbprobe.cpp) >> CMakeLists.txt
- - echo set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src) >> CMakeLists.txt
-# - echo target_compile_options(stockfish PUBLIC "/Ox") >> CMakeLists.txt
+ - ps: |
+ # Get sources
+ $src = get-childitem -Path *.cpp -Recurse | select -ExpandProperty FullName
+ $src = $src -join ' '
+ $src = $src.Replace("\", "/")
+
+ # Build CMakeLists.txt
+ $t = 'cmake_minimum_required(VERSION 3.8)',
+ 'project(Stockfish)',
+ 'set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src)',
+ 'set(source_files', $src, ')',
+ 'add_executable(stockfish ${source_files})'
+
+ # Write CMakeLists.txt withouth BOM
+ $MyPath = (Get-Item -Path "." -Verbose).FullName + '\CMakeLists.txt'
+ $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
+ [System.IO.File]::WriteAllLines($MyPath, $t, $Utf8NoBomEncoding)
+
+ # Obtain bench reference from git log
+ $b = git log HEAD | sls "\b[Bb]ench[ :]+[0-9]{7}" | select -first 1
+ $bench = $b -match '\D+(\d+)' | % { $matches[1] }
+ Write-Host "Reference bench:" $bench
+ $g = "Visual Studio 14 2015"
+ If (${env:PLATFORM} -eq 'x64') { $g = $g + ' Win64' }
+ cmake -G "${g}" .
+ Write-Host "Generated files for: " $g
build_script:
- - cmake -G "Visual Studio 14 2015 Win64" .
- - cmake --build .
+ - cmake --build . --config %CONFIGURATION% -- /verbosity:minimal
before_test:
- - cd Debug
- - stockfish.exe bench > null
+ - cd src/%CONFIGURATION%
+ - ps: |
+ # Verify bench number
+ ./stockfish bench 2> out.txt 1> null
+ $s = (gc "./out.txt" | out-string)
+ $r = ($s -match 'Nodes searched \D+(\d+)' | % { $matches[1] })
+ Write-Host "Engine bench:" $r
+ Write-Host "Reference bench:" $bench
+ If ($r -ne $bench) { exit 1 }
diff --git a/Engines/Linux32/mcbrain/src/Makefile b/Engines/Linux32/mcbrain/src/Makefile
index afd2f7c..6e66fbb 100644
--- a/Engines/Linux32/mcbrain/src/Makefile
+++ b/Engines/Linux32/mcbrain/src/Makefile
@@ -1,22 +1,24 @@
-# 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
.
-
-
+### ==========================================================================
+### Copyright Notice and License Information
+### ==========================================================================
+# McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+# Copyright (C) 2004-2008 Tord Romstad (Glaurung Author)
+# Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+# Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+# Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+# McBrain 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.
+
+# McBrain 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
.
### ==========================================================================
### Section 1. General Configuration
### ==========================================================================
@@ -28,8 +30,8 @@ ifeq ($(KERNEL),Linux)
endif
### Executable name
-EXE = SF-McBrain-27
-# bench = 5127083
+EXE = McBrain-9
+### bench nodes -> Nodes searched : 6871658
### Installation dir definitions
PREFIX = /usr/local
@@ -42,7 +44,7 @@ PGOBENCH2 = ./$(EXE) bench 16 2 10
### Object files
OBJS = benchmark.o bitbase.o bitboard.o endgame.o evaluate.o main.o \
material.o misc.o movegen.o movepick.o pawns.o position.o psqt.o \
- search.o thread.o timeman.o tt.o uci.o ucioption.o tbprobe.o tzbook.o
+ search.o thread.o timeman.o tt.o uci.o ucioption.o polybook.o tbprobe.o
### ==========================================================================
### Section 2. High-level Configuration
@@ -143,7 +145,7 @@ endif
### 3.1 Selecting compiler (default = gcc)
-CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -fno-rtti -std=c++11 $(EXTRACXXFLAGS)
+CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++11 $(EXTRACXXFLAGS)
DEPENDFLAGS += -std=c++11
LDFLAGS += $(EXTRALDFLAGS)
@@ -154,7 +156,7 @@ endif
ifeq ($(COMP),gcc)
comp=gcc
CXX=g++
- CXXFLAGS += -pedantic -Wextra -Wshadow -static-libstdc++
+ CXXFLAGS += -pedantic -Wextra -Wshadow
ifeq ($(ARCH),armv7)
ifeq ($(OS),Android)
@@ -207,7 +209,9 @@ ifeq ($(COMP),clang)
CXX=clang++
CXXFLAGS += -pedantic -Wextra -Wshadow
ifneq ($(KERNEL),Darwin)
+ifneq ($(KERNEL),OpenBSD)
LDFLAGS += -latomic
+endif
endif
ifeq ($(ARCH),armv7)
@@ -276,7 +280,7 @@ endif
### 3.3 Optimization
ifeq ($(optimize),yes)
- CXXFLAGS += -O3
+ CXXFLAGS += -O3 -mtune=native
ifeq ($(comp),gcc)
@@ -302,8 +306,6 @@ ifeq ($(optimize),yes)
ifeq ($(comp),clang)
ifeq ($(KERNEL),Darwin)
- CXXFLAGS += -flto
- LDFLAGS += $(CXXFLAGS)
ifeq ($(arch),i386)
CXXFLAGS += -mdynamic-no-pic
endif
@@ -349,24 +351,20 @@ endif
### 3.8 Link Time Optimization, it works since gcc 4.5 but not on mingw under Windows.
### This is a mix of compile and link time options because the lto link phase
### needs access to the optimization flags.
-ifeq ($(comp),gcc)
- ifeq ($(optimize),yes)
- ifeq ($(debug),no)
- CXXFLAGS += -flto -fno-rtti
+ifeq ($(optimize),yes)
+ifeq ($(debug), no)
+ ifeq ($(comp),$(filter $(comp),gcc clang))
+ CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS)
endif
- endif
-endif
-ifeq ($(comp),mingw)
+ ifeq ($(comp),mingw)
ifeq ($(KERNEL),Linux)
- ifeq ($(optimize),yes)
- ifeq ($(debug),no)
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS)
endif
endif
- endif
+endif
endif
### 3.9 Android 5 can only run position independent executables. Note that this
@@ -434,7 +432,6 @@ help:
build: config-sanity
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) all
strip $(EXE)
- cp $(EXE) /Users/michaelbyrne/cluster.mfb/$(EXE)
profile-build: config-sanity objclean profileclean
@echo ""
@@ -454,7 +451,12 @@ profile-build: config-sanity objclean profileclean
@echo "Step 5/5. Deleting profile data ..."
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) profileclean
strip $(EXE)
- cp $(EXE) /Users/michaelbyrne/cluster.mfb/$(EXE)
+
+cprom:
+ make -j profile-build ARCH=x86-64-modern COMP=clang
+
+cprob:
+ make -j profile-build ARCH=x86-64-bmi2 COMP=clang
strip:
strip $(EXE)
diff --git a/Engines/Linux32/mcbrain/src/benchmark.cpp b/Engines/Linux32/mcbrain/src/benchmark.cpp
index 75c7d1a..807f9de 100644
--- a/Engines/Linux32/mcbrain/src/benchmark.cpp
+++ b/Engines/Linux32/mcbrain/src/benchmark.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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
.
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
diff --git a/Engines/Linux32/mcbrain/src/bitbase.cpp b/Engines/Linux32/mcbrain/src/bitbase.cpp
index d206210..a651e27 100644
--- a/Engines/Linux32/mcbrain/src/bitbase.cpp
+++ b/Engines/Linux32/mcbrain/src/bitbase.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -111,7 +112,7 @@ namespace {
ksq[WHITE] = Square((idx >> 0) & 0x3F);
ksq[BLACK] = Square((idx >> 6) & 0x3F);
us = Color ((idx >> 12) & 0x01);
- psq = make_square(File((idx >> 13) & 0x3), RANK_7 - Rank((idx >> 15) & 0x7));
+ psq = make_square(File((idx >> 13) & 0x3), Rank(RANK_7 - ((idx >> 15) & 0x7)));
// Check if two pieces are on the same square or if a king can be captured
if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
diff --git a/Engines/Linux32/mcbrain/src/bitboard.cpp b/Engines/Linux32/mcbrain/src/bitboard.cpp
index e3c9140..9dd637b 100644
--- a/Engines/Linux32/mcbrain/src/bitboard.cpp
+++ b/Engines/Linux32/mcbrain/src/bitboard.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -54,7 +55,7 @@ namespace {
Bitboard RookTable[0x19000]; // To store rook attacks
Bitboard BishopTable[0x1480]; // To store bishop attacks
- void init_magics(Bitboard table[], Magic magics[], Square deltas[]);
+ void init_magics(Bitboard table[], Magic magics[], Direction directions[]);
// bsf_index() returns the index into BSFTable[] to look up the bitscan. Uses
// Matt Taylor's folding for 32 bit case, extended to 64 bit by Kim Walisch.
@@ -188,7 +189,7 @@ void Bitboards::init() {
for (Square s = SQ_A1; s <= SQ_H8; ++s)
for (int i = 0; steps[pt][i]; ++i)
{
- Square to = s + Square(c == WHITE ? steps[pt][i] : -steps[pt][i]);
+ Square to = s + Direction(c == WHITE ? steps[pt][i] : -steps[pt][i]);
if (is_ok(to) && distance(s, to) < 3)
{
@@ -199,11 +200,11 @@ void Bitboards::init() {
}
}
- Square RookDeltas[] = { NORTH, EAST, SOUTH, WEST };
- Square BishopDeltas[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
+ Direction RookDirections[] = { NORTH, EAST, SOUTH, WEST };
+ Direction BishopDirections[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
- init_magics(RookTable, RookMagics, RookDeltas);
- init_magics(BishopTable, BishopMagics, BishopDeltas);
+ init_magics(RookTable, RookMagics, RookDirections);
+ init_magics(BishopTable, BishopMagics, BishopDirections);
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
{
@@ -225,14 +226,14 @@ void Bitboards::init() {
namespace {
- Bitboard sliding_attack(Square deltas[], Square sq, Bitboard occupied) {
+ Bitboard sliding_attack(Direction directions[], Square sq, Bitboard occupied) {
Bitboard attack = 0;
for (int i = 0; i < 4; ++i)
- for (Square s = sq + deltas[i];
- is_ok(s) && distance(s, s - deltas[i]) == 1;
- s += deltas[i])
+ for (Square s = sq + directions[i];
+ is_ok(s) && distance(s, s - directions[i]) == 1;
+ s += directions[i])
{
attack |= s;
@@ -249,7 +250,7 @@ namespace {
// chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
// use the so called "fancy" approach.
- void init_magics(Bitboard table[], Magic magics[], Square deltas[]) {
+ void init_magics(Bitboard table[], Magic magics[], Direction directions[]) {
// Optimal PRNG seeds to pick the correct magics in the shortest time
int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 },
@@ -269,7 +270,7 @@ namespace {
// the number of 1s of the mask. Hence we deduce the size of the shift to
// apply to the 64 or 32 bits word to get the index.
Magic& m = magics[s];
- m.mask = sliding_attack(deltas, s, 0) & ~edges;
+ m.mask = sliding_attack(directions, s, 0) & ~edges;
m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
// Set the offset for the attacks table of the square. We have individual
@@ -281,7 +282,7 @@ namespace {
b = size = 0;
do {
occupancy[size] = b;
- reference[size] = sliding_attack(deltas, s, b);
+ reference[size] = sliding_attack(directions, s, b);
if (HasPext)
m.attacks[pext(b, m.mask)] = reference[size];
diff --git a/Engines/Linux32/mcbrain/src/bitboard.h b/Engines/Linux32/mcbrain/src/bitboard.h
index c9f199e..c964d1e 100644
--- a/Engines/Linux32/mcbrain/src/bitboard.h
+++ b/Engines/Linux32/mcbrain/src/bitboard.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 BITBOARD_H_INCLUDED
#define BITBOARD_H_INCLUDED
@@ -126,11 +127,10 @@ inline Bitboard& operator^=(Bitboard& b, Square s) {
return b ^= SquareBB[s];
}
-inline bool more_than_one(Bitboard b) {
+constexpr bool more_than_one(Bitboard b) {
return b & (b - 1);
}
-
/// rank_bb() and file_bb() return a bitboard representing all the squares on
/// the given file or rank.
@@ -153,8 +153,8 @@ inline Bitboard file_bb(Square s) {
/// shift() moves a bitboard one step along direction D. Mainly for pawns
-template
-inline Bitboard shift(Bitboard b) {
+template
+constexpr 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
diff --git a/Engines/Linux32/mcbrain/src/endgame.cpp b/Engines/Linux32/mcbrain/src/endgame.cpp
index ca17f6a..3d568f5 100644
--- a/Engines/Linux32/mcbrain/src/endgame.cpp
+++ b/Engines/Linux32/mcbrain/src/endgame.cpp
@@ -1,23 +1,23 @@
/*
- 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-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
- 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 .
-*/
-
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -524,7 +524,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const {
Square bsq = pos.square(weakSide);
Square psq = pos.square(strongSide);
Rank rk = relative_rank(strongSide, psq);
- Square push = pawn_push(strongSide);
+ Direction push = pawn_push(strongSide);
// If the pawn is on the 5th rank and the pawn (currently) is on
// the same color square as the bishop then there is a chance of
diff --git a/Engines/Linux32/mcbrain/src/endgame.h b/Engines/Linux32/mcbrain/src/endgame.h
index 3d61207..3bace6f 100644
--- a/Engines/Linux32/mcbrain/src/endgame.h
+++ b/Engines/Linux32/mcbrain/src/endgame.h
@@ -1,22 +1,24 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+
+ McBrain 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.
+
+ McBrain 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 ENDGAME_H_INCLUDED
#define ENDGAME_H_INCLUDED
diff --git a/Engines/Linux32/mcbrain/src/evaluate.cpp b/Engines/Linux32/mcbrain/src/evaluate.cpp
index 7ee3652..e420d3d 100644
--- a/Engines/Linux32/mcbrain/src/evaluate.cpp
+++ b/Engines/Linux32/mcbrain/src/evaluate.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -31,12 +32,21 @@
namespace {
+ const Bitboard Center = (FileDBB | FileEBB) & (Rank4BB | Rank5BB);
+ const Bitboard QueenSide = FileABB | FileBBB | FileCBB | FileDBB;
+ const Bitboard CenterFiles = FileCBB | FileDBB | FileEBB | FileFBB;
+ const Bitboard KingSide = FileEBB | FileFBB | FileGBB | FileHBB;
+
+ const Bitboard KingFlank[FILE_NB] = {
+ QueenSide, QueenSide, QueenSide, CenterFiles, CenterFiles, KingSide, KingSide, KingSide
+ };
+
namespace Trace {
enum Tracing {NO_TRACE, TRACE};
enum Term { // The first 8 entries are for PieceType
- MATERIAL = 8, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, TOTAL, TERM_NB
+ MATERIAL = 8, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, INITIATIVE, TOTAL, TERM_NB
};
double scores[TERM_NB][COLOR_NB][PHASE_NB];
@@ -54,7 +64,7 @@ namespace {
std::ostream& operator<<(std::ostream& os, Term t) {
- if (t == MATERIAL || t == IMBALANCE || t == Term(PAWN) || t == TOTAL)
+ if (t == MATERIAL || t == IMBALANCE || t == Term(PAWN) || t == INITIATIVE || t == TOTAL)
os << " --- --- | --- --- | ";
else
os << std::setw(5) << scores[t][WHITE][MG] << " "
@@ -88,6 +98,7 @@ namespace {
template void initialize();
template Score evaluate_king();
template Score evaluate_threats();
+ int king_distance(Color c, Square s);
template Score evaluate_passed_pawns();
template Score evaluate_space();
template Score evaluate_pieces();
@@ -102,7 +113,8 @@ namespace {
Score mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO };
// attackedBy[color][piece type] is a bitboard representing all squares
- // attacked by a given color and piece type (can be also ALL_PIECES).
+ // attacked by a given color and piece type. Special "piece types" which are
+ // also calculated are QUEEN_DIAGONAL and ALL_PIECES.
Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB];
// attackedBy2[color] are the squares attacked by 2 pieces of a given color,
@@ -162,8 +174,8 @@ namespace {
// supported by a pawn. If the minor piece occupies an outpost square
// then score is doubled.
const Score Outpost[][2] = {
- { S(22, 6), S(33, 9) }, // Knight
- { S( 9, 2), S(14, 4) } // Bishop
+ { S(22, 6), S(36,12) }, // Knight
+ { S( 9, 2), S(15, 5) } // Bishop
};
// RookOnFile[semiopen/open] contains bonuses for each rook when there is no
@@ -174,23 +186,23 @@ namespace {
// 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)
- };
+ S(0, 0), S(0, 31), S(39, 42), S(57, 44), S(68, 112), S(47, 120)
+ }; //Fauzi Akram
const Score ThreatByRook[PIECE_TYPE_NB] = {
- S(0, 0), S(0, 25), S(40, 62), S(40, 59), S(0, 34), S(35, 48)
- };
+ S(0, 0), S(0, 24), S(38, 71), S(38, 61), S(0, 38), S(36, 38)
+ }; //Fauzi Akram
// ThreatByKing[on one/on many] contains bonuses for king attacks on
// pawns or pieces which are not pawn-defended.
- const Score ThreatByKing[] = { S(3, 62), S(9, 138) };
+ const Score ThreatByKing[] = { S(3, 65), S(9, 145) }; //Fauzi Akram
// Passed[mg/eg][Rank] contains midgame and endgame bonuses for passed pawns.
// We don't use a Score because we process the two components independently.
const Value Passed[][RANK_NB] = {
- { V(5), V( 5), V(31), V(73), V(166), V(252) },
- { V(7), V(14), V(38), V(73), V(166), V(252) }
- };
+ { V(0), V(5), V( 5), V(32), V(70), V(172), V(217) },
+ { V(0), V(7), V(13), V(42), V(70), V(170), V(269) }
+ }; //Fauzi Akram
// PassedFile[File] contains a bonus according to the file of a passed pawn
const Score PassedFile[FILE_NB] = {
@@ -198,25 +210,29 @@ namespace {
S(-20,-12), S( 1, -8), S( 2, 10), S( 9, 10)
};
+ // Rank factor applied on some bonus for passed pawn on rank 4 or beyond
+ const int RankFactor[RANK_NB] = {0, 0, 0, 2, 7, 12, 19}; //Fauzi Akram
+
// KingProtector[PieceType-2] contains a bonus according to distance from king
const Score KingProtector[] = { S(-3, -5), S(-4, -3), S(-3, 0), S(-1, 1) };
// Assorted bonuses and penalties used by evaluation
- const Score MinorBehindPawn = S( 16, 0);
- const Score BishopPawns = S( 8, 12);
- const Score RookOnPawn = S( 8, 24);
- const Score TrappedRook = S( 92, 0);
- 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 ThreatBySafePawn = S(182,175);
- const Score ThreatByRank = S( 16, 3);
- const Score Hanging = S( 48, 27);
- const Score ThreatByPawnPush = S( 38, 22);
- const Score HinderPassedPawn = S( 7, 0);
- const Score TrappedBishopA1H1 = S( 50, 50);
+ const Score MinorBehindPawn = S( 16, 0);
+ const Score BishopPawns = S( 8, 12);
+ const Score LongRangedBishop = S( 22, 0);
+ const Score RookOnPawn = S( 8, 24);
+ const Score TrappedRook = S( 92, 0);
+ const Score WeakQueen = S( 50, 10);
+ const Score CloseEnemies = S( 7, 0);
+ const Score PawnlessFlank = S( 20, 80);
+ const Score ThreatBySafePawn = S(175,168); //Fauzi Akram
+ const Score ThreatByRank = S( 16, 3);
+ const Score Hanging = S( 52, 30); //Fauzi Akram
+ const Score WeakUnopposedPawn = S( 5, 25);
+ const Score ThreatByPawnPush = S( 47, 26); //Fauzi Akram
+ const Score ThreatByAttackOnQueen = S( 42, 21); //Fauzi Akram
+ const Score HinderPassedPawn = S( 8, 1); //Fauzi Akram
+ const Score TrappedBishopA1H1 = S( 50, 50);
#undef S
#undef V
@@ -225,10 +241,10 @@ namespace {
const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 78, 56, 45, 11 };
// Penalties for enemy's safe checks
- const int QueenCheck = 780;
- const int RookCheck = 880;
- const int BishopCheck = 435;
- const int KnightCheck = 790;
+ const int QueenSafeCheck = 780;
+ const int RookSafeCheck = 880;
+ const int BishopSafeCheck = 435;
+ const int KnightSafeCheck = 790;
// Threshold for lazy and space evaluation
const Value LazyThreshold = Value(1500);
@@ -241,9 +257,9 @@ namespace {
template template
void Evaluation::initialize() {
- const Color Them = (Us == WHITE ? BLACK : WHITE);
- const Square Up = (Us == WHITE ? NORTH : SOUTH);
- const Square Down = (Us == WHITE ? SOUTH : NORTH);
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const Direction Up = (Us == WHITE ? NORTH : SOUTH);
+ const Direction 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
@@ -284,6 +300,7 @@ namespace {
const Color Them = (Us == WHITE ? BLACK : WHITE);
const Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB
: Rank5BB | Rank4BB | Rank3BB);
+ const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
const Square* pl = pos.squares(Us);
Bitboard b, bb;
@@ -292,11 +309,14 @@ namespace {
attackedBy[Us][Pt] = 0;
+ if (Pt == QUEEN)
+ attackedBy[Us][QUEEN_DIAGONAL] = 0;
+
while ((s = *pl++) != SQ_NONE)
{
// Find attacked squares, including x-ray attacks for bishops and rooks
- b = Pt == BISHOP ? attacks_bb(s, pos.pieces() ^ pos.pieces(Us, QUEEN))
- : Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(Us, ROOK, QUEEN))
+ b = Pt == BISHOP ? attacks_bb(s, pos.pieces() ^ pos.pieces(QUEEN))
+ : Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(QUEEN) ^ pos.pieces(Us, ROOK))
: pos.attacks_from(s);
if (pos.pinned_pieces(Us) & s)
@@ -305,6 +325,9 @@ namespace {
attackedBy2[Us] |= attackedBy[Us][ALL_PIECES] & b;
attackedBy[Us][ALL_PIECES] |= attackedBy[Us][Pt] |= b;
+ if (Pt == QUEEN)
+ attackedBy[Us][QUEEN_DIAGONAL] |= b & PseudoAttacks[BISHOP][s];
+
if (b & kingRing[Them])
{
kingAttackersCount[Us]++;
@@ -324,12 +347,12 @@ namespace {
// Bonus for outpost squares
bb = OutpostRanks & ~pe->pawn_attacks_span(Them);
if (bb & s)
- score += Outpost[Pt == BISHOP][!!(attackedBy[Us][PAWN] & s)] * 2;
+ score += Outpost[Pt == BISHOP][bool(attackedBy[Us][PAWN] & s)] * 2;
else
{
bb &= b & ~pos.pieces(Us);
if (bb)
- score += Outpost[Pt == BISHOP][!!(attackedBy[Us][PAWN] & bb)];
+ score += Outpost[Pt == BISHOP][bool(attackedBy[Us][PAWN] & bb)];
}
// Bonus when behind a pawn
@@ -337,10 +360,16 @@ namespace {
&& (pos.pieces(PAWN) & (s + pawn_push(Us))))
score += MinorBehindPawn;
- // Penalty for pawns on the same color square as the bishop
if (Pt == BISHOP)
+ {
+ // Penalty for pawns on the same color square as the bishop
score -= BishopPawns * pe->pawns_on_same_color_squares(Us, s);
+ // Bonus for bishop on a long diagonal which can "see" both center squares
+ if (more_than_one(Center & (attacks_bb(s, pos.pieces(PAWN)) | s)))
+ score += LongRangedBishop;
+ }
+
// An important Chess960 pattern: A cornered bishop blocked by a friendly
// pawn diagonally in front of it is a very serious problem, especially
// when that pawn is also blocked.
@@ -348,7 +377,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 ? EAST : WEST);
+ Direction 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
@@ -364,7 +393,7 @@ namespace {
// Bonus when on an open or semi-open file
if (pe->semiopen_file(Us, file_of(s)))
- score += RookOnFile[!!pe->semiopen_file(Them, file_of(s))];
+ score += RookOnFile[bool(pe->semiopen_file(Them, file_of(s)))];
// Penalty when trapped by the king, even more if the king cannot castle
else if (mob <= 3)
@@ -375,6 +404,9 @@ namespace {
&& !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));
}
+ // Bonus when rook can see the enemy back rank and has enough mobility.
+ else if (relative_rank(Us, s) <= RANK_5 && (pos.attacks_from(s) & TRank8BB))
+ score += RookOnFile[0];
}
if (Pt == QUEEN)
@@ -395,119 +427,98 @@ namespace {
// evaluate_king() assigns bonuses and penalties to a king of a given color
- const Bitboard QueenSide = FileABB | FileBBB | FileCBB | FileDBB;
- const Bitboard CenterFiles = FileCBB | FileDBB | FileEBB | FileFBB;
- const Bitboard KingSide = FileEBB | FileFBB | FileGBB | FileHBB;
-
- const Bitboard KingFlank[FILE_NB] = {
- QueenSide, QueenSide, QueenSide, CenterFiles, CenterFiles, KingSide, KingSide, KingSide
- };
-
template template
Score Evaluation::evaluate_king() {
- const Color Them = (Us == WHITE ? BLACK : WHITE);
- const Square Up = (Us == WHITE ? NORTH : SOUTH);
- const Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
- : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
+ : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
const Square ksq = pos.square(Us);
- Bitboard kingOnlyDefended, undefended, b, b1, b2, safe, other;
- int kingDanger;
+ Bitboard weak, b, b1, b2, safe, unsafeChecks;
// King shelter and enemy pawns storm
Score score = pe->king_safety(pos, ksq);
+ // King tropism: firstly, find squares that opponent attacks in our king flank
+ File kf = file_of(ksq);
+ b = 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));
+
+ // Secondly, add the squares which are attacked twice in that flank and
+ // which are not defended by our pawns.
+ b = (Us == WHITE ? b << 4 : b >> 4)
+ | (b & attackedBy2[Them] & ~attackedBy[Us][PAWN]);
+
+ int tropism = popcount(b);
+
// Main king safety evaluation
if (kingAttackersCount[Them] > (1 - pos.count(Them)))
{
- // Find the attacked squares which are defended only by our king...
- kingOnlyDefended = attackedBy[Them][ALL_PIECES]
- & attackedBy[Us][KING]
- & ~attackedBy2[Us];
-
- // ... and those which are not defended at all in the larger king ring
- undefended = attackedBy[Them][ALL_PIECES]
- & ~attackedBy[Us][ALL_PIECES]
- & kingRing[Us]
- & ~pos.pieces(Them);
-
- // 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 weak squares around our king, the absence of queen and
- // the quality of the pawn shelter (current 'score' value).
- kingDanger = kingAttackersCount[Them] * kingAttackersWeight[Them]
- + 102 * kingAdjacentZoneAttacksCount[Them]
- + 191 * popcount(kingOnlyDefended | undefended)
- + 143 * !!pos.pinned_pieces(Us)
- - 848 * !pos.count(Them)
- - 9 * mg_value(score) / 8
- + 40;
+ // Attacked squares defended at most once by our queen or king
+ weak = attackedBy[Them][ALL_PIECES]
+ & ~attackedBy2[Us]
+ & (attackedBy[Us][KING] | attackedBy[Us][QUEEN] | ~attackedBy[Us][ALL_PIECES]);
+
+ int kingDanger = unsafeChecks = 0;
// Analyse the safe enemy's checks which are possible on next move
safe = ~pos.pieces(Them);
- safe &= ~attackedBy[Us][ALL_PIECES] | (kingOnlyDefended & attackedBy2[Them]);
+ safe &= ~attackedBy[Us][ALL_PIECES] | (weak & attackedBy2[Them]);
- b1 = pos.attacks_from< ROOK>(ksq);
- b2 = pos.attacks_from(ksq);
+ b1 = attacks_bb(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
+ b2 = attacks_bb(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
// Enemy queen safe checks
- if ((b1 | b2) & attackedBy[Them][QUEEN] & safe)
- kingDanger += QueenCheck;
-
- // For minors and rooks, also consider the square safe if attacked twice,
- // and only defended by our queen.
- safe |= attackedBy2[Them]
- & ~(attackedBy2[Us] | pos.pieces(Them))
- & 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 = ~( attackedBy[Us][PAWN]
- | (pos.pieces(Them, PAWN) & shift(pos.pieces(PAWN))));
+ if ((b1 | b2) & attackedBy[Them][QUEEN] & safe & ~attackedBy[Us][QUEEN])
+ kingDanger += QueenSafeCheck;
- // Enemy rooks safe and other checks
- if (b1 & attackedBy[Them][ROOK] & safe)
- kingDanger += RookCheck;
+ b1 &= attackedBy[Them][ROOK];
+ b2 &= attackedBy[Them][BISHOP];
- else if (b1 & attackedBy[Them][ROOK] & other)
- score -= OtherCheck;
+ // Enemy rooks checks
+ if (b1 & safe)
+ kingDanger += RookSafeCheck;
+ else
+ unsafeChecks |= b1;
- // Enemy bishops safe and other checks
- if (b2 & attackedBy[Them][BISHOP] & safe)
- kingDanger += BishopCheck;
+ // Enemy bishops checks
+ if (b2 & safe)
+ kingDanger += BishopSafeCheck;
+ else
+ unsafeChecks |= b2;
- else if (b2 & attackedBy[Them][BISHOP] & other)
- score -= OtherCheck;
-
- // Enemy knights safe and other checks
+ // Enemy knights checks
b = pos.attacks_from(ksq) & attackedBy[Them][KNIGHT];
if (b & safe)
- kingDanger += KnightCheck;
-
- else if (b & other)
- score -= OtherCheck;
-
- // Transform the kingDanger units into a Score, and substract it from the evaluation
+ kingDanger += KnightSafeCheck;
+ else
+ unsafeChecks |= b;
+
+ // Unsafe or occupied checking squares will also be considered, as long as
+ // the square is in the attacker's mobility area.
+ unsafeChecks &= mobilityArea[Them];
+
+ kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
+ + 102 * kingAdjacentZoneAttacksCount[Them]
+ + 191 * popcount(kingRing[Us] & weak)
+ + 143 * popcount(pos.pinned_pieces(Us) | unsafeChecks)
+ - 848 * !pos.count(Them)
+ - 9 * mg_value(score) / 8
+ + 4 * tropism;
+
+ // Transform the kingDanger units into a Score, and subtract it from the evaluation
if (kingDanger > 0)
+ {
+ int mobilityDanger = (mg_value(mobility[Them] - mobility[Us])) * 2;
+ kingDanger = std::max(0, kingDanger + mobilityDanger);
score -= make_score(kingDanger * kingDanger / 4096, kingDanger / 16);
+ }
}
- // King tropism: firstly, find squares that opponent attacks in our king flank
- File kf = file_of(ksq);
- b = 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));
-
- // Secondly, add the squares which are attacked twice in that flank and
- // which are not defended by our pawns.
- b = (Us == WHITE ? b << 4 : b >> 4)
- | (b & attackedBy2[Them] & ~attackedBy[Us][PAWN]);
-
- score -= CloseEnemies * popcount(b);
+ score -= CloseEnemies * tropism;
// Penalty when our king is on a pawnless flank
if (!(pos.pieces(PAWN) & KingFlank[kf]))
@@ -526,11 +537,11 @@ namespace {
template template
Score Evaluation::evaluate_threats() {
- 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 TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const Direction Up = (Us == WHITE ? NORTH : SOUTH);
+ const Direction Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
+ const Direction Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
+ const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
Bitboard b, weak, defended, stronglyProtected, safeThreats;
Score score = SCORE_ZERO;
@@ -546,9 +557,6 @@ namespace {
safeThreats = (shift(b) | shift(b)) & weak;
score += ThreatBySafePawn * popcount(safeThreats);
-
- if (weak ^ safeThreats)
- score += ThreatByHangingPawn;
}
// Squares strongly protected by the opponent, either because they attack the
@@ -593,6 +601,10 @@ namespace {
score += ThreatByKing[more_than_one(b)];
}
+ // Bonus for opponent unopposed weak pawns
+ if (pos.pieces(Us, ROOK, QUEEN))
+ score += WeakUnopposedPawn * pe->weak_unopposed(Them);
+
// Find squares where our pawns can push on the next move
b = shift(pos.pieces(Us, PAWN)) & ~pos.pieces();
b |= shift(b & TRank3BB) & ~pos.pieces();
@@ -608,12 +620,24 @@ namespace {
score += ThreatByPawnPush * popcount(b);
+ // Add a bonus for safe slider attack threats on opponent queen
+ safeThreats = ~pos.pieces(Us) & ~attackedBy2[Them] & attackedBy2[Us];
+ b = (attackedBy[Us][BISHOP] & attackedBy[Them][QUEEN_DIAGONAL])
+ | (attackedBy[Us][ROOK ] & attackedBy[Them][QUEEN] & ~attackedBy[Them][QUEEN_DIAGONAL]);
+
+ score += ThreatByAttackOnQueen * popcount(b & safeThreats);
+
if (T)
Trace::add(THREAT, Us, score);
return score;
}
+ // helper used by evaluate_passed_pawns to cap the distance
+ template
+ int Evaluation::king_distance(Color c, Square s) {
+ return std::min(distance(pos.square(c), s), 5);
+ }
// evaluate_passed_pawns() evaluates the passed pawns and candidate passed
// pawns of the given color.
@@ -621,8 +645,8 @@ namespace {
template template
Score Evaluation::evaluate_passed_pawns() {
- const Color Them = (Us == WHITE ? BLACK : WHITE);
- const Square Up = (Us == WHITE ? NORTH : SOUTH);
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const Direction Up = (Us == WHITE ? NORTH : SOUTH);
Bitboard b, bb, squaresToQueen, defendedSquares, unsafeSquares;
Score score = SCORE_ZERO;
@@ -638,8 +662,8 @@ namespace {
bb = forward_file_bb(Us, s) & (attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
score -= HinderPassedPawn * popcount(bb);
- int r = relative_rank(Us, s) - RANK_2;
- int rr = r * (r - 1);
+ int r = relative_rank(Us, s);
+ int rr = RankFactor[r];
Value mbonus = Passed[MG][r], ebonus = Passed[EG][r];
@@ -648,12 +672,11 @@ namespace {
Square blockSq = s + Up;
// Adjust bonus based on the king's proximity
- ebonus += distance(pos.square(Them), blockSq) * 5 * rr
- - distance(pos.square( Us), blockSq) * 2 * rr;
+ ebonus += (king_distance(Them, blockSq) * 5 - king_distance(Us, blockSq) * 2) * rr;
// If blockSq is not the queening square then consider also a second push
- if (relative_rank(Us, blockSq) != RANK_8)
- ebonus -= distance(pos.square(Us), blockSq + Up) * rr;
+ if (r != RANK_7)
+ ebonus -= king_distance(Us, blockSq + Up) * rr;
// If the pawn is free to advance, then increase the bonus
if (pos.empty(blockSq))
@@ -673,7 +696,7 @@ namespace {
// If there aren't any enemy attacks, assign a big bonus. Otherwise
// assign a smaller bonus if the block square isn't attacked.
- int k = !unsafeSquares ? 18 : !(unsafeSquares & blockSq) ? 8 : 0;
+ int k = !unsafeSquares ? 20 : !(unsafeSquares & blockSq) ? 9 : 0; //Fauzi Akram
// If the path to the queen is fully defended, assign a big bonus.
// Otherwise assign a smaller bonus if the block square is defended.
@@ -762,6 +785,9 @@ namespace {
// that the endgame score will never change sign after the bonus.
int v = ((eg > 0) - (eg < 0)) * std::max(initiative, -abs(eg));
+ if (T)
+ Trace::add(INITIATIVE, make_score(0, v));
+
return make_score(0, v);
}
@@ -822,7 +848,7 @@ namespace {
// 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() + me->imbalance();
+ Score score = pos.psq_score() + me->imbalance() + Eval::Contempt;
// Probe the pawn hash table
pe = Pawns::probe(pos);
@@ -880,18 +906,19 @@ namespace {
Trace::add(TOTAL, score);
}
- return (pos.side_to_move() == WHITE ? v : -v) + Eval::Tempo; // Side to move point of view
+ return pos.side_to_move() == WHITE ? v : -v; // Side to move point of view
}
} // namespace
+Score Eval::Contempt = SCORE_ZERO;
/// evaluate() is the evaluator for the outer world. It returns a static evaluation
/// of the position from the point of view of the side to move.
Value Eval::evaluate(const Position& pos)
{
- return Evaluation<>(pos).value();
+ return Evaluation<>(pos).value() + Eval::Tempo;
}
/// trace() is like evaluate(), but instead of returning a value, it returns
@@ -902,7 +929,7 @@ std::string Eval::trace(const Position& pos) {
std::memset(scores, 0, sizeof(scores));
- Value v = Evaluation(pos).value();
+ Value v = Evaluation(pos).value() + Eval::Tempo;
v = pos.side_to_move() == WHITE ? v : -v; // White's point of view
std::stringstream ss;
@@ -922,6 +949,7 @@ std::string Eval::trace(const Position& pos) {
<< " Threats | " << Term(THREAT)
<< " Passed pawns | " << Term(PASSED)
<< " Space | " << Term(SPACE)
+ << " Initiative | " << Term(INITIATIVE)
<< "----------------+-------------+-------------+-------------\n"
<< " Total | " << Term(TOTAL);
diff --git a/Engines/Linux32/mcbrain/src/evaluate.h b/Engines/Linux32/mcbrain/src/evaluate.h
index 95a1f19..8d388fa 100644
--- a/Engines/Linux32/mcbrain/src/evaluate.h
+++ b/Engines/Linux32/mcbrain/src/evaluate.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 EVALUATE_H_INCLUDED
#define EVALUATE_H_INCLUDED
@@ -31,6 +32,8 @@ namespace Eval {
const Value Tempo = Value(20); // Must be visible to search
+extern Score Contempt;
+
std::string trace(const Position& pos);
Value evaluate(const Position& pos);
diff --git a/Engines/Linux32/mcbrain/src/main.cpp b/Engines/Linux32/mcbrain/src/main.cpp
index 5c2810e..637dc3b 100644
--- a/Engines/Linux32/mcbrain/src/main.cpp
+++ b/Engines/Linux32/mcbrain/src/main.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -27,7 +28,7 @@
#include "tt.h"
#include "uci.h"
#include "tbprobe.h"
-#include "tzbook.h"
+#include "polybook.h"
namespace PSQT {
void init();
@@ -44,13 +45,14 @@ int main(int argc, char* argv[]) {
Bitbases::init();
Search::init();
Pawns::init();
+ polybook.init(Options["BookFile"]);
Tablebases::init(Options["SyzygyPath"]);
TT.resize(Options["Hash"]);
- Threads.init(Options["Threads"]);
+ Threads.set(Options["Threads"]);
Search::clear(); // After threads are up
UCI::loop(argc, argv);
- Threads.exit();
+ Threads.set(0);
return 0;
}
diff --git a/Engines/Linux32/mcbrain/src/material.cpp b/Engines/Linux32/mcbrain/src/material.cpp
index d67b95c..2b28837 100644
--- a/Engines/Linux32/mcbrain/src/material.cpp
+++ b/Engines/Linux32/mcbrain/src/material.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 // For std::min
#include
@@ -39,7 +40,7 @@ namespace {
{ 32, 255, -3 }, // Knight OUR PIECES
{ 0, 104, 4, 0 }, // Bishop
{ -26, -2, 47, 105, -149 }, // Rook
- {-185, 24, 122, 137, -134, 0 } // Queen
+ {-189, 24, 117, 133, -134, -10 } // Queen
};
const int QuadraticTheirs[][PIECE_TYPE_NB] = {
@@ -50,18 +51,7 @@ namespace {
{ 9, 63, 0 }, // Knight OUR PIECES
{ 59, 65, 42, 0 }, // Bishop
{ 46, 39, 24, -24, 0 }, // Rook
- { 101, 100, -37, 141, 268, 0 } // Queen
- };
-
- // PawnSet[pawn count] contains a bonus/malus indexed by number of pawns
- const int PawnSet[] = {
- 24, -32, 107, -51, 117, -9, -126, -21, 31
- };
-
- // QueenMinorsImbalance[opp_minor_count] is applied when only one side has a queen.
- // It contains a bonus/malus for the side with the queen.
- const int QueenMinorsImbalance[13] = {
- 31, -8, -15, -25, -5
+ { 97, 100, -42, 137, 268, 0 } // Queen
};
// Endgame evaluation and scaling functions are accessed directly and not through
@@ -100,9 +90,9 @@ namespace {
const Color Them = (Us == WHITE ? BLACK : WHITE);
- int bonus = PawnSet[pieceCount[Us][PAWN]];
+ int bonus = 0;
- // Second-degree polynomial material imbalance by Tord Romstad
+ // Second-degree polynomial material imbalance, by Tord Romstad
for (int pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1)
{
if (!pieceCount[Us][pt1])
@@ -117,10 +107,6 @@ namespace {
bonus += pieceCount[Us][pt1] * v;
}
- // Special handling of Queen vs. Minors
- if (pieceCount[Us][QUEEN] == 1 && pieceCount[Them][QUEEN] == 0)
- bonus += QueenMinorsImbalance[pieceCount[Them][KNIGHT] + pieceCount[Them][BISHOP]];
-
return bonus;
}
diff --git a/Engines/Linux32/mcbrain/src/material.h b/Engines/Linux32/mcbrain/src/material.h
index ccf97b7..95d6c84 100644
--- a/Engines/Linux32/mcbrain/src/material.h
+++ b/Engines/Linux32/mcbrain/src/material.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 MATERIAL_H_INCLUDED
#define MATERIAL_H_INCLUDED
diff --git a/Engines/Linux32/mcbrain/src/misc.cpp b/Engines/Linux32/mcbrain/src/misc.cpp
index 16dc981..a14d9c4 100644
--- a/Engines/Linux32/mcbrain/src/misc.cpp
+++ b/Engines/Linux32/mcbrain/src/misc.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 .
+ */
#ifdef _WIN32
#if _WIN32_WINNT < 0x0601
@@ -51,7 +52,7 @@ namespace {
/// Version number. If Version is left empty, then compile date in the format
/// DD-MM-YY and show in engine_info.
-const string Version = "v2.7";
+const string Version = "9";
/// 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
@@ -122,7 +123,7 @@ const string engine_info(bool to_uci) {
string month, day, year;
stringstream ss, date(__DATE__); // From compiler, format is "Sep 21 2008"
- ss << "SF-McBrain " << Version << setfill('0');
+ ss << "McBrain " << Version << setfill('0');
if (Version.empty())
{
@@ -133,7 +134,7 @@ const string engine_info(bool to_uci) {
ss << (Is64Bit ? " 64" : "")
<< (HasPext ? " BMI2" : (HasPopCnt ? " POPCNT" : ""))
<< (to_uci ? "\nid author ": " by ")
- << "M. Byrne based on Stockfish";
+ << "M. Byrne, Stockfish authors and others";
return ss.str();
}
@@ -293,14 +294,6 @@ int get_group(size_t idx) {
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);
diff --git a/Engines/Linux32/mcbrain/src/misc.h b/Engines/Linux32/mcbrain/src/misc.h
index b63e613..98b5202 100644
--- a/Engines/Linux32/mcbrain/src/misc.h
+++ b/Engines/Linux32/mcbrain/src/misc.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 MISC_H_INCLUDED
#define MISC_H_INCLUDED
diff --git a/Engines/Linux32/mcbrain/src/movegen.cpp b/Engines/Linux32/mcbrain/src/movegen.cpp
index 465d616..d06bc86 100644
--- a/Engines/Linux32/mcbrain/src/movegen.cpp
+++ b/Engines/Linux32/mcbrain/src/movegen.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -42,8 +43,8 @@ namespace {
assert(!pos.checkers());
- const Square K = Chess960 ? kto > kfrom ? WEST : EAST
- : KingSide ? WEST : EAST;
+ const Direction K = Chess960 ? kto > kfrom ? WEST : EAST
+ : KingSide ? WEST : EAST;
for (Square s = kto; s != kfrom; s += K)
if (pos.attackers_to(s) & enemies)
@@ -65,7 +66,7 @@ namespace {
}
- template
+ template
ExtMove* make_promotions(ExtMove* moveList, Square to, Square ksq) {
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
@@ -94,13 +95,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 ? NORTH : SOUTH);
- const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
- const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
+ 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 Direction Up = (Us == WHITE ? NORTH : SOUTH);
+ const Direction Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
+ const Direction Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
Bitboard emptySquares;
diff --git a/Engines/Linux32/mcbrain/src/movegen.h b/Engines/Linux32/mcbrain/src/movegen.h
index 8256057..666e4ef 100644
--- a/Engines/Linux32/mcbrain/src/movegen.h
+++ b/Engines/Linux32/mcbrain/src/movegen.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 MOVEGEN_H_INCLUDED
#define MOVEGEN_H_INCLUDED
@@ -45,7 +46,7 @@ struct ExtMove {
// Inhibit unwanted implicit conversions to Move
// with an ambiguity that yields to a compile error.
- operator float() const;
+ operator float() const = delete;
};
inline bool operator<(const ExtMove& f, const ExtMove& s) {
diff --git a/Engines/Linux32/mcbrain/src/movepick.cpp b/Engines/Linux32/mcbrain/src/movepick.cpp
index 1c0de69..f62ca2b 100644
--- a/Engines/Linux32/mcbrain/src/movepick.cpp
+++ b/Engines/Linux32/mcbrain/src/movepick.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -28,8 +29,7 @@ namespace {
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, QCAPTURES_INIT, QCAPTURES, QCHECKS,
QSEARCH_RECAPTURES, QRECAPTURES
};
@@ -68,8 +68,8 @@ namespace {
/// MovePicker constructor for the main search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh,
- const PieceToHistory** ch, Move cm, Move* killers_p)
- : pos(p), mainHistory(mh), contHistory(ch), countermove(cm),
+ const CapturePieceToHistory* cph, const PieceToHistory** ch, Move cm, Move* killers_p)
+ : pos(p), mainHistory(mh), captureHistory(cph), contHistory(ch), countermove(cm),
killers{killers_p[0], killers_p[1]}, depth(d){
assert(d > DEPTH_ZERO);
@@ -80,19 +80,16 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHist
}
/// MovePicker constructor for quiescence search
-MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, Square s)
- : pos(p), mainHistory(mh) {
+MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, const CapturePieceToHistory* cph, Square s)
+ : pos(p), mainHistory(mh), captureHistory(cph), depth(d) {
assert(d <= DEPTH_ZERO);
if (pos.checkers())
stage = EVASION;
- else if (d > DEPTH_QS_NO_CHECKS)
- stage = QSEARCH_WITH_CHECKS;
-
else if (d > DEPTH_QS_RECAPTURES)
- stage = QSEARCH_NO_CHECKS;
+ stage = QSEARCH;
else
{
@@ -107,8 +104,8 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHist
/// MovePicker constructor for ProbCut: we generate captures with SEE higher
/// than or equal to the given threshold.
-MovePicker::MovePicker(const Position& p, Move ttm, Value th)
- : pos(p), threshold(th) {
+MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePieceToHistory* cph)
+ : pos(p), captureHistory(cph), threshold(th) {
assert(!pos.checkers());
@@ -123,7 +120,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Value th)
/// score() assigns a numerical value to each move in a list, used for sorting.
/// Captures are ordered by Most Valuable Victim (MVV), preferring captures
-/// near our home rank. Quiets are ordered using the histories.
+/// with a good history. Quiets are ordered using the histories.
template
void MovePicker::score() {
@@ -132,7 +129,7 @@ void MovePicker::score() {
for (auto& m : *this)
if (Type == CAPTURES)
m.value = PieceValue[MG][pos.piece_on(to_sq(m))]
- - Value(200 * relative_rank(pos.side_to_move(), to_sq(m)));
+ + Value((*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))]);
else if (Type == QUIETS)
m.value = (*mainHistory)[pos.side_to_move()][from_to(m)]
@@ -161,8 +158,7 @@ Move MovePicker::next_move(bool skipQuiets) {
switch (stage) {
- case MAIN_SEARCH: case EVASION: case QSEARCH_WITH_CHECKS:
- case QSEARCH_NO_CHECKS: case PROBCUT:
+ case MAIN_SEARCH: case EVASION: case QSEARCH: case PROBCUT:
++stage;
return ttMove;
@@ -179,7 +175,7 @@ Move MovePicker::next_move(bool skipQuiets) {
move = pick_best(cur++, endMoves);
if (move != ttMove)
{
- if (pos.see_ge(move))
+ if (pos.see_ge(move, Value(-55 * (cur-1)->value / 1024)))
return move;
// Losing capture, move it to the beginning of the array
@@ -280,21 +276,21 @@ Move MovePicker::next_move(bool skipQuiets) {
}
break;
- case QCAPTURES_1_INIT: case QCAPTURES_2_INIT:
+ case QCAPTURES_INIT:
cur = moves;
endMoves = generate(pos, cur);
score();
++stage;
/* fallthrough */
- case QCAPTURES_1: case QCAPTURES_2:
+ case QCAPTURES:
while (cur < endMoves)
{
move = pick_best(cur++, endMoves);
if (move != ttMove)
return move;
}
- if (stage == QCAPTURES_2)
+ if (depth <= DEPTH_QS_NO_CHECKS)
break;
cur = moves;
endMoves = generate(pos, cur);
@@ -313,14 +309,13 @@ Move MovePicker::next_move(bool skipQuiets) {
case QSEARCH_RECAPTURES:
cur = moves;
endMoves = generate(pos, cur);
- score();
++stage;
/* fallthrough */
case QRECAPTURES:
while (cur < endMoves)
{
- move = pick_best(cur++, endMoves);
+ move = *cur++;
if (to_sq(move) == recaptureSquare)
return move;
}
diff --git a/Engines/Linux32/mcbrain/src/movepick.h b/Engines/Linux32/mcbrain/src/movepick.h
index 66fc1bd..26e2a14 100644
--- a/Engines/Linux32/mcbrain/src/movepick.h
+++ b/Engines/Linux32/mcbrain/src/movepick.h
@@ -1,27 +1,29 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 MOVEPICK_H_INCLUDED
#define MOVEPICK_H_INCLUDED
#include
+#include
#include "movegen.h"
#include "position.h"
@@ -39,7 +41,7 @@ struct StatBoards : public std::array, Size1> {
void update(T& entry, int bonus, const int D) {
assert(abs(bonus) <= D); // Ensure range is [-32 * D, 32 * D]
- assert(abs(32 * D) < INT16_MAX); // Ensure we don't overflow
+ assert(abs(32 * D) < (std::numeric_limits::max)()); // Ensure we don't overflow
entry += bonus * 32 - entry * abs(bonus) / D;
@@ -47,6 +49,26 @@ struct StatBoards : public std::array, Size1> {
}
};
+/// StatCubes is a generic 3-dimensional array used to store various statistics
+template
+struct StatCubes : public std::array, Size2>, Size1> {
+
+ void fill(const T& v) {
+ T* p = &(*this)[0][0][0];
+ std::fill(p, p + sizeof(*this) / sizeof(*p), v);
+ }
+
+ void update(T& entry, int bonus, const int D, const int W) {
+
+ assert(abs(bonus) <= D); // Ensure range is [-W * D, W * D]
+ assert(abs(W * D) < (std::numeric_limits::max)()); // Ensure we don't overflow
+
+ entry += bonus * W - entry * abs(bonus) / D;
+
+ assert(abs(entry) <= W * D);
+ }
+};
+
/// ButterflyBoards are 2 tables (one for each color) indexed by the move's from
/// and to squares, see chessprogramming.wikispaces.com/Butterfly+Boards
typedef StatBoards ButterflyBoards;
@@ -54,6 +76,9 @@ typedef StatBoards ButterflyBoards;
/// PieceToBoards are addressed by a move's [piece][to] information
typedef StatBoards PieceToBoards;
+/// CapturePieceToBoards are addressed by a move's [piece][to][captured piece type] information
+typedef StatCubes CapturePieceToBoards;
+
/// ButterflyHistory records how often quiet moves have been successful or
/// unsuccessful during the current search, and is used for reduction and move
/// ordering decisions. It uses ButterflyBoards as backing store.
@@ -72,6 +97,14 @@ struct PieceToHistory : public PieceToBoards {
}
};
+/// CapturePieceToHistory is like PieceToHistory, but is based on CapturePieceToBoards
+struct CapturePieceToHistory : public CapturePieceToBoards {
+
+ void update(Piece pc, Square to, PieceType captured, int bonus) {
+ StatCubes::update((*this)[pc][to][captured], bonus, 324, 2);
+ }
+};
+
/// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
/// move, see chessprogramming.wikispaces.com/Countermove+Heuristic
typedef StatBoards CounterMoveHistory;
@@ -93,9 +126,9 @@ class MovePicker {
public:
MovePicker(const MovePicker&) = delete;
MovePicker& operator=(const MovePicker&) = delete;
- MovePicker(const Position&, Move, Value);
- MovePicker(const Position&, Move, Depth, const ButterflyHistory*, Square);
- MovePicker(const Position&, Move, Depth, const ButterflyHistory*, const PieceToHistory**, Move, Move*);
+ MovePicker(const Position&, Move, Value, const CapturePieceToHistory*);
+ MovePicker(const Position&, Move, Depth, const ButterflyHistory*, const CapturePieceToHistory*, Square);
+ MovePicker(const Position&, Move, Depth, const ButterflyHistory*, const CapturePieceToHistory*, const PieceToHistory**, Move, Move*);
Move next_move(bool skipQuiets = false);
private:
@@ -105,8 +138,9 @@ class MovePicker {
const Position& pos;
const ButterflyHistory* mainHistory;
+ const CapturePieceToHistory* captureHistory;
const PieceToHistory** contHistory;
- Move ttMove, countermove, killers[2];
+ Move ttMove, countermove, killers[4];
ExtMove *cur, *endMoves, *endBadCaptures;
int stage;
Square recaptureSquare;
diff --git a/Engines/Linux32/mcbrain/src/pawns.cpp b/Engines/Linux32/mcbrain/src/pawns.cpp
index 98811e7..3e5c2ed 100644
--- a/Engines/Linux32/mcbrain/src/pawns.cpp
+++ b/Engines/Linux32/mcbrain/src/pawns.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -31,11 +32,11 @@ namespace {
#define V Value
#define S(mg, eg) make_score(mg, eg)
- // Isolated pawn penalty by opposed flag
- const Score Isolated[] = { S(27, 30), S(13, 18) };
+ // Isolated pawn penalty
+ const Score Isolated = S(13, 18);
- // Backward pawn penalty by opposed flag
- const Score Backward[] = { S(40, 26), S(24, 12) };
+ // Backward pawn penalty
+ const Score Backward = S(24, 12);
// Connected pawn bonus by opposed, phalanx, #support and rank
Score Connected[2][2][3][RANK_NB];
@@ -43,38 +44,36 @@ namespace {
// Doubled pawn penalty
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)
- };
-
- // 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 [isKingFile][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(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) }
+ const Value ShelterWeakness[][int(FILE_NB) / 2][RANK_NB] = {
+ { { V( 97), V(17), V( 9), V(44), V( 84), V( 87), V( 99) }, // Not On King file
+ { V(106), V( 6), V(33), V(86), V( 87), V(104), V(112) },
+ { V(101), V( 2), V(65), V(98), V( 58), V( 89), V(115) },
+ { V( 73), V( 7), V(54), V(73), V( 84), V( 83), V(111) } },
+ { { V(104), V(20), V( 6), V(27), V( 86), V( 93), V( 82) }, // On King file
+ { V(123), V( 9), V(34), V(96), V(112), V( 88), V( 75) },
+ { V(120), V(25), V(65), V(91), V( 66), V( 78), V(117) },
+ { V( 81), V( 2), V(47), V(63), V( 94), V( 93), V(104) } }
};
// 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.
+ // 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(-290), V(-274), V(57), V(41) }, //BlockedByKing
+ { { 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( 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( 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(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) } }
@@ -90,10 +89,10 @@ namespace {
template
Score evaluate(const Position& pos, Pawns::Entry* e) {
- 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);
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const Direction Up = (Us == WHITE ? NORTH : SOUTH);
+ const Direction Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
+ const Direction Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
Bitboard b, neighbours, stoppers, doubled, supported, phalanx;
Bitboard lever, leverPush;
@@ -105,7 +104,7 @@ namespace {
Bitboard ourPawns = pos.pieces( Us, PAWN);
Bitboard theirPawns = pos.pieces(Them, PAWN);
- e->passedPawns[Us] = e->pawnAttacksSpan[Us] = 0;
+ e->passedPawns[Us] = e->pawnAttacksSpan[Us] = e->weakUnopposed[Us] = 0;
e->semiopenFiles[Us] = 0xFF;
e->kingSquares[Us] = SQ_NONE;
e->pawnAttacks[Us] = shift(ourPawns) | shift(ourPawns);
@@ -160,7 +159,7 @@ namespace {
e->passedPawns[Us] |= s;
else if ( stoppers == SquareBB[s + Up]
- && relative_rank(Us, s) >= RANK_4)
+ && relative_rank(Us, s) >= RANK_5)
{
b = shift(supported) & ~theirPawns;
while (b)
@@ -170,19 +169,16 @@ namespace {
// Score this pawn
if (supported | phalanx)
- score += Connected[opposed][!!phalanx][popcount(supported)][relative_rank(Us, s)];
+ score += Connected[opposed][bool(phalanx)][popcount(supported)][relative_rank(Us, s)];
else if (!neighbours)
- score -= Isolated[opposed];
+ score -= Isolated, e->weakUnopposed[Us] += !opposed;
else if (backward)
- score -= Backward[opposed];
+ score -= Backward, e->weakUnopposed[Us] += !opposed;
if (doubled && !supported)
score -= Doubled;
-
- if (lever)
- score += Lever[relative_rank(Us, s)];
}
return score;
@@ -250,7 +246,7 @@ Value Entry::shelter_storm(const Position& pos, Square ksq) {
Value safety = MaxSafetyBonus;
File center = std::max(FILE_B, std::min(FILE_G, file_of(ksq)));
- for (File f = center - File(1); f <= center + File(1); ++f)
+ for (File f = File(center - 1); f <= File(center + 1); ++f)
{
b = ourPawns & file_bb(f);
Rank rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1;
@@ -258,8 +254,8 @@ 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;
- int d = std::min(f, FILE_H - f);
- safety -= ShelterWeakness[d][rkUs]
+ int d = std::min(f, ~f);
+ safety -= ShelterWeakness[f == file_of(ksq)][d][rkUs]
+ StormDanger
[f == file_of(ksq) && rkThem == relative_rank(Us, ksq) + 1 ? BlockedByKing :
rkUs == RANK_1 ? Unopposed :
diff --git a/Engines/Linux32/mcbrain/src/pawns.h b/Engines/Linux32/mcbrain/src/pawns.h
index 15b0b77..e834e18 100644
--- a/Engines/Linux32/mcbrain/src/pawns.h
+++ b/Engines/Linux32/mcbrain/src/pawns.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-218 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 PAWNS_H_INCLUDED
#define PAWNS_H_INCLUDED
@@ -37,6 +38,7 @@ struct Entry {
Bitboard pawn_attacks(Color c) const { return pawnAttacks[c]; }
Bitboard passed_pawns(Color c) const { return passedPawns[c]; }
Bitboard pawn_attacks_span(Color c) const { return pawnAttacksSpan[c]; }
+ int weak_unopposed(Color c) const { return weakUnopposed[c]; }
int pawn_asymmetry() const { return asymmetry; }
int open_files() const { return openFiles; }
@@ -49,7 +51,7 @@ struct Entry {
}
int pawns_on_same_color_squares(Color c, Square s) const {
- return pawnsOnSquares[c][!!(DarkSquares & s)];
+ return pawnsOnSquares[c][bool(DarkSquares & s)];
}
template
@@ -71,6 +73,7 @@ struct Entry {
Bitboard pawnAttacksSpan[COLOR_NB];
Square kingSquares[COLOR_NB];
Score kingSafety[COLOR_NB];
+ int weakUnopposed[COLOR_NB];
int castlingRights[COLOR_NB];
int semiopenFiles[COLOR_NB];
int pawnsOnSquares[COLOR_NB][COLOR_NB]; // [color][light/dark squares]
diff --git a/Engines/Linux32/mcbrain/src/polybook.cpp b/Engines/Linux32/mcbrain/src/polybook.cpp
new file mode 100644
index 0000000..9aaacb4
--- /dev/null
+++ b/Engines/Linux32/mcbrain/src/polybook.cpp
@@ -0,0 +1,737 @@
+/*
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 .
+ */
+// polybook.cpp was written by Thomas Ziproth
+/*
+BrainFish, a UCI chess playing engine derived from Stockfish
+Copyright (C) 2016-2017 Thomas Zipproth
+
+BrainFish 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.
+
+BrainFish 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 "polybook.h"
+#include "uci.h"
+#include "movegen.h"
+#include "thread.h"
+#include
+#include "misc.h"
+#include
+
+PolyBook polybook; // global PolyBook
+
+using namespace std;
+
+// Random numbers from PolyGlot, used to compute book hash keys
+const union {
+ uint64_t PolyGlotRandoms[781];
+ struct {
+ uint64_t psq[12][64]; // [piece][square]
+ uint64_t castle[4]; // [castle right]
+ uint64_t enpassant[8]; // [file]
+ uint64_t 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
+ } };
+
+
+PolyBook::PolyBook()
+{
+ keycount = 0;
+ polyhash = NULL;
+
+ use_best_book_move = true;
+ max_book_depth = 255;
+ book_depth_count = 0;
+
+ last_position = 0;
+ akt_position = 0;
+ last_anz_pieces = 0;
+ akt_anz_pieces = 0;
+ search_counter = 0;
+
+ do_search = true;
+ enabled = false;
+}
+
+
+PolyBook::~PolyBook()
+{
+ if (polyhash != NULL)
+ delete[]polyhash;
+}
+
+
+void PolyBook::init(const std::string& bookfile)
+{
+ if (bookfile.length() == 0) return;
+ const char *fnam = bookfile.c_str();
+
+ if (strcmp(fnam, "") == 0)
+ {
+ enabled = false;
+ return;
+ }
+
+ FILE *fpt = fopen(fnam, "rb");
+ if (fpt == NULL)
+ {
+ sync_cout << "info string Could not open " << bookfile << sync_endl;
+ enabled = false;
+ return;
+ }
+
+ if (polyhash != NULL)
+ {
+ free(polyhash);
+ polyhash = NULL;
+ }
+
+ fseek(fpt, 0L, SEEK_END);
+ int filesize = ftell(fpt);
+ fseek(fpt, 0L, SEEK_SET);
+
+ keycount = filesize / 16;
+ polyhash = new PolyHash[keycount];
+
+ fread(polyhash, 1, filesize, fpt);
+ fclose(fpt);
+
+ for (int i = 0; i= max_book_depth)
+ return m1;
+
+ Key key = polyglot_key(pos);
+
+ int n = find_first_key(key);
+
+ if (n < 1)
+ {
+ search_counter++;
+ if (search_counter > 4)
+ {
+ // stop searching after 4 times not in the book till position changes
+ // according to check_do_search()
+ do_search = false;
+ search_counter = 0;
+ book_depth_count = 0;
+ }
+
+ return m1;
+ }
+
+ book_depth_count++;
+
+ int idx1;
+ if (use_best_book_move)
+ idx1 = index_best;
+ else
+ idx1 = index_rand;
+
+ m1 = pg_move_to_sf_move(pos, polyhash[idx1].move);
+
+ if (!pos.is_draw(64)) return m1;
+ if (n == 1) return m1;
+
+ // special case draw position and 2 moves available
+
+ if (!check_draw(m1, pos))
+ return m1;
+
+ int idx2 = index_first;
+ if (idx1 == idx2)
+ idx2 = index_first + 1;
+ Move m2 = pg_move_to_sf_move(pos, polyhash[idx2].move);
+
+ if (!check_draw(m2, pos))
+ return m2;
+
+ return MOVE_NONE;
+}
+
+
+Key PolyBook::polyglot_key(const Position & pos)
+{
+ Key key = 0;
+ Bitboard b = pos.pieces();
+
+ while (b)
+ {
+ Square s = pop_lsb(&b);
+ Piece p = pos.piece_on(s);
+
+ // PolyGlot pieces are: BP = 0, WP = 1, BN = 2, ... BK = 10, WK = 11
+ key ^= PG.Zobrist.psq[2 * (type_of(p) - 1) + (color_of(p) == WHITE)][s];
+ }
+
+ b = pos.can_castle(ANY_CASTLING);
+
+ while (b)
+ key ^= PG.Zobrist.castle[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;
+}
+
+// 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 "king captures rook" representation. So in case book
+// move is a promotion we have to convert to our representation, in all the
+// other cases we can directly compare with a Move after having masked out
+// the special Move's flags (bit 14-15) that are not supported by PolyGlot.
+//
+// SF:
+// bit 0- 5: destination square (from 0 to 63)
+// bit 6-11: origin square (from 0 to 63)
+// bit 12-13: promotion piece type - 2 (from KNIGHT-2 to QUEEN-2)
+// bit 14-15: special move flag: promotion (1), en passant (2), castling (3)
+Move PolyBook::pg_move_to_sf_move(const Position & pos, unsigned short pg_move)
+{
+ Move move = Move(pg_move);
+
+ int pt = (move >> 12) & 7;
+ if (pt)
+ return 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.move & (~(3 << 14)))) // compare with MoveType (bit 14-15) masked out
+ return m;
+ }
+
+ return MOVE_NONE;
+}
+
+
+int PolyBook::find_first_key(uint64_t key)
+{
+ index_first = -1;
+ index_count = 0;
+ index_weight_count = 0;
+ index_best = -1;
+ index_rand = -1;
+
+ int start = 0;
+ int end = keycount;
+
+ for (;;)
+ {
+ int mid = (end + start) / 2;
+
+ if (polyhash[mid].key < key)
+ start = mid;
+ else
+ {
+ if (polyhash[mid].key > key)
+ end = mid;
+ else
+ {
+ start = max(mid - 4, 0);
+ end = min(mid + 4, keycount);
+ }
+ }
+
+ if (end - start < 9)
+ break;
+ }
+
+ for (int i = start; i < end; i++)
+ {
+ if (key == polyhash[i].key)
+ {
+ index_first = i;
+ while ((index_first>0) && (key == polyhash[index_first - 1].key))
+ index_first--;
+ return get_key_data();
+ }
+ }
+
+ return -1;
+}
+
+
+int PolyBook::get_key_data()
+{
+ int best_weight = polyhash[index_first].weight;
+ index_weight_count = best_weight;
+ uint64_t key = polyhash[index_first].key;
+
+ index_count = 1;
+ index_best = index_first;
+
+ for (int i = index_first + 1; i best_weight)
+ {
+ best_weight = polyhash[i].weight;
+ index_best = i;
+ }
+ }
+
+ int rand_pos = (rand64() % index_weight_count);
+ int weight_count = 0;
+ index_rand = index_best;
+
+ for (int i = index_first; i < index_first + index_count; i++)
+ {
+ if ((rand_pos >= weight_count) && (rand_pos < weight_count + polyhash[i].weight))
+ {
+ index_rand = i;
+ break;
+ }
+ weight_count += polyhash[i].weight;
+ }
+
+ return index_count;
+}
+
+
+bool PolyBook::check_do_search(const Position & pos)
+{
+ akt_position = pos.pieces();
+ akt_anz_pieces = popcount(akt_position);
+
+ bool pos_changed = false;
+
+ Bitboard b = akt_position ^ last_position;
+ int n2 = popcount(b);
+
+ if (n2 > 6) pos_changed = true;
+ if (akt_position == last_position) pos_changed = true;
+ if (akt_anz_pieces > last_anz_pieces) pos_changed = true;
+ if (akt_anz_pieces < last_anz_pieces - 2) pos_changed = true;
+ if (pos.key() == 0xB4D30CD15A43432D) pos_changed = true;
+
+ // reset do_search and book depth counter if
+ // postion changed more than one move can do or in initial position
+ if (pos_changed)
+ {
+ book_depth_count = 0;
+ do_search = true;
+ }
+
+ last_position = akt_position;
+ last_anz_pieces = akt_anz_pieces;
+
+ return do_search;
+}
+
+
+bool PolyBook::check_draw(Move m, Position & pos)
+{
+ StateInfo st;
+
+ pos.do_move(m, st, pos.gives_check(m));
+ bool draw = pos.is_draw(64);
+ pos.undo_move(m);
+
+ return draw;
+}
+
+
+void PolyBook::byteswap_polyhash(PolyHash *ph)
+{
+ if (is_little_endian())
+ {
+ ph->key = swap_uint64(ph->key);
+ ph->move = swap_uint16(ph->move);
+ ph->weight = swap_uint16(ph->weight);
+ ph->learn = swap_uint32(ph->learn);
+ }
+}
+
+
+uint64_t PolyBook::rand64()
+{
+ sr ^= sr >> 12, sr ^= sr << 25, sr ^= sr >> 27;
+ return sr * 2685821657736338717LL;
+}
+
+
+bool PolyBook::is_little_endian()
+{
+ int num = 1;
+ return (*(uint8_t *)&num == 1);
+}
+
+
+uint64_t PolyBook::swap_uint64(uint64_t d)
+{
+ uint64_t a;
+ uint8_t *dst = (uint8_t *)&a;
+ uint8_t *src = (uint8_t *)&d;
+
+ dst[0] = src[7];
+ dst[1] = src[6];
+ dst[2] = src[5];
+ dst[3] = src[4];
+ dst[4] = src[3];
+ dst[5] = src[2];
+ dst[6] = src[1];
+ dst[7] = src[0];
+
+ return a;
+}
+
+
+uint32_t PolyBook::swap_uint32(uint32_t d)
+{
+ uint32_t a;
+ uint8_t *dst = (uint8_t *)&a;
+ uint8_t *src = (uint8_t *)&d;
+
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
+
+ return a;
+}
+
+
+uint16_t PolyBook::swap_uint16(uint16_t d)
+{
+ uint16_t a;
+ uint8_t *dst = (uint8_t *)&a;
+ uint8_t *src = (uint8_t *)&d;
+
+ dst[0] = src[1];
+ dst[1] = src[0];
+
+ return a;
+}
+
diff --git a/Engines/Linux32/mcbrain/src/polybook.h b/Engines/Linux32/mcbrain/src/polybook.h
new file mode 100644
index 0000000..8696eda
--- /dev/null
+++ b/Engines/Linux32/mcbrain/src/polybook.h
@@ -0,0 +1,113 @@
+/*
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 .
+ */
+//polybook.h was wriiten by Thomas Zipproth
+/*
+polybook.h was written by Thomas Zipproth
+BrainFish, a UCI chess playing engine derived from Stockfish
+Copyright (C) 2016-2018 Thomas Zipproth
+
+BrainFish 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.
+
+BrainFish 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 POLYBOOK_H_INCLUDED
+#define POLYBOOK_H_INCLUDED
+
+#include "bitboard.h"
+#include "position.h"
+#include "string.h"
+
+typedef struct {
+ uint64_t key;
+ uint16_t move;
+ uint16_t weight;
+ uint32_t learn;
+} PolyHash;
+
+class PolyBook
+{
+public:
+
+ PolyBook();
+ ~PolyBook();
+
+ void init(const std::string& bookfile);
+ void set_best_book_move(bool best_book_move);
+ void set_book_depth(int book_depth);
+
+ Move probe(Position& pos);
+
+private:
+
+ Key polyglot_key(const Position& pos);
+ Move pg_move_to_sf_move(const Position & pos, unsigned short pg_move);
+
+ int find_first_key(uint64_t key);
+ int get_key_data();
+
+ bool check_do_search(const Position & pos);
+ bool check_draw(Move m, Position& pos);
+
+ void byteswap_polyhash(PolyHash *ph);
+ uint64_t rand64();
+
+ bool is_little_endian();
+ uint64_t swap_uint64(uint64_t d);
+ uint32_t swap_uint32(uint32_t d);
+ uint16_t swap_uint16(uint16_t d);
+
+ int keycount;
+ PolyHash *polyhash;
+
+ bool use_best_book_move;
+ int max_book_depth;
+ int book_depth_count;
+
+ int index_first;
+ int index_count;
+ int index_best;
+ int index_rand;
+ int index_weight_count;
+
+ uint64_t sr;
+
+ Bitboard last_position;
+ Bitboard akt_position;
+ int last_anz_pieces;
+ int akt_anz_pieces;
+ int search_counter;
+
+ bool enabled, do_search;
+};
+
+extern PolyBook polybook;
+
+#endif // #ifndef POLYBOOK_H_INCLUDED
diff --git a/Engines/Linux32/mcbrain/src/position.cpp b/Engines/Linux32/mcbrain/src/position.cpp
index aa43740..acef66b 100644
--- a/Engines/Linux32/mcbrain/src/position.cpp
+++ b/Engines/Linux32/mcbrain/src/position.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -211,10 +212,10 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
while ((ss >> token) && !isspace(token))
{
if (isdigit(token))
- sq += Square(token - '0'); // Advance the given number of files
+ sq += (token - '0') * EAST; // Advance the given number of files
else if (token == '/')
- sq -= Square(16);
+ sq += 2 * SOUTH;
else if ((idx = PieceToChar.find(token)) != string::npos)
{
@@ -272,7 +273,7 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
// 5-6. Halfmove clock and fullmove number
ss >> std::skipws >> st->rule50 >> gamePly;
- // Convert from fullmove starting from 1 to ply starting from 0,
+ // Convert from fullmove starting from 1 to gamePly starting from 0,
// handle also common incorrect FEN with fullmove = 0.
gamePly = std::max(2 * (gamePly - 1), 0) + (sideToMove == BLACK);
@@ -787,7 +788,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
if ( (int(to) ^ int(from)) == 16
&& (attacks_from(to - pawn_push(us), us) & pieces(them, PAWN)))
{
- st->epSquare = (from + to) / 2;
+ st->epSquare = to - pawn_push(us);
k ^= Zobrist::enpassant[file_of(st->epSquare)];
}
@@ -1003,22 +1004,22 @@ bool Position::see_ge(Move m, Value threshold) const {
Value balance; // Values of the pieces taken by us minus opponent's ones
Bitboard occupied, stmAttackers;
- balance = PieceValue[MG][piece_on(to)];
- occupied = 0;
+ // The opponent may be able to recapture so this is the best result
+ // we can hope for.
+ balance = PieceValue[MG][piece_on(to)] - threshold;
- if (balance < threshold)
+ if (balance < VALUE_ZERO)
return false;
- if (nextVictim == KING)
- return true;
-
+ // Now assume the worst possible result: that the opponent can
+ // capture our piece for free.
balance -= PieceValue[MG][nextVictim];
- if (balance >= threshold)
+ if (balance >= VALUE_ZERO) // Always true if nextVictim == KING
return true;
- bool relativeStm = true; // True if the opponent is to move
- occupied ^= pieces() ^ from ^ to;
+ bool opponentToMove = true;
+ occupied = pieces() ^ from ^ to;
// Find all attackers to the destination square, with the moving piece removed,
// but possibly an X-ray attacker added behind it.
@@ -1026,6 +1027,12 @@ bool Position::see_ge(Move m, Value threshold) const {
while (true)
{
+ // The balance is negative only because we assumed we could win
+ // the last piece for free. We are truly winning only if we can
+ // win the last piece _cheaply enough_. Test if we can actually
+ // do this otherwise "give up".
+ assert(balance < VALUE_ZERO);
+
stmAttackers = attackers & pieces(stm);
// Don't allow pinned pieces to attack pieces except the king as long all
@@ -1033,25 +1040,40 @@ bool Position::see_ge(Move m, Value threshold) const {
if (!(st->pinnersForKing[stm] & ~occupied))
stmAttackers &= ~st->blockersForKing[stm];
+ // If we have no more attackers we must give up
if (!stmAttackers)
- return relativeStm;
+ break;
// Locate and remove the next least valuable attacker
nextVictim = min_attacker(byTypeBB, to, stmAttackers, occupied, attackers);
if (nextVictim == KING)
- return relativeStm == bool(attackers & pieces(~stm));
-
- balance += relativeStm ? PieceValue[MG][nextVictim]
- : -PieceValue[MG][nextVictim];
+ {
+ // Our only attacker is the king. If the opponent still has
+ // attackers we must give up. Otherwise we make the move and
+ // (having no more attackers) the opponent must give up.
+ if (!(attackers & pieces(~stm)))
+ opponentToMove = !opponentToMove;
+ break;
+ }
- relativeStm = !relativeStm;
+ // Assume the opponent can win the next piece for free and switch sides
+ balance += PieceValue[MG][nextVictim];
+ opponentToMove = !opponentToMove;
- if (relativeStm == (balance >= threshold))
- return relativeStm;
+ // If balance is negative after receiving a free piece then give up
+ if (balance < VALUE_ZERO)
+ break;
+ // Complete the process of switching sides. The first line swaps
+ // all negative numbers with non-negative numbers. The compiler
+ // probably knows that it is just the bitwise negation ~balance.
+ balance = -balance-1;
stm = ~stm;
}
+
+ // If the opponent gave up we win, otherwise we lose.
+ return opponentToMove;
}
@@ -1075,18 +1097,16 @@ bool Position::is_draw(int ply) const {
{
stp = stp->previous->previous;
- // At root position ply is 1, so return a draw score if a position
- // repeats once earlier but strictly after the root, or repeats twice
- // before or at the root.
+ // Return a draw score if a position repeats once earlier but strictly
+ // after the root, or repeats twice before or at the root.
if ( stp->key == st->key
- && ++cnt + (ply - 1 > i) == 2)
+ && ++cnt + (ply > i) == 2)
return true;
}
return false;
}
-
/// Position::flip() flips position with the white and black sides reversed. This
/// is only useful for debugging e.g. for finding evaluation symmetry bugs.
diff --git a/Engines/Linux32/mcbrain/src/position.h b/Engines/Linux32/mcbrain/src/position.h
index fa812ef..c809549 100644
--- a/Engines/Linux32/mcbrain/src/position.h
+++ b/Engines/Linux32/mcbrain/src/position.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 POSITION_H_INCLUDED
#define POSITION_H_INCLUDED
diff --git a/Engines/Linux32/mcbrain/src/psqt.cpp b/Engines/Linux32/mcbrain/src/psqt.cpp
index 0d16b1c..55a2e72 100644
--- a/Engines/Linux32/mcbrain/src/psqt.cpp
+++ b/Engines/Linux32/mcbrain/src/psqt.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -116,7 +117,7 @@ void init() {
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
- File f = std::min(file_of(s), FILE_H - file_of(s));
+ File f = std::min(file_of(s), ~file_of(s));
psq[ pc][ s] = v + Bonus[pc][rank_of(s)][f];
psq[~pc][~s] = -psq[pc][s];
}
diff --git a/Engines/Linux32/mcbrain/src/search.cpp b/Engines/Linux32/mcbrain/src/search.cpp
index 7805768..92753c0 100644
--- a/Engines/Linux32/mcbrain/src/search.cpp
+++ b/Engines/Linux32/mcbrain/src/search.cpp
@@ -1,35 +1,38 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
#include
#include // For std::memset
+#include //for sleep //MichaelB7
#include
#include
-#include
+#include // ELO MichaelB7
#include "evaluate.h"
#include "misc.h"
#include "movegen.h"
#include "movepick.h"
+#include "polybook.h" // Cerebellum
#include "position.h"
#include "search.h"
#include "timeman.h"
@@ -37,7 +40,6 @@
#include "tt.h"
#include "uci.h"
#include "tbprobe.h"
-#include "tzbook.h"
namespace Search {
@@ -69,19 +71,16 @@ namespace {
const int skipPhase[] = { 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7 };
// Razoring and futility margin based on depth
- // razor_margin[0] is unused as long as depth >= ONE_PLY in search
- const int razor_margin[] = { 0, 570, 603, 554 };
- Value futility_margin(Depth d) { return Value(150 * d / ONE_PLY); }
+ const int razor_margin = 600;
+ //Value futility_margin(Depth d) { return Value(150 * d / ONE_PLY); }
+ Value futility_margin(Depth d) { return Value(16 * d^2 / ONE_PLY + 200 * d / ONE_PLY);} // idea from JD Watson, code modfied by MichaelB7
// Futility and reductions lookup tables, initialized at startup
int FutilityMoveCounts[2][16]; // [improving][depth]
- int Reductions[2][2][64][64]; // [pv][improving][depth][moveNumber]
-
- // Threshold used for countermoves based pruning
- const int CounterMovePruneThreshold = 0;
+ int Reductions[2][2][128][96]; // [pv][improving][depth][moveNumber] //MichaelB7
template Depth reduction(bool i, Depth d, int mn) {
- return Reductions[PvNode][i][std::min(d / ONE_PLY, 63)][std::min(mn, 63)] * ONE_PLY;
+ return Reductions[PvNode][i][std::min(d / ONE_PLY, 127)][std::min(mn, 95)] * ONE_PLY; //MichaelB7
}
// History and stats update bonus, based on depth
@@ -92,61 +91,18 @@ namespace {
// Skill structure is used to implement strength limit
struct Skill {
- Skill(int l) : level(l) {}
+ explicit Skill(int l) : level(l) {}
bool enabled() const { return level < 20; }
bool time_to_pick(Depth depth) const { return depth / ONE_PLY == 1 + level; }
- Move best_move(size_t multiPV) { return best ? best : pick_best(multiPV); }
Move pick_best(size_t multiPV);
int level;
Move best = MOVE_NONE;
};
-
- // EasyMoveManager structure is used to detect an 'easy move'. When the PV is stable
- // across multiple search iterations, we can quickly return the best move.
- struct EasyMoveManager {
-
- void clear() {
- stableCnt = 0;
- expectedPosKey = 0;
- pv[0] = pv[1] = pv[2] = MOVE_NONE;
- }
-
- Move get(Key key) const {
- return expectedPosKey == key ? pv[2] : MOVE_NONE;
- }
-
- void update(Position& pos, const std::vector& newPv) {
-
- assert(newPv.size() >= 3);
-
- // Keep track of how many times in a row the 3rd ply remains stable
- stableCnt = (newPv[2] == pv[2]) ? stableCnt + 1 : 0;
-
- if (!std::equal(newPv.begin(), newPv.begin() + 3, pv))
- {
- std::copy(newPv.begin(), newPv.begin() + 3, pv);
-
- StateInfo st[2];
- pos.do_move(newPv[0], st[0]);
- pos.do_move(newPv[1], st[1]);
- expectedPosKey = pos.key();
- pos.undo_move(newPv[1]);
- pos.undo_move(newPv[0]);
- }
- }
-
- Key expectedPosKey;
- int stableCnt;
- Move pv[3];
- };
-
- EasyMoveManager EasyMove;
- Value DrawValue[COLOR_NB];
int tactical;
- bool bruteForce, limitStrength, noNULL;
+ bool bookEnabled, bruteForce, limitStrength, noNULL;
template
Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode, bool skipEarlyPruning);
@@ -159,6 +115,8 @@ namespace {
void update_pv(Move* pv, Move move, Move* childPv);
void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus);
void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus);
+ void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCnt, int bonus);
+ bool pv_is_draw(Position& pos);
// perft() is our utility to verify move generation. All the leaf nodes up
// to the given depth are generated and counted, and the sum is returned.
@@ -194,10 +152,10 @@ namespace {
void Search::init() {
for (int imp = 0; imp <= 1; ++imp)
- for (int d = 1; d < 64; ++d)
- for (int mc = 1; mc < 64; ++mc)
+ for (int d = 1; d < 128; ++d) // MichaelB7
+ for (int mc = 1; mc < 96; ++mc) // MichaelB7
{
- double r = 0.2 * d * (1.0 - exp(-9.0 / d)) * log(mc);
+ double r = log(d) * log(mc) / 1.89 ;
Reductions[NonPV][imp][d][mc] = int(std::round(r));
Reductions[PV][imp][d][mc] = std::max(Reductions[NonPV][imp][d][mc] - 1, 0);
@@ -223,21 +181,7 @@ void Search::clear() {
Time.availableNodes = 0;
TT.clear();
-
- for (Thread* th : Threads)
- {
- th->counterMoves.fill(MOVE_NONE);
- th->mainHistory.fill(0);
-
- for (auto& to : th->contHistory)
- for (auto& h : to)
- h.fill(0);
-
- th->contHistory[NO_PIECE][0].fill(CounterMovePruneThreshold - 1);
- }
-
- Threads.main()->callsCnt = 0;
- Threads.main()->previousScore = VALUE_INFINITE;
+ Threads.clear();
}
@@ -257,20 +201,24 @@ void MainThread::search() {
limitStrength = Options["UCI_LimitStrength"];
noNULL = Options["No_Null_Moves"];
tactical = Options["Tactical"];
+ bookEnabled = Options["Book_Enabled"];
Color us = rootPos.side_to_move();
Time.init(Limits, us, rootPos.game_ply());
TT.new_search();
- if (Options["Respect"]){
- int respect = Options["Respect"] * PawnValueEg / 100; // From centipawns
- DrawValue[ us] = VALUE_DRAW + Value(respect);
- DrawValue[~us] = VALUE_DRAW - Value(respect);}
-
- else if (Options["Respect White POV"]) {
- int respectPOV = Options["Respect White POV"] * PawnValueEg / 100; // From centipawns
- DrawValue[WHITE] = VALUE_DRAW + Value(respectPOV);
- DrawValue[BLACK] = VALUE_DRAW - Value(respectPOV);}
+ int contempt = Options["Contempt"] * PawnValueEg / 100; // From centipawns
+
+ // In analysis mode, adjust contempt in accordance with user preference
+ if (Limits.infinite || Options["UCI_AnalyseMode"])
+ contempt = Options["Analysis Contempt"] == "Off" ? 0
+ : Options["Analysis Contempt"] == "White" && us == BLACK ? -contempt
+ : Options["Analysis Contempt"] == "Black" && us == WHITE ? -contempt
+ : contempt; // contempt remains with the side to move
+
+ // Eval::Contempt is from white's point of view
+ Eval::Contempt = (us == WHITE ? make_score(contempt, contempt / 2)
+ : -make_score(contempt, contempt / 2));
if (rootMoves.empty())
{
@@ -280,26 +228,22 @@ void MainThread::search() {
<< sync_endl;
}
else
- {
- Move bookMove = MOVE_NONE;
-
- if (!Limits.infinite && !Limits.mate)
- bookMove = tzbook.probe2(rootPos);
-
- if (bookMove && std::count(rootMoves.begin(), rootMoves.end(), bookMove))
- {
- std::swap(rootMoves[0], *std::find(rootMoves.begin(), rootMoves.end(), bookMove));
- for (Thread* th : Threads)
- if (th != this)
- std::swap(th->rootMoves[0], *std::find(th->rootMoves.begin(), th->rootMoves.end(), bookMove));
- }
- else
- {
+ {
+ Move bookMove = MOVE_NONE;
+
+ if (!Limits.infinite && !Limits.mate)
+ bookMove = polybook.probe(rootPos);
+
+ if (bookEnabled && bookMove && std::count(rootMoves.begin(), rootMoves.end(), bookMove))
+ {
+ for (Thread* th : Threads)
+ std::swap(th->rootMoves[0], *std::find(th->rootMoves.begin(), th->rootMoves.end(), bookMove));
+ }
+ else
+ {
if (limitStrength)
{
-
int uci_elo = (Options["UCI_ELO"]);
-
std::mt19937 gen(now());
std::uniform_int_distribution dis(-33, 33);
int rand = dis(gen);
@@ -311,18 +255,13 @@ void MainThread::search() {
Limits.nodes *= std::max(1,Time.optimum()/1000 );
std::this_thread::sleep_for (std::chrono::seconds(Time.optimum()/1000) * (1 - Limits.nodes/724000));
}
- for (Thread* th : Threads)
- if (th != this)
- th->start_searching();
-
- Thread::search(); // Let's start searching!
- }
- }
-
- // When playing in 'nodes as time' mode, subtract the searched nodes from
- // the available ones before exiting.
- if (Limits.npmsec)
- Time.availableNodes += Limits.inc[us] - Threads.nodes_searched();
+ for (Thread* th : Threads)
+ if (th != this)
+ th->start_searching();
+
+ Thread::search(); // Let's start searching!
+ }
+ }
// When we reach the maximum depth, we can arrive here without a raise of
// Threads.stop. However, if we are pondering or in an infinite search,
@@ -343,10 +282,14 @@ void MainThread::search() {
if (th != this)
th->wait_for_search_finished();
+ // When playing in 'nodes as time' mode, subtract the searched nodes from
+ // the available ones before exiting.
+ if (Limits.npmsec)
+ Time.availableNodes += Limits.inc[us] - Threads.nodes_searched();
+
// Check if there are threads with a better score than main thread
Thread* bestThread = this;
- if ( !this->easyMovePlayed
- && Options["MultiPV"] == 1
+ if ( Options["MultiPV"] == 1
&& !Limits.depth
&& !Skill(Options["Skill Level"]).enabled()
&& rootMoves[0].pv[0] != MOVE_NONE)
@@ -384,28 +327,30 @@ void MainThread::search() {
void Thread::search() {
- Stack stack[MAX_PLY+7], *ss = stack+4; // To allow referencing (ss-4) and (ss+2)
- Value bestValue, alpha, beta, delta;
- Move easyMove = MOVE_NONE;
+ Stack stack[MAX_PLY+7], *ss = stack+4; // To reference from (ss-4) to (ss+2)
+ Value bestValue, alpha, beta, delta1, delta2;
+ Move lastBestMove = MOVE_NONE;
+ Depth lastBestMoveDepth = DEPTH_ZERO;
MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr);
+ double timeReduction = 1.0;
std::memset(ss-4, 0, 7 * sizeof(Stack));
for (int i = 4; i > 0; i--)
(ss-i)->contHistory = &this->contHistory[NO_PIECE][0]; // Use as sentinel
- bestValue = delta = alpha = -VALUE_INFINITE;
+ bestValue = delta1 = delta2 = alpha = -VALUE_INFINITE;
beta = VALUE_INFINITE;
if (mainThread)
{
- easyMove = EasyMove.get(rootPos.key());
- EasyMove.clear();
- mainThread->easyMovePlayed = mainThread->failedLow = false;
+ mainThread->failedLow = false;
mainThread->bestMoveChanges = 0;
}
- size_t multiPV = Options["MultiPV"];
+ multiPV = Options["MultiPV"];
Skill skill(Options["Skill Level"]);
+ if (tactical) multiPV = pow(2, tactical);
+
// When playing with strength handicap enable MultiPV search that we will
// use behind the scenes to retrieve a set of possible moves.
@@ -413,19 +358,25 @@ void Thread::search() {
multiPV = std::max(multiPV, (size_t)4);
multiPV = std::min(multiPV, rootMoves.size());
+
+ // UCI options specify 256 as the max MultiPv option
+ int consecutiveEarlyExits[257] = {0};
// Iterative deepening loop until requested to stop or the target depth is reached
while ( (rootDepth += ONE_PLY) < DEPTH_MAX
&& !Threads.stop
&& !(Limits.depth && mainThread && rootDepth / ONE_PLY > Limits.depth))
{
- // Distribute search depths across the threads
- if (idx)
- {
- int i = (idx - 1) % 20;
- if (((rootDepth / ONE_PLY + rootPos.game_ply() + skipPhase[i]) / skipSize[i]) % 2)
- continue;
- }
+ // Distribute search depths across the threads
+ if (idx)
+ {
+ int i = (idx - 1) % 20;
+ if (idx == Threads.size() - 1 && !ss->excludedMove && rootDepth < 14 * ONE_PLY && rootMoves.size() > 1 && rootPos.see_ge(rootMoves[0].pv[0], VALUE_ZERO + 1))
+ ss->excludedMove = rootMoves[0].pv[0]; //lazy_or_stubborn by pb00068
+ else
+ if (((rootDepth / ONE_PLY + rootPos.game_ply() + skipPhase[i]) / skipSize[i]) % 2)
+ continue;
+ }
// Age out PV variability metric
if (mainThread)
@@ -445,10 +396,11 @@ void Thread::search() {
// Reset aspiration window starting size
if (rootDepth >= 5 * ONE_PLY)
{
- Value prevScore = rootMoves[PVIdx].previousScore;
- delta = std::max(Value(int(8.0 + 0.1 * abs(prevScore))), Value(18));
- alpha = std::max(rootMoves[PVIdx].previousScore - delta,-VALUE_INFINITE);
- beta = std::min(rootMoves[PVIdx].previousScore + delta, VALUE_INFINITE);
+ Value prevScore = rootMoves[PVIdx].previousScore;
+ delta1 = (prevScore < 0) ? Value(int(8.0 + 0.1 * abs(prevScore))) : Value(18);
+ delta2 = (prevScore > 0) ? Value(int(8.0 + 0.1 * abs(prevScore))) : Value(18);
+ alpha = std::max(prevScore - delta1,-VALUE_INFINITE);
+ beta = std::min(prevScore + delta2, VALUE_INFINITE);
}
// Start with a small aspiration window and, in the case of a fail
@@ -464,7 +416,8 @@ void Thread::search() {
// and we want to keep the same order for all the moves except the
// new PV that goes to the front. Note that in case of MultiPV
// search the already searched PV lines are preserved.
- std::stable_sort(rootMoves.begin() + PVIdx, rootMoves.end());
+ if (PVIdx + 1 == multiPV)
+ std::stable_sort(rootMoves.begin() + PVIdx, rootMoves.end());
// If search has been stopped, we break immediately. Sorting and
// writing PV back to TT is safe because RootMoves is still
@@ -485,7 +438,7 @@ void Thread::search() {
if (bestValue <= alpha)
{
beta = (alpha + beta) / 2;
- alpha = std::max(bestValue - delta, -VALUE_INFINITE);
+ alpha = std::max(bestValue - delta1, -VALUE_INFINITE);
if (mainThread)
{
@@ -493,14 +446,20 @@ void Thread::search() {
Threads.stopOnPonderhit = false;
}
}
- else if (bestValue >= beta)
- beta = std::min(bestValue + delta, VALUE_INFINITE);
+
+ else if ( bestValue >= beta)
+ beta = std::min(bestValue + delta2, VALUE_INFINITE); //Ivan Ivec
+
else
+ {
+ delta1 += delta1 / 4 + 5; //Ivan Ivec
+ delta2 += delta2 / 4 + 5; //Ivan Ivec
+
+ assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
+
+ consecutiveEarlyExits[PVIdx] = (bestValue >= beta) ? consecutiveEarlyExits[PVIdx] + 1 : 0;
break;
-
- delta += delta / 4 + 5;
-
- assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
+ }
}
// Sort the PV lines searched so far and update the GUI
@@ -514,7 +473,12 @@ void Thread::search() {
if (!Threads.stop)
completedDepth = rootDepth;
- // Has any of the threads found a "mate in x"?
+ if (rootMoves[0].pv[0] != lastBestMove) {
+ lastBestMove = rootMoves[0].pv[0];
+ lastBestMoveDepth = rootDepth;
+ }
+
+ // Have we found a "mate in x"?
if ( Limits.mate
&& bestValue >= VALUE_MATE_IN_MAX_PLY
&& VALUE_MATE - bestValue <= 2 * Limits.mate)
@@ -522,14 +486,14 @@ void Thread::search() {
if (!mainThread)
continue;
-
+//BEGINS MichaelB7
if (Options["FastPlay"])
- {
- if ( Time.elapsed() > Time.optimum() / 256
- && ( abs(bestValue) > 12300 || abs(bestValue) >= VALUE_MATE_IN_MAX_PLY ))
- Threads.stop = true;
- }
-
+ {
+ if ( Time.elapsed() > Time.optimum() / 256
+ && ( abs(bestValue) > 12300 || abs(bestValue) >= VALUE_MATE_IN_MAX_PLY ))
+ Threads.stop = true;
+ }
+//ENDS MichaelB7
// If skill level is enabled and time is up, pick a sub-optimal best move
if (skill.enabled() && skill.time_to_pick(rootDepth))
skill.pick_best(multiPV);
@@ -540,21 +504,29 @@ void Thread::search() {
if (!Threads.stop && !Threads.stopOnPonderhit)
{
// Stop the search if only one legal move is available, or if all
- // of the available time has been used, or if we matched an easyMove
- // from the previous search and just did a fast verification.
+ // of the available time has been used
const int F[] = { mainThread->failedLow,
bestValue - mainThread->previousScore };
-
int improvingFactor = std::max(229, std::min(715, 357 + 119 * F[0] - 6 * F[1]));
- double unstablePvFactor = 1 + mainThread->bestMoveChanges;
- bool doEasyMove = rootMoves[0].pv[0] == easyMove
- && mainThread->bestMoveChanges < 0.03
- && Time.elapsed() > Time.optimum() * 5 / 44;
+ Color us = rootPos.side_to_move();
+ bool thinkHard = bestValue == VALUE_DRAW
+ && Limits.time[us] - Time.elapsed() > Limits.time[~us]
+ && ::pv_is_draw(rootPos);
+
+ double unstablePvFactor = 1 + mainThread->bestMoveChanges + thinkHard;
+
+ // if the bestMove is stable over several iterations, reduce time for this move,
+ // the longer the move has been stable, the more.
+ // Use part of the gained time from a previous stable move for the current move.
+ timeReduction = 1;
+ for (int i : {3, 4, 5})
+ if (lastBestMoveDepth * i < completedDepth && !thinkHard)
+ timeReduction *= 1.3;
+ unstablePvFactor *= std::pow(mainThread->previousTimeReduction, 0.51) / timeReduction;
if ( rootMoves.size() == 1
- || Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 628
- || (mainThread->easyMovePlayed = doEasyMove, doEasyMove))
+ || Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 628)
{
// If we are allowed to ponder do not stop the search now but
// keep pondering until the GUI sends "ponderhit" or "stop".
@@ -564,26 +536,18 @@ void Thread::search() {
Threads.stop = true;
}
}
-
- if (rootMoves[0].pv.size() >= 3)
- EasyMove.update(rootPos, rootMoves[0].pv);
- else
- EasyMove.clear();
}
}
if (!mainThread)
return;
- // Clear any candidate easy move that wasn't stable for the last search
- // iterations; the second condition prevents consecutive fast moves.
- if (EasyMove.stableCnt < 6 || mainThread->easyMovePlayed)
- EasyMove.clear();
+ mainThread->previousTimeReduction = timeReduction;
// If skill level is enabled, swap best PV line with the sub-optimal one
if (skill.enabled())
- std::swap(rootMoves[0], *std::find(rootMoves.begin(),
- rootMoves.end(), skill.best_move(multiPV)));
+ std::swap(rootMoves[0], *std::find(rootMoves.begin(), rootMoves.end(),
+ skill.best ? skill.best : skill.pick_best(multiPV)));
}
@@ -595,7 +559,7 @@ namespace {
Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode, bool skipEarlyPruning) {
const bool PvNode = NT == PV;
- const bool rootNode = PvNode && (ss-1)->ply == 0;
+ const bool rootNode = PvNode && ss->ply == 0;
assert(-VALUE_INFINITE <= alpha && alpha < beta && beta <= VALUE_INFINITE);
assert(PvNode || (alpha == beta - 1));
@@ -603,7 +567,7 @@ namespace {
assert(!(PvNode && cutNode));
assert(depth / ONE_PLY * ONE_PLY == depth);
- Move pv[MAX_PLY+1], quietsSearched[64];
+ Move pv[MAX_PLY+1], capturesSearched[32], quietsSearched[64];
StateInfo st;
TTEntry* tte;
Key posKey;
@@ -611,19 +575,19 @@ namespace {
Depth extension, newDepth;
Value bestValue, value, ttValue, eval, maxValue;
bool ttHit, inCheck, givesCheck, singularExtensionNode, improving;
- bool captureOrPromotion, doFullDepthSearch, moveCountPruning, skipQuiets, ttCapture;
+ bool captureOrPromotion, doFullDepthSearch, moveCountPruning, skipQuiets, ttCapture, goodCap, pvExact;
Piece movedPiece;
- int moveCount, quietCount;
+ int moveCount, captureCount, quietCount;
// Step 1. Initialize node
Thread* thisThread = pos.this_thread();
inCheck = pos.checkers();
- moveCount = quietCount = ss->moveCount = 0;
+ moveCount = captureCount = quietCount = ss->moveCount = 0;
ss->statScore = 0;
bestValue = -VALUE_INFINITE;
maxValue = VALUE_INFINITE;
- ss->ply = (ss-1)->ply + 1;
+ (ss + 1)->ply = (ss)->ply + 1;
ss->forcedMove = 0;
ss->forcingTree = ((ss - 2)->forcingTree && (ss - 2)->forcedMove) // Recursive forcing tree.
|| (ss->ply == 2 && (ss - 1)->moveCount > 1) // Offensive forcing tree
@@ -633,16 +597,15 @@ namespace {
if (thisThread == Threads.main())
static_cast(thisThread)->check_time();
- // Used to send selDepth info to GUI
- if (PvNode && thisThread->selDepth < ss->ply)
- thisThread->selDepth = ss->ply;
+ // Used to send selDepth info to GUI (selDepth counts from 1, ply from 0)
+ if (PvNode && thisThread->selDepth < ss->ply + 1)
+ thisThread->selDepth = ss->ply + 1;
if (!rootNode)
{
// Step 2. Check for aborted search and immediate draw
if (Threads.stop.load(std::memory_order_relaxed) || pos.is_draw(ss->ply) || ss->ply >= MAX_PLY)
- return ss->ply >= MAX_PLY && !inCheck ? evaluate(pos)
- : DrawValue[pos.side_to_move()];
+ return ss->ply >= MAX_PLY && !inCheck ? evaluate(pos) : VALUE_DRAW;
// Step 3. Mate distance pruning. Even if we mate at the next move our score
// would be at best mate_in(ss->ply+1), but if alpha is already bigger because
@@ -658,16 +621,17 @@ namespace {
assert(0 <= ss->ply && ss->ply < MAX_PLY);
+ (ss+1)->ply = ss->ply + 1;
ss->currentMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
ss->contHistory = &thisThread->contHistory[NO_PIECE][0];
- (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
+ (ss+2)->killers[0] = (ss+2)->killers[1] = (ss+2)->killers[2] = (ss+2)->killers[3] = MOVE_NONE;
Square prevSq = to_sq((ss-1)->currentMove);
// Step 4. Transposition table lookup. We don't want the score of a partial
// search to overwrite a previous full search TT value, so we use a different
// position key in case of an excluded move.
excludedMove = ss->excludedMove;
- posKey = pos.key() ^ Key(excludedMove);
+ posKey = pos.key() ^ Key(excludedMove << 16); // isn't a very good hash
tte = TT.probe(posKey, ttHit);
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
ttMove = rootNode ? thisThread->rootMoves[thisThread->PVIdx].pv[0]
@@ -688,7 +652,16 @@ namespace {
{
if (!pos.capture_or_promotion(ttMove))
update_stats(pos, ss, ttMove, nullptr, 0, stat_bonus(depth));
-
+ else update_capture_stats(pos, ttMove, nullptr, 0, stat_bonus(depth));
+ if(type_of(ttMove) == PROMOTION || !pos.see_ge(ttMove, VALUE_ZERO))
+ {
+ if (ss->killers[2] != ttMove)
+ {
+ ss->killers[3] = ss->killers[2];
+ ss->killers[2] = ttMove;
+ }
+ }
+
// Extra penalty for a quiet TT move in previous ply when it gets refuted
if ((ss-1)->moveCount == 1 && !pos.captured_piece())
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + ONE_PLY));
@@ -715,7 +688,7 @@ namespace {
&& !pos.can_castle(ANY_CASTLING))
{
TB::ProbeState err;
- TB::WDLScore v = Tablebases::probe_wdl(pos, &err);
+ TB::WDLScore wdl = Tablebases::probe_wdl(pos, &err);
if (err != TB::ProbeState::FAIL)
{
@@ -723,36 +696,30 @@ namespace {
int drawScore = TB::UseRule50 ? 1 : 0;
- value = v < -drawScore ? -VALUE_MATE + MAX_PLY + ss->ply
- : v > drawScore ? VALUE_MATE - MAX_PLY - ss->ply
- : VALUE_DRAW + 2 * v * drawScore;
+ value = wdl < -drawScore ? -VALUE_MATE + MAX_PLY + ss->ply + 1
+ : wdl > drawScore ? VALUE_MATE - MAX_PLY - ss->ply - 1
+ : VALUE_DRAW + 2 * wdl * drawScore;
+
+ Bound b = wdl < -drawScore ? BOUND_UPPER
+ : wdl > drawScore ? BOUND_LOWER : BOUND_EXACT;
+
+ if ( b == BOUND_EXACT
+ || (b == BOUND_LOWER ? value >= beta : value <= alpha))
+ {
+ tte->save(posKey, value_to_tt(value, ss->ply), b,
+ std::min(DEPTH_MAX - ONE_PLY, depth + 6 * ONE_PLY),
+ MOVE_NONE, VALUE_NONE, TT.generation());
- if (abs(v) <= drawScore) {
- tte->save(posKey, value_to_tt(value, ss->ply), BOUND_EXACT,
- depth, MOVE_NONE, VALUE_NONE, TT.generation());
return value;
}
- else if (v < -drawScore) {
- if (alpha >= value) {
- tte->save(posKey, value_to_tt(value, ss->ply),
- BOUND_UPPER, depth, MOVE_NONE, VALUE_NONE,
- TT.generation());
- return value;
- }
- maxValue = value;
- }
- else {
- if (beta <= value) {
- tte->save(posKey, value_to_tt(value, ss->ply),
- BOUND_LOWER, depth, MOVE_NONE, VALUE_NONE,
- TT.generation());
- return value;
- }
- bestValue = value;
- if (PvNode && bestValue > alpha)
- alpha = bestValue;
- }
+ if (PvNode)
+ {
+ if (b == BOUND_LOWER)
+ bestValue = value, alpha = std::max(alpha, bestValue);
+ else
+ maxValue = value;
+ }
}
}
}
@@ -785,18 +752,18 @@ namespace {
ss->staticEval, TT.generation());
}
- if (skipEarlyPruning)
+ if (skipEarlyPruning || !pos.non_pawn_material(pos.side_to_move()))
goto moves_loop;
// Step 6. Razoring (skipped when in check)
if ( !bruteForce && !PvNode
&& depth < 4 * ONE_PLY
- && eval + razor_margin[depth / ONE_PLY] <= alpha)
+ && eval + razor_margin <= alpha)
{
if (depth <= ONE_PLY)
return qsearch(pos, ss, alpha, alpha+1);
- Value ralpha = alpha - razor_margin[depth / ONE_PLY];
+ Value ralpha = alpha - razor_margin;
Value v = qsearch(pos, ss, ralpha, ralpha+1);
if (v <= ralpha)
return v;
@@ -806,22 +773,23 @@ namespace {
if ( !bruteForce && !rootNode
&& depth < 7 * ONE_PLY
&& eval - futility_margin(depth) >= beta
- && eval < VALUE_KNOWN_WIN // Do not return unproven wins
- && pos.non_pawn_material(pos.side_to_move()))
+ && eval < VALUE_KNOWN_WIN) // Do not return unproven wins
return eval;
// Step 8. Null move search with verification search (is omitted in PV nodes)
- if ( !noNULL && !PvNode
+ if ( !PvNode
&& eval >= beta
- && (ss->staticEval >= beta - 35 * (depth / ONE_PLY - 6) || depth >= 13 * ONE_PLY)
- && thisThread->selDepth + 3 * ONE_PLY > thisThread->rootDepth
- && pos.non_pawn_material(pos.side_to_move()) > (depth > 12 * ONE_PLY) * BishopValueMg)
+ && ss->staticEval >= beta - int(320 * log(depth / ONE_PLY)) + 500 //Corchess/IIvec
+ && (((ss-2)->currentMove != MOVE_NULL) || (ss-2)->staticEval >= beta - 36 * depth / ONE_PLY + 225)
+ && thisThread->selDepth + 3 > thisThread->rootDepth / ONE_PLY // idea from Corchess/IIvec
+ && (ss->ply >= thisThread->nmp_ply || ss->ply % 2 != thisThread->pair)
+ && !(MoveList(pos).size() < 4)) //MichaelB7
{
assert(eval - beta >= 0);
// Null move dynamic reduction based on depth and value
- Depth R = ((823 + 67 * depth / ONE_PLY) / 256 + std::min((eval - beta) / PawnValueMg, 3)) * ONE_PLY;
+ Depth R = (int(2.6 * log(depth / ONE_PLY)) + std::min((eval - beta) / Value(170), 3)) * ONE_PLY;
ss->currentMove = MOVE_NULL;
ss->contHistory = &thisThread->contHistory[NO_PIECE][0];
@@ -841,8 +809,16 @@ namespace {
return nullValue;
// Do verification search when searching for mate
+ R += ONE_PLY;
+ // disable null move pruning for side to move for the first part of the remaining search tree
+ int nmp_ply = thisThread->nmp_ply;
+ int pair = thisThread->pair;
+ thisThread->nmp_ply = ss->ply + 3 * (depth-R) / 4;
+ thisThread->pair = (ss->ply % 2) == 0;
Value v = depth-R < ONE_PLY ? qsearch(pos, ss, beta-1, beta)
: search(pos, ss, beta-1, beta, depth-R, false, true);
+ thisThread->pair = pair;
+ thisThread->nmp_ply = nmp_ply;
if (v >= beta)
return nullValue;
@@ -852,7 +828,8 @@ namespace {
// Step 9. ProbCut (skipped when in check)
// If we have a good enough capture and a reduced search returns a value
// much above beta, we can (almost) safely prune the previous move.
- if ( !bruteForce && !PvNode
+ if ( !bruteForce
+ && !PvNode
&& depth >= 5 * ONE_PLY
&& abs(beta) < VALUE_MATE_IN_MAX_PLY)
{
@@ -860,7 +837,7 @@ namespace {
assert(is_ok((ss-1)->currentMove));
- MovePicker mp(pos, ttMove, rbeta - ss->staticEval);
+ MovePicker mp(pos, ttMove, rbeta - ss->staticEval, &thisThread->captureHistory);
while ((move = mp.next_move()) != MOVE_NONE)
if (pos.legal(move))
@@ -894,7 +871,7 @@ namespace {
const PieceToHistory* contHist[] = { (ss-1)->contHistory, (ss-2)->contHistory, nullptr, (ss-4)->contHistory };
Move countermove = thisThread->counterMoves[pos.piece_on(prevSq)][prevSq];
- MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory, contHist, countermove, ss->killers);
+ MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory, &thisThread->captureHistory, contHist, countermove, ss->killers);
value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc
improving = ss->staticEval >= (ss-2)->staticEval
/* || ss->staticEval == VALUE_NONE Already implicit in the previous condition */
@@ -909,6 +886,8 @@ namespace {
&& tte->depth() >= depth - 3 * ONE_PLY;
skipQuiets = false;
ttCapture = false;
+ goodCap = false;
+ pvExact = PvNode && ttHit && tte->bound() == BOUND_EXACT;
// Step 11. Loop through moves
// Loop through all pseudo-legal moves until no moves remain or a beta cutoff occurs
@@ -919,12 +898,20 @@ namespace {
if (move == excludedMove)
continue;
- // At root obey the "searchmoves" option and skip moves not listed in Root
- // Move List. As a consequence any illegal move is also skipped. In MultiPV
- // mode we also skip PV moves which have been already searched.
- if (rootNode && !std::count(thisThread->rootMoves.begin() + thisThread->PVIdx,
- thisThread->rootMoves.end(), move))
- continue;
+ if (rootNode)
+ {
+ // At root obey the "searchmoves" option and skip moves not listed in Root
+ // Move List. As a consequence any illegal move is also skipped.
+ if (!std::count(thisThread->rootMoves.begin() + thisThread->PVIdx,
+ thisThread->rootMoves.end(), move))
+ continue;
+
+ // In MultiPV mode we not only skip PV moves which have already been searched,
+ // but also any other move except we have reached the last PV line.
+ if ( thisThread->PVIdx + 1 < thisThread->multiPV
+ && move != ttMove)
+ continue;
+ }
ss->moveCount = ++moveCount;
@@ -941,7 +928,7 @@ namespace {
movedPiece = pos.moved_piece(move);
givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates()
- ? pos.check_squares(type_of(pos.piece_on(from_sq(move)))) & to_sq(move)
+ ? pos.check_squares(type_of(movedPiece)) & to_sq(move)
: pos.gives_check(move);
moveCountPruning = depth < 16 * ONE_PLY
@@ -956,6 +943,7 @@ namespace {
// ttValue minus a margin then we will extend the ttMove.
if ( singularExtensionNode
&& move == ttMove
+ && !extension
&& pos.legal(move))
{
Value rBeta = std::max(ttValue - 2 * depth / ONE_PLY, -VALUE_MATE);
@@ -965,22 +953,22 @@ namespace {
ss->excludedMove = MOVE_NONE;
if (value < rBeta)
- extension = ONE_PLY;
+ extension = ONE_PLY;
}
- else if ( givesCheck
- && !moveCountPruning
- && pos.see_ge(move))
- extension = ONE_PLY;
+ else if (!moveCountPruning)
+ {
+ if ( givesCheck
+ && (pos.see_ge(move) || PvNode ))
+ extension = ONE_PLY;
+
+ else if ( PvNode
+ && depth < 13 * ONE_PLY
+ && ( givesCheck || pos.advanced_pawn_push(move)
+ || ( ss->forcingTree && (ss)->newDepth - depth > 1)))
+ extension = ONE_PLY;
+ }
- else if ( pos.advanced_pawn_push(move)
- && !moveCountPruning
- && pos.non_pawn_material(pos.side_to_move()) <= RookValueEg)
- extension = ONE_PLY;
- else if ( ss->forcingTree && (ss - 1)->newDepth - depth > 1
- && !moveCountPruning)
- extension = ONE_PLY;
-
// Calculate new depth for this move
newDepth = depth - ONE_PLY + extension;
@@ -1001,8 +989,7 @@ namespace {
}
// Reduced depth of the next LMR search
- int mch = std::max(1, moveCount - (ss-1)->moveCount / 16);
- int lmrDepth = std::max(newDepth - reduction(improving, depth, mch), DEPTH_ZERO) / ONE_PLY;
+ int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount), DEPTH_ZERO) / ONE_PLY;
// Countermoves based pruning
if ( lmrDepth < 3
@@ -1013,7 +1000,7 @@ namespace {
// Futility pruning: parent node
if ( lmrDepth < 7
&& !inCheck
- && ss->staticEval + 256 + 200 * lmrDepth <= alpha)
+ && ss->staticEval + 256 + futility_margin(lmrDepth * ONE_PLY) <= alpha)// idea from JD Watson, modifed by MichaelB7
continue;
// Prune moves with negative SEE
@@ -1039,11 +1026,13 @@ namespace {
if (move == ttMove && captureOrPromotion)
ttCapture = true;
+ else if (to_sq(move) == to_sq((ss - 1)->currentMove))
+ goodCap = true;
// Update the current move (this must be done after singular extension search)
ss->currentMove = move;
ss->contHistory = &thisThread->contHistory[movedPiece][to_sq(move)];
- ss->forcedMove = (extension || inCheck || captureOrPromotion) && -(ss - 1)->staticEval < alpha - PawnValueEg / 2 && ss->staticEval > alpha - PawnValueEg / 2;
+ ss->forcedMove = (extension || inCheck || captureOrPromotion) && (ss)->staticEval < alpha - PawnValueEg / 2 && ss->staticEval > alpha - PawnValueEg / 2;
// Step 14. Make the move
pos.do_move(move, st, givesCheck);
@@ -1052,18 +1041,29 @@ namespace {
// re-searched at full depth.
if ( !bruteForce && depth >= 3 * ONE_PLY
&& moveCount > 1
- && (!captureOrPromotion || moveCountPruning))
+ && (!captureOrPromotion || moveCountPruning)
+ && (ss+2)->killers[0] != move
+ && (ss+2)->killers[1] != move)
{
- int mch = std::max(1, moveCount - (ss-1)->moveCount / 16);
- Depth r = reduction(improving, depth, mch);
+ Depth r = reduction(improving, depth, moveCount);
if (captureOrPromotion)
r -= r ? ONE_PLY : DEPTH_ZERO;
else
{
+ // Decrease reduction if opponent's move count is high
+ if ((ss-1)->moveCount > 13 )
+ r -= ONE_PLY;
+
+ // Decrease reduction for exact PV nodes
+ if (pvExact)
+ r -= ONE_PLY;
+
// Increase reduction if ttMove is a capture
- if (ttCapture)
+ if (ttCapture || (!pvExact && depth > 13 * ONE_PLY))
r += ONE_PLY;
+ else if(goodCap && !inCheck && !givesCheck)
+ r += ONE_PLY;
// Increase reduction for cut nodes
if (cutNode)
@@ -1079,18 +1079,18 @@ namespace {
ss->statScore = thisThread->mainHistory[~pos.side_to_move()][from_to(move)]
+ (*contHist[0])[movedPiece][to_sq(move)]
+ (*contHist[1])[movedPiece][to_sq(move)]
- + (*contHist[3])[movedPiece][to_sq(move)]
+ + (*contHist[3])[movedPiece][to_sq(move)]
- 4000;
// Decrease/increase reduction by comparing opponent's stat score
- if (ss->statScore > 0 && ss->statScore > (ss-1)->statScore)
+ if (ss->statScore >= 0 && (ss-1)->statScore < 0)
r -= ONE_PLY;
- else if (ss->statScore < 0 && ss->statScore < (ss-1)->statScore )
+ else if ((ss-1)->statScore >= 0 && ss->statScore < 0)
r += ONE_PLY;
// Decrease/increase reduction for moves with a good/bad history
- r = std::max(DEPTH_ZERO, (r / ONE_PLY - ss->statScore / 32768) * ONE_PLY);
+ r = std::max(DEPTH_ZERO, (r / ONE_PLY - ss->statScore / 20000) * ONE_PLY);
}
Depth d = std::max(newDepth - r, ONE_PLY);
@@ -1188,6 +1188,8 @@ namespace {
if (!captureOrPromotion && move != bestMove && quietCount < 64)
quietsSearched[quietCount++] = move;
+ else if (captureOrPromotion && move != bestMove && captureCount < 32)
+ capturesSearched[captureCount++] = move;
}
// The following condition would detect a stop only after move loop has been
@@ -1207,12 +1209,22 @@ namespace {
if (!moveCount)
bestValue = excludedMove ? alpha
- : inCheck ? mated_in(ss->ply) : DrawValue[pos.side_to_move()];
+ : inCheck ? mated_in(ss->ply) : VALUE_DRAW;
else if (bestMove)
{
// Quiet best move: update move sorting heuristics
if (!pos.capture_or_promotion(bestMove))
update_stats(pos, ss, bestMove, quietsSearched, quietCount, stat_bonus(depth));
+ else update_capture_stats(pos, bestMove, capturesSearched, captureCount, stat_bonus(depth));
+ if(type_of(bestMove) == PROMOTION || quietCount > 3)
+ {
+ if (ss->killers[2] != bestMove)
+ {
+ ss->killers[3] = ss->killers[2];
+ ss->killers[2] = bestMove;
+ }
+ }
+
// Extra penalty for a quiet TT move in previous ply when it gets refuted
if ((ss-1)->moveCount == 1 && !pos.captured_piece())
@@ -1224,8 +1236,8 @@ namespace {
&& is_ok((ss-1)->currentMove))
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth));
- if (PvNode && bestValue > maxValue)
- bestValue = maxValue;
+ if (PvNode)
+ bestValue = std::min(bestValue, maxValue);
if (!excludedMove)
tte->save(posKey, value_to_tt(bestValue, ss->ply),
@@ -1247,7 +1259,7 @@ namespace {
const bool PvNode = NT == PV;
- assert(InCheck == !!pos.checkers());
+ assert(InCheck == bool(pos.checkers()));
assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE);
assert(PvNode || (alpha == beta - 1));
assert(depth <= DEPTH_ZERO);
@@ -1271,13 +1283,12 @@ namespace {
}
ss->currentMove = bestMove = MOVE_NONE;
- ss->ply = (ss-1)->ply + 1;
+ (ss+1)->ply = ss->ply + 1;
moveCount = 0;
// Check for an instant draw or if the maximum ply has been reached
if (pos.is_draw(ss->ply) || ss->ply >= MAX_PLY)
- return ss->ply >= MAX_PLY && !InCheck ? evaluate(pos)
- : DrawValue[pos.side_to_move()];
+ return ss->ply >= MAX_PLY && !InCheck ? evaluate(pos) : VALUE_DRAW;
assert(0 <= ss->ply && ss->ply < MAX_PLY);
@@ -1286,7 +1297,6 @@ namespace {
// only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS.
ttDepth = InCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS
: DEPTH_QS_NO_CHECKS;
-
// Transposition table lookup
posKey = pos.key();
tte = TT.probe(posKey, ttHit);
@@ -1329,7 +1339,7 @@ namespace {
if (bestValue >= beta)
{
if (!ttHit)
- tte->save(pos.key(), value_to_tt(bestValue, ss->ply), BOUND_LOWER,
+ tte->save(posKey, value_to_tt(bestValue, ss->ply), BOUND_LOWER,
DEPTH_NONE, MOVE_NONE, ss->staticEval, TT.generation());
return bestValue;
@@ -1345,7 +1355,7 @@ namespace {
// to search the moves. Because the depth is <= 0 here, only captures,
// queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
// be generated.
- MovePicker mp(pos, ttMove, depth, &pos.this_thread()->mainHistory, to_sq((ss-1)->currentMove));
+ MovePicker mp(pos, ttMove, depth, &pos.this_thread()->mainHistory, &pos.this_thread()->captureHistory, to_sq((ss-1)->currentMove));
// Loop through the moves until no moves remain or a beta cutoff occurs
while ((move = mp.next_move()) != MOVE_NONE)
@@ -1353,7 +1363,7 @@ namespace {
assert(is_ok(move));
givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates()
- ? pos.check_squares(type_of(pos.piece_on(from_sq(move)))) & to_sq(move)
+ ? pos.check_squares(type_of(pos.moved_piece(move))) & to_sq(move)
: pos.gives_check(move);
moveCount++;
@@ -1389,7 +1399,6 @@ namespace {
// Don't search moves with negative SEE values
if ( (!InCheck || evasionPrunable)
- && type_of(move) != PROMOTION
&& !pos.see_ge(move))
continue;
@@ -1500,6 +1509,26 @@ namespace {
}
+ // update_capture_stats() updates move sorting heuristics when a new capture best move is found
+
+ void update_capture_stats(const Position& pos, Move move,
+ Move* captures, int captureCnt, int bonus) {
+
+ CapturePieceToHistory& captureHistory = pos.this_thread()->captureHistory;
+ Piece moved_piece = pos.moved_piece(move);
+ PieceType captured = type_of(pos.piece_on(to_sq(move)));
+ captureHistory.update(moved_piece, to_sq(move), captured, bonus);
+
+ // Decrease all the other played capture moves
+ for (int i = 0; i < captureCnt; ++i)
+ {
+ moved_piece = pos.moved_piece(captures[i]);
+ captured = type_of(pos.piece_on(to_sq(captures[i])));
+ captureHistory.update(moved_piece, to_sq(captures[i]), captured, -bonus);
+ }
+ }
+
+
// update_stats() updates move sorting heuristics when a new quiet best move is found
void update_stats(const Position& pos, Stack* ss, Move move,
@@ -1531,6 +1560,24 @@ namespace {
}
+ // Is the PV leading to a draw position? Assumes all pv moves are legal
+ bool pv_is_draw(Position& pos) {
+
+ StateInfo st[MAX_PLY];
+ auto& pv = pos.this_thread()->rootMoves[0].pv;
+
+ for (size_t i = 0; i < pv.size(); ++i)
+ pos.do_move(pv[i], st[i]);
+
+ bool isDraw = pos.is_draw(pv.size());
+
+ for (size_t i = pv.size(); i > 0; --i)
+ pos.undo_move(pv[i-1]);
+
+ return isDraw;
+ }
+
+
// When playing with strength handicap, choose best move among a set of RootMoves
// using a statistical rule dependent on 'level'. Idea by Heinz van Saanen.
@@ -1554,7 +1601,7 @@ namespace {
int push = ( weakness * int(topScore - rootMoves[i].score)
+ delta * (rng.rand() % weakness)) / 128;
- if (rootMoves[i].score + push > maxScore)
+ if (rootMoves[i].score + push >= maxScore)
{
maxScore = rootMoves[i].score + push;
best = rootMoves[i].pv[0];
@@ -1593,7 +1640,7 @@ namespace {
if (Threads.ponder)
return;
- if ( (Limits.use_time_management() && elapsed > Time.maximum())
+ if ( (Limits.use_time_management() && elapsed > Time.maximum() - 10)
|| (Limits.movetime && elapsed >= Limits.movetime)
|| (Limits.nodes && Threads.nodes_searched() >= (uint64_t)Limits.nodes))
Threads.stop = true;
@@ -1606,12 +1653,19 @@ namespace {
string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
std::stringstream ss;
+ int temp = 0;
int elapsed = Time.elapsed() + 1;
const RootMoves& rootMoves = pos.this_thread()->rootMoves;
size_t PVIdx = pos.this_thread()->PVIdx;
- size_t multiPV = std::min((size_t)Options["MultiPV"], rootMoves.size());
+ size_t multiPV = pos.this_thread()->multiPV;
uint64_t nodesSearched = Threads.nodes_searched();
uint64_t tbHits = Threads.tb_hits() + (TB::RootInTB ? rootMoves.size() : 0);
+
+ if (tactical)
+ {
+ temp = multiPV;
+ multiPV = 1;
+ }
for (size_t i = 0; i < multiPV; ++i)
{
@@ -1651,11 +1705,10 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
for (Move m : rootMoves[i].pv)
ss << " " << UCI::move(m, pos.is_chess960());
}
-
+ if (tactical) multiPV = temp;
return ss.str();
}
-
/// RootMove::extract_ponder_from_tt() is called in case we have no ponder move
/// before exiting the search, for instance, in case we stop the search during a
/// fail high at root. We try hard to have a ponder move to return to the GUI,
@@ -1702,6 +1755,10 @@ void Tablebases::filter_root_moves(Position& pos, Search::RootMoves& rootMoves)
if (Cardinality < popcount(pos.pieces()) || pos.can_castle(ANY_CASTLING))
return;
+ // Don't filter any moves if the user requested analysis on multiple
+ if (Options["MultiPV"] != 1)
+ return;
+
// If the current root position is in the tablebases, then RootMoves
// contains only moves that preserve the draw or the win.
RootInTB = root_probe(pos, rootMoves, TB::Score);
@@ -1723,8 +1780,9 @@ void Tablebases::filter_root_moves(Position& pos, Search::RootMoves& rootMoves)
TB::Score = TB::Score > VALUE_DRAW ? VALUE_MATE - MAX_PLY - 1
: TB::Score < VALUE_DRAW ? -VALUE_MATE + MAX_PLY + 1
: VALUE_DRAW;
- // Since root_probe() and root_probe_wdl() dirty the root move scores,
- // we reset them to -VALUE_INFINITE
- for (size_t i = 0; i < rootMoves.size(); ++i)
- rootMoves[i].score = -VALUE_INFINITE;
+
+ // Since root_probe() and root_probe_wdl() dirty the root move scores,
+ // we reset them to -VALUE_INFINITE
+ for (RootMove& rm : rootMoves)
+ rm.score = -VALUE_INFINITE;
}
diff --git a/Engines/Linux32/mcbrain/src/search.h b/Engines/Linux32/mcbrain/src/search.h
index 5fe6d32..f1ac439 100644
--- a/Engines/Linux32/mcbrain/src/search.h
+++ b/Engines/Linux32/mcbrain/src/search.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 SEARCH_H_INCLUDED
#define SEARCH_H_INCLUDED
@@ -31,6 +32,10 @@ class Position;
namespace Search {
+/// Threshold used for countermoves based pruning
+const int CounterMovePruneThreshold = 0;
+
+
/// Stack struct keeps track of the information we need to remember from nodes
/// shallower and deeper in the tree during the search. Each search thread has
/// its own array of Stack objects, indexed by the current ply.
@@ -41,14 +46,13 @@ struct Stack {
int ply;
Move currentMove;
Move excludedMove;
- Move killers[2];
+ Move killers[4];
Value staticEval;
int statScore;
int moveCount;
Depth newDepth;
uint8_t forcedMove;
uint8_t forcingTree;
-
};
diff --git a/Engines/Linux32/mcbrain/src/tbprobe.cpp b/Engines/Linux32/mcbrain/src/tbprobe.cpp
index 90a016b..09e031c 100644
--- a/Engines/Linux32/mcbrain/src/tbprobe.cpp
+++ b/Engines/Linux32/mcbrain/src/tbprobe.cpp
@@ -1,21 +1,23 @@
/*
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (c) 2013 Ronald de Man
- Copyright (C) 2016-2017 Marco Costalba, Lucas Braesch
-
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -133,16 +135,16 @@ struct Atomic {
std::atomic_bool ready;
};
-// We define types for the different parts of the WLDEntry and DTZEntry with
+// We define types for the different parts of the WDLEntry and DTZEntry with
// corresponding specializations for pieces or pawns.
-struct WLDEntryPiece {
+struct WDLEntryPiece {
PairsData* precomp;
};
struct WDLEntryPawn {
uint8_t pawnCount[2]; // [Lead color / other color]
- WLDEntryPiece file[2][4]; // [wtm / btm][FILE_A..FILE_D]
+ WDLEntryPiece file[2][4]; // [wtm / btm][FILE_A..FILE_D]
};
struct DTZEntryPiece {
@@ -172,7 +174,7 @@ struct WDLEntry : public TBEntry {
WDLEntry(const std::string& code);
~WDLEntry();
union {
- WLDEntryPiece pieceTable[2]; // [wtm / btm]
+ WDLEntryPiece pieceTable[2]; // [wtm / btm]
WDLEntryPawn pawnTable;
};
};
@@ -341,6 +343,10 @@ class TBFile : public std::ifstream {
#ifndef _WIN32
struct stat statbuf;
int fd = ::open(fname.c_str(), O_RDONLY);
+
+ if (fd == -1)
+ return *baseAddress = nullptr, nullptr;
+
fstat(fd, &statbuf);
*mapping = statbuf.st_size;
*baseAddress = mmap(nullptr, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
@@ -353,6 +359,10 @@ class TBFile : public std::ifstream {
#else
HANDLE fd = CreateFile(fname.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+
+ if (fd == INVALID_HANDLE_VALUE)
+ return *baseAddress = nullptr, nullptr;
+
DWORD size_high;
DWORD size_low = GetFileSize(fd, &size_high);
HANDLE mmap = CreateFileMapping(fd, nullptr, PAGE_READONLY, size_high, size_low, nullptr);
@@ -380,8 +390,7 @@ class TBFile : public std::ifstream {
|| *data++ != *TB_MAGIC) {
std::cerr << "Corrupted table in file " << fname << std::endl;
unmap(*baseAddress, *mapping);
- *baseAddress = nullptr;
- return nullptr;
+ return *baseAddress = nullptr, nullptr;
}
return data;
@@ -482,7 +491,7 @@ void HashTable::insert(const std::vector& pieces) {
TBFile file(code.insert(code.find('K', 1), "v") + ".rtbw"); // KRK -> KRvK
- if (!file.is_open())
+ if (!file.is_open()) // Only WDL file is checked
return;
file.close();
@@ -1385,7 +1394,7 @@ void Tablebases::init(const std::string& paths) {
}
}
- sync_cout << "info string Found " << EntryTable.size() << " tablebases" << sync_endl;
+ sync_cout << "Info string found: " << EntryTable.size() << " tablebases" << sync_endl;
}
// Probe the WDL table for a particular position.
diff --git a/Engines/Linux32/mcbrain/src/tbprobe.h b/Engines/Linux32/mcbrain/src/tbprobe.h
index 0c16662..97ec7b1 100644
--- a/Engines/Linux32/mcbrain/src/tbprobe.h
+++ b/Engines/Linux32/mcbrain/src/tbprobe.h
@@ -1,21 +1,23 @@
/*
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (c) 2013 Ronald de Man
- Copyright (C) 2016-2017 Marco Costalba, Lucas Braesch
-
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 TBPROBE_H
#define TBPROBE_H
diff --git a/Engines/Linux32/mcbrain/src/thread.cpp b/Engines/Linux32/mcbrain/src/thread.cpp
index 6b24521..47a21c1 100644
--- a/Engines/Linux32/mcbrain/src/thread.cpp
+++ b/Engines/Linux32/mcbrain/src/thread.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017*2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 // For std::count
#include
@@ -24,6 +25,7 @@
#include "movegen.h"
#include "search.h"
#include "thread.h"
+#include "uci.h"
#include "tbprobe.h"
ThreadPool Threads; // Global object
@@ -51,6 +53,21 @@ Thread::~Thread() {
}
+/// Thread::clear() reset histories, usually before a new game
+
+void Thread::clear() {
+
+ counterMoves.fill(MOVE_NONE);
+ mainHistory.fill(0);
+ captureHistory.fill(0);
+
+ for (auto& to : contHistory)
+ for (auto& h : to)
+ h.fill(0);
+
+ contHistory[NO_PIECE][0].fill(Search::CounterMovePruneThreshold - 1);
+}
+
/// Thread::start_searching() wakes up the thread that will start the search
void Thread::start_searching() {
@@ -76,7 +93,13 @@ void Thread::wait_for_search_finished() {
void Thread::idle_loop() {
- WinProcGroup::bindThisThread(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 (Options["Threads"] >= 8)
+ WinProcGroup::bindThisThread(idx);
while (true)
{
@@ -94,42 +117,40 @@ void Thread::idle_loop() {
}
}
+/// ThreadPool::set() creates/destroys threads to match the requested number.
+/// Created and launced threads wil go immediately to sleep in idle_loop.
+/// Upon resizing, threads are recreated to allow for binding if necessary.
-/// ThreadPool::init() creates and launches the threads that will go
-/// immediately to sleep in idle_loop. We cannot use the c'tor because
-/// Threads is a static object and we need a fully initialized engine at
-/// this point due to allocation of Endgames in the Thread constructor.
-
-void ThreadPool::init(size_t requested) {
-
- push_back(new MainThread(0));
- set(requested);
-}
+void ThreadPool::set(size_t requested) {
+ if (size() > 0) { // destroy any existing thread(s)
+ main()->wait_for_search_finished();
-/// ThreadPool::exit() terminates threads before the program exits. Cannot be
-/// done in the destructor because threads must be terminated before deleting
-/// any static object, so before main() returns.
+ while (size() > 0)
+ delete back(), pop_back();
+ }
-void ThreadPool::exit() {
+ if (requested > 0) { // create new thread(s)
+ push_back(new MainThread(0));
- main()->wait_for_search_finished();
- set(0);
+ while (size() < requested)
+ push_back(new Thread(size()));
+ clear();
+ }
}
+/// ThreadPool::clear() sets threadPool data to initial values.
-/// ThreadPool::set() creates/destroys threads to match the requested number
-
-void ThreadPool::set(size_t requested) {
+void ThreadPool::clear() {
- while (size() < requested)
- push_back(new Thread(size()));
+ for (Thread* th : *this)
+ th->clear();
- while (size() > requested)
- delete back(), pop_back();
+ main()->callsCnt = 0;
+ main()->previousScore = VALUE_INFINITE;
+ main()->previousTimeReduction = 1;
}
-
/// ThreadPool::start_thinking() wakes up main thread waiting in idle_loop() and
/// returns immediately. Main thread will wake up other threads and start the search.
@@ -165,12 +186,14 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states,
// is shared by threads but is accessed in read-only mode.
StateInfo tmp = setupStates->back();
- for (Thread* th : Threads)
+ for (Thread* th : *this)
{
th->nodes = th->tbHits = 0;
th->rootDepth = th->completedDepth = DEPTH_ZERO;
th->rootMoves = rootMoves;
th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th);
+ th->nmp_ply = 0;
+ th->pair = -1;
}
setupStates->back() = tmp;
diff --git a/Engines/Linux32/mcbrain/src/thread.h b/Engines/Linux32/mcbrain/src/thread.h
index 8c0a666..25a6511 100644
--- a/Engines/Linux32/mcbrain/src/thread.h
+++ b/Engines/Linux32/mcbrain/src/thread.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 THREAD_H_INCLUDED
#define THREAD_H_INCLUDED
@@ -52,6 +53,7 @@ class Thread {
explicit Thread(size_t);
virtual ~Thread();
virtual void search();
+ void clear();
void idle_loop();
void start_searching();
void wait_for_search_finished();
@@ -59,8 +61,8 @@ class Thread {
Pawns::Table pawnsTable;
Material::Table materialTable;
Endgames endgames;
- size_t PVIdx;
- int selDepth;
+ size_t PVIdx, multiPV;
+ int selDepth, nmp_ply, pair;
std::atomic nodes, tbHits;
Position rootPos;
@@ -68,6 +70,7 @@ class Thread {
Depth rootDepth, completedDepth;
CounterMoveHistory counterMoves;
ButterflyHistory mainHistory;
+ CapturePieceToHistory captureHistory;
ContinuationHistory contHistory;
};
@@ -81,8 +84,8 @@ struct MainThread : public Thread {
void search() override;
void check_time();
- bool easyMovePlayed, failedLow;
- double bestMoveChanges;
+ bool failedLow;
+ double bestMoveChanges, previousTimeReduction;
Value previousScore;
int callsCnt;
};
@@ -97,11 +100,19 @@ struct ThreadPool : public std::vector {
void init(size_t); // No constructor and destructor, threads rely on globals that should
void exit(); // be initialized and valid during the whole thread lifetime.
void start_thinking(Position&, StateListPtr&, const Search::LimitsType&, bool = false);
+ void clear();
void set(size_t);
MainThread* main() const { return static_cast(front()); }
uint64_t nodes_searched() const { return accumulate(&Thread::nodes); }
uint64_t tb_hits() const { return accumulate(&Thread::tbHits); }
+
+ Depth lowestDepth(){
+ Depth lowest = DEPTH_MAX;
+ for (Thread* th: *this)
+ lowest = std::min(lowest, th->rootDepth);
+ return lowest;
+ }
std::atomic_bool stop, ponder, stopOnPonderhit;
diff --git a/Engines/Linux32/mcbrain/src/thread_win32.h b/Engines/Linux32/mcbrain/src/thread_win32.h
index 917563a..d69e817 100644
--- a/Engines/Linux32/mcbrain/src/thread_win32.h
+++ b/Engines/Linux32/mcbrain/src/thread_win32.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 THREAD_WIN32_H_INCLUDED
#define THREAD_WIN32_H_INCLUDED
diff --git a/Engines/Linux32/mcbrain/src/timeman.cpp b/Engines/Linux32/mcbrain/src/timeman.cpp
index 330709b..6a854c9 100644
--- a/Engines/Linux32/mcbrain/src/timeman.cpp
+++ b/Engines/Linux32/mcbrain/src/timeman.cpp
@@ -1,24 +1,27 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
+#include
#include "search.h"
#include "timeman.h"
@@ -30,43 +33,41 @@ namespace {
enum TimeType { OptimumTime, MaxTime };
- int remaining(int myTime, int myInc, int moveOverhead, int movesToGo,
- int moveNum, bool ponder, TimeType type) {
+ const int MoveHorizon = 50; // Plan time management at most this many moves ahead
+ const double MaxRatio = 7.09; // When in trouble, we can step over reserved time with this ratio
+ const double StealRatio = 0.35; // However we must not steal time from remaining moves over this ratio
+
- if (myTime <= 0)
- return 0;
+ // move_importance() is a skew-logistic function based on naive statistical
+ // analysis of "how many games are still undecided after n half-moves". Game
+ // is considered "undecided" as long as neither side has >275cp advantage.
+ // Data was extracted from the CCRL game database with some simple filtering criteria.
- double ratio; // Which ratio of myTime we are going to use
+ double move_importance(int ply) {
- // Usage of increment follows quadratic distribution with the maximum at move 25
- double inc = myInc * std::max(55.0, 120 - 0.12 * (moveNum - 25) * (moveNum - 25));
+ const double XScale = 7.64;
+ const double XShift = 58.4;
+ const double Skew = 0.183;
- // In moves-to-go we distribute time according to a quadratic function with
- // the maximum around move 20 for 40 moves in y time case.
- if (movesToGo)
- {
- ratio = (type == OptimumTime ? 1.0 : 6.0) / std::min(50, movesToGo);
+ return pow((1 + exp((ply - XShift) / XScale)), -Skew) + DBL_MIN; // Ensure non-zero
+ }
+
+ template
+ int remaining(int myTime, int movesToGo, int ply, int slowMover) {
- if (moveNum <= 40)
- ratio *= 1.1 - 0.001 * (moveNum - 20) * (moveNum - 20);
- else
- ratio *= 1.5;
+ const double TMaxRatio = (T == OptimumTime ? 1 : MaxRatio);
+ const double TStealRatio = (T == OptimumTime ? 0 : StealRatio);
- ratio *= 1 + inc / (myTime * 8.5);
- }
- // Otherwise we increase usage of remaining time as the game goes on
- else
- {
- double k = 1 + 20 * moveNum / (500.0 + moveNum);
- ratio = (type == OptimumTime ? 0.017 : 0.07) * (k + inc / myTime);
- }
+ double moveImportance = (move_importance(ply) * slowMover) / 100;
+ double otherMovesImportance = 0;
- int time = int(std::min(1.0, ratio) * std::max(0, myTime - moveOverhead));
+ for (int i = 1; i < movesToGo; ++i)
+ otherMovesImportance += move_importance(ply + 2 * i);
- if (type == OptimumTime && ponder)
- time *= 1.25;
+ double ratio1 = (TMaxRatio * moveImportance) / (TMaxRatio * moveImportance + otherMovesImportance);
+ double ratio2 = (moveImportance + TStealRatio * otherMovesImportance) / (moveImportance + otherMovesImportance);
- return time;
+ return int(myTime * std::min(ratio1, ratio2)); // Intel C++ asks for an explicit cast
}
} // namespace
@@ -81,11 +82,12 @@ namespace {
/// inc > 0 && movestogo == 0 means: x basetime + z increment
/// inc > 0 && movestogo != 0 means: x moves in y minutes + z increment
-void TimeManagement::init(Search::LimitsType& limits, Color us, int ply)
-{
- int moveOverhead = Options["Move Overhead"];
- int npmsec = Options["nodestime"];
- bool ponder = Options["Ponder"];
+void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
+
+ int minThinkingTime = Options["Minimum Thinking Time"];
+ int moveOverhead = Options["Move Overhead"];
+ int slowMover = Options["Slow Mover"];
+ int npmsec = Options["nodestime"];
// If we have to play in 'nodes as time' mode, then convert from time
// to nodes, and use resulting values in time management formulas.
@@ -102,11 +104,30 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply)
limits.npmsec = npmsec;
}
- int moveNum = (ply + 1) / 2;
-
startTime = limits.startTime;
- optimumTime = remaining(limits.time[us], limits.inc[us], moveOverhead,
- limits.movestogo, moveNum, ponder, OptimumTime);
- maximumTime = remaining(limits.time[us], limits.inc[us], moveOverhead,
- limits.movestogo, moveNum, ponder, MaxTime);
+ optimumTime = maximumTime = std::max(limits.time[us], minThinkingTime);
+
+ const int MaxMTG = limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon;
+
+ // We calculate optimum time usage for different hypothetical "moves to go"-values
+ // and choose the minimum of calculated search time values. Usually the greatest
+ // hypMTG gives the minimum values.
+ for (int hypMTG = 1; hypMTG <= MaxMTG; ++hypMTG)
+ {
+ // Calculate thinking time for hypothetical "moves to go"-value
+ int hypMyTime = limits.time[us]
+ + limits.inc[us] * (hypMTG - 1)
+ - moveOverhead * (2 + std::min(hypMTG, 40));
+
+ hypMyTime = std::max(hypMyTime, 0);
+
+ int t1 = minThinkingTime + remaining(hypMyTime, hypMTG, ply, slowMover);
+ int t2 = minThinkingTime + remaining(hypMyTime, hypMTG, ply, slowMover);
+
+ optimumTime = std::min(t1, optimumTime);
+ maximumTime = std::min(t2, maximumTime);
+ }
+
+ if (Options["Ponder"])
+ optimumTime += optimumTime / 4;
}
diff --git a/Engines/Linux32/mcbrain/src/timeman.h b/Engines/Linux32/mcbrain/src/timeman.h
index c22c8c2..4d3172b 100644
--- a/Engines/Linux32/mcbrain/src/timeman.h
+++ b/Engines/Linux32/mcbrain/src/timeman.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 TIMEMAN_H_INCLUDED
#define TIMEMAN_H_INCLUDED
diff --git a/Engines/Linux32/mcbrain/src/tt.cpp b/Engines/Linux32/mcbrain/src/tt.cpp
index f283d0c..1aed0f3 100644
--- a/Engines/Linux32/mcbrain/src/tt.cpp
+++ b/Engines/Linux32/mcbrain/src/tt.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 // For std::memset
#include
@@ -33,7 +34,7 @@ TranspositionTable TT; // Our global transposition table
void TranspositionTable::resize(size_t mbSize) {
- size_t newClusterCount = size_t(1) << msb((mbSize * 1024 * 1024) / sizeof(Cluster));
+ size_t newClusterCount = mbSize * 1024 * 1024 / sizeof(Cluster);
if (newClusterCount == clusterCount)
return;
@@ -41,7 +42,7 @@ void TranspositionTable::resize(size_t mbSize) {
clusterCount = newClusterCount;
free(mem);
- mem = calloc(clusterCount * sizeof(Cluster) + CacheLineSize - 1, 1);
+ mem = malloc(clusterCount * sizeof(Cluster) + CacheLineSize - 1);
if (!mem)
{
@@ -51,6 +52,7 @@ void TranspositionTable::resize(size_t mbSize) {
}
table = (Cluster*)((uintptr_t(mem) + CacheLineSize - 1) & ~(CacheLineSize - 1));
+ clear();
}
diff --git a/Engines/Linux32/mcbrain/src/tt.h b/Engines/Linux32/mcbrain/src/tt.h
index 24045ed..e0dc386 100644
--- a/Engines/Linux32/mcbrain/src/tt.h
+++ b/Engines/Linux32/mcbrain/src/tt.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 TT_H_INCLUDED
#define TT_H_INCLUDED
@@ -104,9 +105,9 @@ class TranspositionTable {
void resize(size_t mbSize);
void clear();
- // The lowest order bits of the key are used to get the index of the cluster
+ // The 32 lowest order bits of the key are used to get the index of the cluster
TTEntry* first_entry(const Key key) const {
- return &table[(size_t)key & (clusterCount - 1)].entry[0];
+ return &table[(uint32_t(key) * uint64_t(clusterCount)) >> 32].entry[0];
}
private:
diff --git a/Engines/Linux32/mcbrain/src/types.h b/Engines/Linux32/mcbrain/src/types.h
index acca874..7b4318e 100644
--- a/Engines/Linux32/mcbrain/src/types.h
+++ b/Engines/Linux32/mcbrain/src/types.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 TYPES_H_INCLUDED
#define TYPES_H_INCLUDED
@@ -146,7 +147,7 @@ enum CastlingRight {
};
template struct MakeCastling {
- static const CastlingRight
+ static constexpr CastlingRight
right = C == WHITE ? S == QUEEN_SIDE ? WHITE_OOO : WHITE_OO
: S == QUEEN_SIDE ? BLACK_OOO : BLACK_OO;
};
@@ -187,7 +188,7 @@ enum Value : int {
KnightValueMg = 764, KnightValueEg = 848,
BishopValueMg = 826, BishopValueEg = 891,
RookValueMg = 1282, RookValueEg = 1373,
- QueenValueMg = 2526, QueenValueEg = 2646,
+ QueenValueMg = 2560, QueenValueEg = 2680,
MidgameLimit = 15258, EndgameLimit = 3915
};
@@ -195,6 +196,7 @@ enum Value : int {
enum PieceType {
NO_PIECE_TYPE, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING,
ALL_PIECES = 0,
+ QUEEN_DIAGONAL = 7,
PIECE_TYPE_NB = 8
};
@@ -222,7 +224,7 @@ enum Depth : int {
static_assert(!(ONE_PLY & (ONE_PLY - 1)), "ONE_PLY is not a power of 2");
-enum Square {
+enum Square : int {
SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1,
SQ_A2, SQ_B2, SQ_C2, SQ_D2, SQ_E2, SQ_F2, SQ_G2, SQ_H2,
SQ_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3,
@@ -233,8 +235,10 @@ enum Square {
SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
SQ_NONE,
- SQUARE_NB = 64,
+ SQUARE_NB = 64
+};
+enum Direction : int {
NORTH = 8,
EAST = 1,
SOUTH = -NORTH,
@@ -261,7 +265,7 @@ enum Rank : int {
/// care to avoid left-shifting a signed int to avoid undefined behavior.
enum Score : int { SCORE_ZERO };
-inline Score make_score(int mg, int eg) {
+constexpr Score make_score(int mg, int eg) {
return Score((int)((unsigned int)eg << 16) + mg);
}
@@ -269,58 +273,68 @@ inline Score make_score(int mg, int eg) {
/// according to the standard a simple cast to short is implementation defined
/// and so is a right shift of a signed integer.
inline Value eg_value(Score s) {
-
union { uint16_t u; int16_t s; } eg = { uint16_t(unsigned(s + 0x8000) >> 16) };
return Value(eg.s);
}
inline Value mg_value(Score s) {
-
union { uint16_t u; int16_t s; } mg = { uint16_t(unsigned(s)) };
return Value(mg.s);
}
-#define ENABLE_BASE_OPERATORS_ON(T) \
-inline T operator+(T d1, T d2) { return T(int(d1) + int(d2)); } \
-inline T operator-(T d1, T d2) { return T(int(d1) - int(d2)); } \
-inline T operator-(T d) { return T(-int(d)); } \
-inline T& operator+=(T& d1, T d2) { return d1 = d1 + d2; } \
-inline T& operator-=(T& d1, T d2) { return d1 = d1 - d2; } \
-
-#define ENABLE_FULL_OPERATORS_ON(T) \
-ENABLE_BASE_OPERATORS_ON(T) \
-inline T operator*(int i, T d) { return T(i * int(d)); } \
-inline T operator*(T d, int i) { return T(int(d) * i); } \
-inline T& operator++(T& d) { return d = T(int(d) + 1); } \
-inline T& operator--(T& d) { return d = T(int(d) - 1); } \
-inline T operator/(T d, int i) { return T(int(d) / i); } \
-inline int operator/(T d1, T d2) { return int(d1) / int(d2); } \
-inline T& operator*=(T& d, int i) { return d = T(int(d) * i); } \
+#define ENABLE_BASE_OPERATORS_ON(T) \
+constexpr T operator+(T d1, T d2) { return T(int(d1) + int(d2)); } \
+constexpr T operator-(T d1, T d2) { return T(int(d1) - int(d2)); } \
+constexpr T operator-(T d) { return T(-int(d)); } \
+inline T& operator+=(T& d1, T d2) { return d1 = d1 + d2; } \
+inline T& operator-=(T& d1, T d2) { return d1 = d1 - d2; }
+
+#define ENABLE_INCR_OPERATORS_ON(T) \
+inline T& operator++(T& d) { return d = T(int(d) + 1); } \
+inline T& operator--(T& d) { return d = T(int(d) - 1); }
+
+#define ENABLE_FULL_OPERATORS_ON(T) \
+ENABLE_BASE_OPERATORS_ON(T) \
+ENABLE_INCR_OPERATORS_ON(T) \
+constexpr T operator*(int i, T d) { return T(i * int(d)); } \
+constexpr T operator*(T d, int i) { return T(int(d) * i); } \
+constexpr T operator/(T d, int i) { return T(int(d) / i); } \
+constexpr int operator/(T d1, T d2) { return int(d1) / int(d2); } \
+inline T& operator*=(T& d, int i) { return d = T(int(d) * i); } \
inline T& operator/=(T& d, int i) { return d = T(int(d) / i); }
ENABLE_FULL_OPERATORS_ON(Value)
-ENABLE_FULL_OPERATORS_ON(PieceType)
-ENABLE_FULL_OPERATORS_ON(Piece)
-ENABLE_FULL_OPERATORS_ON(Color)
ENABLE_FULL_OPERATORS_ON(Depth)
-ENABLE_FULL_OPERATORS_ON(Square)
-ENABLE_FULL_OPERATORS_ON(File)
-ENABLE_FULL_OPERATORS_ON(Rank)
+ENABLE_FULL_OPERATORS_ON(Direction)
+
+ENABLE_INCR_OPERATORS_ON(PieceType)
+ENABLE_INCR_OPERATORS_ON(Piece)
+ENABLE_INCR_OPERATORS_ON(Color)
+ENABLE_INCR_OPERATORS_ON(Square)
+ENABLE_INCR_OPERATORS_ON(File)
+ENABLE_INCR_OPERATORS_ON(Rank)
ENABLE_BASE_OPERATORS_ON(Score)
#undef ENABLE_FULL_OPERATORS_ON
+#undef ENABLE_INCR_OPERATORS_ON
#undef ENABLE_BASE_OPERATORS_ON
/// Additional operators to add integers to a Value
-inline Value operator+(Value v, int i) { return Value(int(v) + i); }
-inline Value operator-(Value v, int i) { return Value(int(v) - i); }
+constexpr Value operator+(Value v, int i) { return Value(int(v) + i); }
+constexpr Value operator-(Value v, int i) { return Value(int(v) - i); }
inline Value& operator+=(Value& v, int i) { return v = v + i; }
inline Value& operator-=(Value& v, int i) { return v = v - i; }
+/// Additional operators to add a Direction to a Square
+inline Square operator+(Square s, Direction d) { return Square(int(s) + int(d)); }
+inline Square operator-(Square s, Direction d) { return Square(int(s) - int(d)); }
+inline Square& operator+=(Square &s, Direction d) { return s = s + d; }
+inline Square& operator-=(Square &s, Direction d) { return s = s - d; }
+
/// Only declared but not defined. We don't want to multiply two scores due to
/// a very high risk of overflow. So user should explicitly convert to integer.
-inline Score operator*(Score s1, Score s2);
+Score operator*(Score, Score) = delete;
/// Division of a Score must be handled separately for each term
inline Score operator/(Score s, int i) {
@@ -339,39 +353,43 @@ inline Score operator*(Score s, int i) {
return result;
}
-inline Color operator~(Color c) {
+constexpr Color operator~(Color c) {
return Color(c ^ BLACK); // Toggle color
}
-inline Square operator~(Square s) {
+constexpr Square operator~(Square s) {
return Square(s ^ SQ_A8); // Vertical flip SQ_A1 -> SQ_A8
}
-inline Piece operator~(Piece pc) {
+constexpr File operator~(File f) {
+ return File(f ^ FILE_H); // Horizontal flip FILE_A -> FILE_H
+}
+
+constexpr Piece operator~(Piece pc) {
return Piece(pc ^ 8); // Swap color of piece B_KNIGHT -> W_KNIGHT
}
-inline CastlingRight operator|(Color c, CastlingSide s) {
+constexpr CastlingRight operator|(Color c, CastlingSide s) {
return CastlingRight(WHITE_OO << ((s == QUEEN_SIDE) + 2 * c));
}
-inline Value mate_in(int ply) {
+constexpr Value mate_in(int ply) {
return VALUE_MATE - ply;
}
-inline Value mated_in(int ply) {
+constexpr Value mated_in(int ply) {
return -VALUE_MATE + ply;
}
-inline Square make_square(File f, Rank r) {
+constexpr Square make_square(File f, Rank r) {
return Square((r << 3) + f);
}
-inline Piece make_piece(Color c, PieceType pt) {
+constexpr Piece make_piece(Color c, PieceType pt) {
return Piece((c << 3) + pt);
}
-inline PieceType type_of(Piece pc) {
+constexpr PieceType type_of(Piece pc) {
return PieceType(pc & 7);
}
@@ -380,27 +398,27 @@ inline Color color_of(Piece pc) {
return Color(pc >> 3);
}
-inline bool is_ok(Square s) {
+constexpr bool is_ok(Square s) {
return s >= SQ_A1 && s <= SQ_H8;
}
-inline File file_of(Square s) {
+constexpr File file_of(Square s) {
return File(s & 7);
}
-inline Rank rank_of(Square s) {
+constexpr Rank rank_of(Square s) {
return Rank(s >> 3);
}
-inline Square relative_square(Color c, Square s) {
+constexpr Square relative_square(Color c, Square s) {
return Square(s ^ (c * 56));
}
-inline Rank relative_rank(Color c, Rank r) {
+constexpr Rank relative_rank(Color c, Rank r) {
return Rank(r ^ (c * 7));
}
-inline Rank relative_rank(Color c, Square s) {
+constexpr Rank relative_rank(Color c, Square s) {
return relative_rank(c, rank_of(s));
}
@@ -409,27 +427,27 @@ inline bool opposite_colors(Square s1, Square s2) {
return ((s >> 3) ^ s) & 1;
}
-inline Square pawn_push(Color c) {
+constexpr Direction pawn_push(Color c) {
return c == WHITE ? NORTH : SOUTH;
}
-inline Square from_sq(Move m) {
+constexpr Square from_sq(Move m) {
return Square((m >> 6) & 0x3F);
}
-inline Square to_sq(Move m) {
+constexpr Square to_sq(Move m) {
return Square(m & 0x3F);
}
-inline int from_to(Move m) {
+constexpr int from_to(Move m) {
return m & 0xFFF;
}
-inline MoveType type_of(Move m) {
+constexpr MoveType type_of(Move m) {
return MoveType(m & (3 << 14));
}
-inline PieceType promotion_type(Move m) {
+constexpr PieceType promotion_type(Move m) {
return PieceType(((m >> 12) & 3) + KNIGHT);
}
@@ -438,11 +456,11 @@ inline Move make_move(Square from, Square to) {
}
template
-inline Move make(Square from, Square to, PieceType pt = KNIGHT) {
+constexpr Move make(Square from, Square to, PieceType pt = KNIGHT) {
return Move(T + ((pt - KNIGHT) << 12) + (from << 6) + to);
}
-inline bool is_ok(Move m) {
+constexpr bool is_ok(Move m) {
return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE
}
diff --git a/Engines/Linux32/mcbrain/src/tzbook.cpp b/Engines/Linux32/mcbrain/src/tzbook.cpp
deleted file mode 100644
index 4052256..0000000
--- a/Engines/Linux32/mcbrain/src/tzbook.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-#include "tzbook.h"
-#include "uci.h"
-#include "movegen.h"
-#include "thread.h"
-#include
-#include "misc.h"
-#include
-
-TZBook tzbook; // global TZBook
-
-using namespace std;
-
-int qsort_compare_int(const void* a, const void* b)
-{
- const int int_a = *((const int*)a);
- const int int_b = *((const int*)b);
-
- if (int_a == int_b) return 0;
- else if (int_a < int_b) return -1;
- else return 1;
-}
-
-TZBook::TZBook()
-{
- keycount = 0;
- book_move2_probability = 0;
- last_position = 0;
- akt_position = 0;
- last_anz_pieces = 0;
- akt_anz_pieces = 0;
- search_counter = 0;
- tzhash2 = NULL;
- do_search = true;
- enabled = false;
-}
-
-TZBook::~TZBook()
-{
-}
-
-
-void TZBook::init(const std::string& path)
-{
- if (path.length() == 0) return;
-
- const char *p = path.c_str();
- if (strcmp(p, "") == 0)
- return;
-
- FILE *fpt = fopen(p, "rb");
- if (fpt == NULL)
- {
- sync_cout << "info string Could not open " << path << sync_endl;
- return;
- }
-
- if (tzhash2 != NULL)
- {
- free(tzhash2);
- tzhash2 = NULL;
- }
-
- fseek(fpt, 0L, SEEK_END);
- int filesize = ftell(fpt);
- fseek(fpt, 0L, SEEK_SET);
-
- keycount = filesize / 8;
- tzhash2 = new TZHash2[keycount];
-
- fread(tzhash2, 1, filesize, fpt);
- fclose(fpt);
-
- sync_cout << "info string Book loaded: " << path << sync_endl;
-
- srand((int)time(NULL));
- enabled = true;
-}
-
-
-void TZBook::set_book_move2_probability(int book_move2_prob)
-{
- book_move2_probability = book_move2_prob;
-}
-
-
-Move TZBook::probe2(Position& pos)
-{
- Move m = MOVE_NONE;
- if (!enabled) return m;
-
- akt_position = pos.pieces();
- akt_anz_pieces = popcount(akt_position);
-
- if (do_search == false)
- {
- Bitboard b = akt_position ^ last_position;
- int n2 = popcount(b);
-
- if (n2 > 4) do_search = true;
- if (akt_anz_pieces > last_anz_pieces) do_search = true;
- if (akt_anz_pieces < last_anz_pieces - 2) do_search = true;
- }
-
- last_position = akt_position;
- last_anz_pieces = akt_anz_pieces;
-
- if (do_search)
- {
- TZHash2 *tz = probe2(pos.key());
- if (tz == NULL)
- {
- search_counter++;
- if (search_counter > 2)
- {
- do_search = false;
- search_counter = 0;
- }
- }
- else
- {
- if (pos.is_draw(64))
- m = get_move_from_draw_position(pos, tz);
- else
- m = get_move(pos, tz);
- }
- }
-
- return m;
-}
-
-
-TZHash2 *TZBook::probe2(Key key)
-{
- uint32_t key1 = key >> 32;
- unsigned short key2 = key >> 16 & 0xFFFF;
-
- int start = 0;
- int end = keycount;
-
- for (;;)
- {
- int mid = (end + start) / 2;
-
- if (tzhash2[mid].key1 < key1)
- start = mid;
- else
- {
- if (tzhash2[mid].key1 > key1)
- end = mid;
- else
- {
- start = max(mid - 4, 0);
- end = min(mid + 4, keycount);
- }
- }
-
- if (end - start < 9)
- break;
- }
-
- for (int i = start; i < end; i++)
- if ((key1 == tzhash2[i].key1) && (key2 == tzhash2[i].key2))
- return &(tzhash2[i]);
-
- return NULL;
-}
-
-Move TZBook::movenumber_to_move(Position& pos, int n)
-{
- const ExtMove *m = MoveList(pos).begin();
- size_t size = MoveList(pos).size();
- Move *mv = new Move[size];
- for (unsigned int i = 0; i < size; i++)
- mv[i] = m[i].move;
-
- qsort(mv, size, sizeof(mv[0]), qsort_compare_int);
-
- return mv[n];
-}
-
-bool TZBook::check_draw(Move m, Position& pos)
-{
- StateInfo st;
-
- pos.do_move(m, st, pos.gives_check(m));
- bool draw = pos.is_draw(64);
- pos.undo_move(m);
-
- return draw;
-}
-
-
-Move TZBook::get_move_from_draw_position(Position& pos, TZHash2 *tz)
-{
- Move m = movenumber_to_move(pos, tz->move_number);
- if (!check_draw(m, pos))
- return m;
-
- if (tz->move_number2 == 255)
- return m;
-
- m = movenumber_to_move(pos, tz->move_number2);
- if (!check_draw(m, pos))
- return m;
-
- return MOVE_NONE;
-}
-
-
-Move TZBook::get_move(Position& pos, TZHash2 *tz)
-{
- Move m1 = movenumber_to_move(pos, tz->move_number);
- if ((book_move2_probability == 0) || (tz->move_number2 == 255))
- return m1;
-
- Move m2 = movenumber_to_move(pos, tz->move_number2);
- if ((book_move2_probability == 100) || (rand() % 100 < book_move2_probability))
- return m2;
-
- return m1;
-}
\ No newline at end of file
diff --git a/Engines/Linux32/mcbrain/src/tzbook.h b/Engines/Linux32/mcbrain/src/tzbook.h
deleted file mode 100644
index 744618a..0000000
--- a/Engines/Linux32/mcbrain/src/tzbook.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef TZBOOK_H_INCLUDED
-#define TZBOOK_H_INCLUDED
-
-#include "bitboard.h"
-#include "position.h"
-#include "string.h"
-
-struct TZHash2
-{
- uint32_t key1;
- uint16_t key2;
- unsigned char move_number;
- unsigned char move_number2;
-};
-
-class TZBook
-{
- public:
-
- Bitboard last_position;
- Bitboard akt_position;
- int last_anz_pieces;
- int akt_anz_pieces;
- int search_counter;
-
- bool enabled, do_search;
- int book_move2_probability;
-
- TZBook();
- ~TZBook();
-
- void init(const std::string& path);
- void set_book_move2_probability(int book_move2_prob);
-
- Move probe2(Position& pos);
- TZHash2 *probe2(Key key);
-
-private:
-
- int keycount;
- TZHash2 *tzhash2;
- bool check_draw(Move m, Position& pos);
- Move get_move_from_draw_position(Position& pos, TZHash2 *tz);
- Move get_move(Position& pos, TZHash2 *tz);
- Move movenumber_to_move(Position& pos, int n);
-};
-
-extern TZBook tzbook;
-
-#endif // #ifndef TZBOOK_H_INCLUDED
\ No newline at end of file
diff --git a/Engines/Linux32/mcbrain/src/uci.cpp b/Engines/Linux32/mcbrain/src/uci.cpp
index 0b9c680..40efb6d 100644
--- a/Engines/Linux32/mcbrain/src/uci.cpp
+++ b/Engines/Linux32/mcbrain/src/uci.cpp
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
@@ -103,7 +104,33 @@ namespace {
else
sync_cout << "No such option: " << name << sync_endl;
}
-
+
+ // set() is called by typing "s" from the terminal when the user wants to use abbreviated
+ // non-UCI comamnds and avoid the uci option protocol "setoption name (option name) value (xxx) ",
+ // e.g., instead of typing "setoption name threads value 8" to set cores to 8 at the terminal,
+ // the user simply types "s threads 8" - restricted to option names that do not contain
+ // any white spaces - see ucioption.cpp. The argument can take white spaces e.g.,
+ // "s syzygypath /endgame tablebases/syzygy" will work
+ void set(istringstream& is) {
+ string token, name, value;
+
+ // Read option name (no white spaces in option name)
+ is >> token;
+ name = token;
+
+ // Read option value (can contain white spaces)
+ while (is >> token)
+ value += string(" ", value.empty() ? 0 : 1) + token;
+
+ // provide user confirmation
+ if (Options.count(name)) {
+ Options[name] = value;
+ sync_cout << "Confirmation: "<< name << " set to " << value << sync_endl;
+
+ }
+ else
+ sync_cout << "No such option: " << name << sync_endl;
+ }
// go() is called when engine receives the "go" UCI command. The function sets
// the thinking time and other parameters from the input string, then starts
@@ -132,6 +159,7 @@ namespace {
else if (token == "nodes") is >> limits.nodes;
else if (token == "movetime") is >> limits.movetime;
else if (token == "mate") is >> limits.mate;
+ else if (token == "perft") is >> limits.perft;
else if (token == "infinite") limits.infinite = 1;
else if (token == "i") limits.infinite = 1;
else if (token == "ponder") ponderMode = true;;
@@ -167,6 +195,7 @@ namespace {
nodes += Threads.nodes_searched();
}
else if (token == "setoption") setoption(is);
+ else if (token == "s") set(is);
else if (token == "position") position(pos, is, states);
else if (token == "ucinewgame") Search::clear();
}
@@ -222,6 +251,7 @@ void UCI::loop(int argc, char* argv[]) {
if ( token == "quit"
|| token == "q"
|| token == "stop"
+ || token == "?"
|| (token == "ponderhit" && Threads.stopOnPonderhit))
Threads.stop = true;
@@ -235,19 +265,21 @@ void UCI::loop(int argc, char* argv[]) {
else if (token == "setoption") setoption(is);
else if (token == "so") setoption(is);
+ else if (token == "set") set(is);
+ else if (token == "s") set(is);
else if (token == "go") go(pos, is, states);
else if (token == "g") go(pos, is, states);
else if (token == "q") cmd = "quit";
else if (token == "position")
{
position(pos, is, states);
- if (Options["Clean Search"] == 1)
+ if (Options["Clean_Search"] == true)
Search::clear();
}
else if (token == "p")
{
position(pos, is, states);
- if (Options["Clean Search"] == 1)
+ if (Options["Clean_Search"] == true)
Search::clear();
}
else if (token == "ucinewgame") Search::clear();
@@ -256,7 +288,7 @@ void UCI::loop(int argc, char* argv[]) {
// Additional custom non-UCI commands, mainly for debugging
else if (token == "flip") pos.flip();
else if (token == "bench") bench(pos, is, states);
- else if (token == "b") bench(pos, is, states);
+ else if (token == "b") bench(pos, is, states);
else if (token == "d") sync_cout << pos << sync_endl;
else if (token == "eval") sync_cout << Eval::trace(pos) << sync_endl;
else
diff --git a/Engines/Linux32/mcbrain/src/uci.h b/Engines/Linux32/mcbrain/src/uci.h
index e6b31c5..713468b 100644
--- a/Engines/Linux32/mcbrain/src/uci.h
+++ b/Engines/Linux32/mcbrain/src/uci.h
@@ -1,22 +1,23 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 UCI_H_INCLUDED
#define UCI_H_INCLUDED
@@ -50,11 +51,13 @@ class Option {
Option(bool v, OnChange = nullptr);
Option(const char* v, OnChange = nullptr);
Option(int v, int minv, int maxv, OnChange = nullptr);
+ Option(const char* v, const char *cur, OnChange = nullptr);
Option& operator=(const std::string&);
void operator<<(const Option&);
operator int() const;
operator std::string() const;
+ bool operator==(const char*);
private:
friend std::ostream& operator<<(std::ostream&, const OptionsMap&);
diff --git a/Engines/Linux32/mcbrain/src/ucioption.cpp b/Engines/Linux32/mcbrain/src/ucioption.cpp
index abc5fba..3c31396 100644
--- a/Engines/Linux32/mcbrain/src/ucioption.cpp
+++ b/Engines/Linux32/mcbrain/src/ucioption.cpp
@@ -1,32 +1,33 @@
/*
- 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-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
- 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 .
-*/
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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
#include
#include "misc.h"
+#include "polybook.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
-#include "tzbook.h"
#include "uci.h"
#include "tbprobe.h"
@@ -42,8 +43,9 @@ void on_hash_size(const Option& o) { TT.resize(o); }
void on_logger(const Option& o) { start_logger(o); }
void on_threads(const Option& o) { Threads.set(o); }
void on_tb_path(const Option& o) { Tablebases::init(o); }
-void on_brainbook_path(const Option& o) { tzbook.init(o); }
-void on_book_move2_prob(const Option& o) { tzbook.set_book_move2_probability(o); }
+void on_book_file(const Option& o) { polybook.init(o); }
+void on_best_book_move(const Option& o) { polybook.set_best_book_move(o); }
+void on_book_depth(const Option& o) { polybook.set_book_depth(o); }
/// Our case insensitive less() function as required by UCI protocol
@@ -58,35 +60,46 @@ bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const
void init(OptionsMap& o) {
- const int MaxHashMB = Is64Bit ? 1024 * 1024 : 2048;
+ // at most 2^32 clusters.
+ const int MaxHashMB = Is64Bit ? 131072 : 2048;
+ o["Debug Log File"] << Option("", on_logger);
+ o["Contempt"] << Option(20, -100, 100);
+ o["Analysis Contempt"] << Option("Off var Off var White var Black var Both", "Off");
+ o["UCI_AnalyseMode"] << Option(false);
+ o["Tactical"] << Option(0, 0, 8);
+ o["Threads"] << Option(1, 1, 512, on_threads);
o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size);
o["Ponder"] << Option(false);
o["Threads"] << Option(1, 1, 512, on_threads);
-
- o["Clear Hash"] << Option(on_clear_hash);
- o["Clean Search"] << Option(false);
+ o["Clear_Hash"] << Option(on_clear_hash);
+ o["Clean_Search"] << Option(false);
o["BruteForce"] << Option(false);
o["FastPlay"] << Option(false);
o["No_Null_Moves"] << Option(false);
+ o["UCI_Chess960"] << Option(false);
o["UCI_LimitStrength"] << Option(false);
- o["UCI_ELO"] << Option(1500, 1500, 2800);
- o["Book Move2 Probability"]<< Option(0, 0, 100, on_book_move2_prob);
- o["BookPath"] << Option("", on_brainbook_path);
- o["Respect"] << Option(0, -300, 300);
- o["Respect White POV"] << Option(0, -300, 300);
- o["Tactical"] << Option(0, 0, 8);
- o["MultiPV"] << Option(1, 1, 500);
+ o["UCI_ELO"] << Option(1500, 1500, 2800);
o["Skill Level"] << Option(20, 0, 20);
- o["Move Overhead"] << Option(60, 0, 5000);
+
+ o["MultiPV"] << Option(1, 1, 256);
+
+
+ o["Move Overhead"] << Option(30, 0, 5000);
+ o["Minimum Thinking Time"] << Option(20, 0, 5000);
+ o["Slow Mover"] << Option(89, 10, 1000);
o["nodestime"] << Option(0, 0, 10000);
- o["UCI_Chess960"] << Option(false);
+
o["SyzygyPath"] << Option("", on_tb_path);
o["SyzygyProbeDepth"] << Option(1, 1, 100);
o["Syzygy50MoveRule"] << Option(true);
o["SyzygyProbeLimit"] << Option(6, 0, 6);
- o["Debug Log File"] << Option("", on_logger);
+ o["Book_Enabled"] << Option(false);
+ o["BookFile"] << Option("", on_book_file);
+ o["BestBookMove"] << Option(true, on_best_book_move);
+ o["BookDepth"] << Option(255, 1, 255, on_book_depth);
+ o["Debug"] << Option("", on_logger);
}
@@ -129,6 +142,9 @@ Option::Option(OnChange f) : type("button"), min(0), max(0), on_change(f)
Option::Option(int v, int minv, int maxv, OnChange f) : type("spin"), min(minv), max(maxv), on_change(f)
{ defaultValue = currentValue = std::to_string(v); }
+Option::Option(const char* v, const char* cur, OnChange f) : type("combo"), min(0), max(0), on_change(f)
+{ defaultValue = v; currentValue = cur; }
+
Option::operator int() const {
assert(type == "check" || type == "spin");
return (type == "spin" ? stoi(currentValue) : currentValue == "true");
@@ -139,6 +155,11 @@ Option::operator std::string() const {
return currentValue;
}
+bool Option::operator==(const char* s) {
+ assert(type == "combo");
+ return !CaseInsensitiveLess()(currentValue, s) && !CaseInsensitiveLess()(s, currentValue);
+}
+
/// operator<<() inits options and assigns idx in the correct printing order
diff --git a/Engines/Linux64/mcbrain/.travis.yml b/Engines/Linux64/mcbrain/.travis.yml
index 87a3e7d..0a214d1 100644
--- a/Engines/Linux64/mcbrain/.travis.yml
+++ b/Engines/Linux64/mcbrain/.travis.yml
@@ -18,11 +18,12 @@ matrix:
compiler: clang
addons:
apt:
- sources: ['ubuntu-toolchain-r-test']
- packages: ['clang', 'g++-multilib', 'valgrind', 'expect']
+ sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0']
+ packages: ['clang-5.0', 'llvm-5.0-dev', 'g++-multilib', 'valgrind', 'expect']
env:
- - COMPILER=clang++
+ - COMPILER=clang++-5.0
- COMP=clang
+ - LDFLAGS=-fuse-ld=gold
- os: osx
compiler: gcc
@@ -44,30 +45,30 @@ before_script:
- cd src
script:
- #
- # checking bench for various build types
- #
- # obtain reference from git log
- - git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9][0-9]*\)/\1/g" > git_sig
+ # Obtain bench reference from git log
+ - git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9]*\).*/\1/g" > git_sig
- export benchref=$(cat git_sig)
- echo "Reference bench:" $benchref
- # verify against reference
- - make clean && make ARCH=x86-64 build > /dev/null && ../tests/signature.sh $benchref
- - make clean && make ARCH=x86-32 build > /dev/null && ../tests/signature.sh $benchref
- #
- # perft
- #
- - make clean && make ARCH=x86-64 build > /dev/null && ../tests/perft.sh
#
- # reproducible search
+ # Verify bench number against various builds
+ - export CXXFLAGS=-Werror
+ - make clean && make -j2 ARCH=x86-64 optimize=no debug=yes build && ../tests/signature.sh $benchref
+ - make clean && make -j2 ARCH=x86-32 optimize=no debug=yes build && ../tests/signature.sh $benchref
+ - make clean && make -j2 ARCH=x86-32 build && ../tests/signature.sh $benchref
+ - make clean && make -j2 ARCH=x86-64 build && ../tests/signature.sh $benchref
#
- - make clean && make ARCH=x86-64 build > /dev/null && ../tests/reprosearch.sh
+ # Check perft and reproducible search
+ - ../tests/perft.sh
+ - ../tests/reprosearch.sh
#
- # valgrind
+ # Valgrind
#
- - if [ -x "$(command -v valgrind )" ]; then make clean && make ARCH=x86-64 debug=yes optimize=no build > /dev/null && ../tests/instrumented.sh --valgrind; fi
+ - export CXXFLAGS=-O1
+ - if [ -x "$(command -v valgrind )" ]; then make clean && make -j2 ARCH=x86-64 debug=yes optimize=no build > /dev/null && ../tests/instrumented.sh --valgrind; fi
+ - if [ -x "$(command -v valgrind )" ]; then ../tests/instrumented.sh --valgrind-thread; fi
#
- # sanitizer
+ # Sanitizer
#
- # use g++-6 as a proxy for having sanitizers, might need revision as they become available for more recent versions of clang/gcc
- - if [[ "$COMPILER" == "g++-6" ]]; then make clean && make ARCH=x86-64 sanitize=yes build > /dev/null && ../tests/instrumented.sh --sanitizer; fi
+ # Use g++-6 as a proxy for having sanitizers, might need revision as they become available for more recent versions of clang/gcc
+ - if [[ "$COMPILER" == "g++-6" ]]; then make clean && make -j2 ARCH=x86-64 sanitize=undefined optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-undefined; fi
+ - if [[ "$COMPILER" == "g++-6" ]]; then make clean && make -j2 ARCH=x86-64 sanitize=thread optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-thread; fi
diff --git a/Engines/Linux64/mcbrain/AUTHORS b/Engines/Linux64/mcbrain/AUTHORS
index 3095efc..9b91b93 100644
--- a/Engines/Linux64/mcbrain/AUTHORS
+++ b/Engines/Linux64/mcbrain/AUTHORS
@@ -1,6 +1,5 @@
# Generated with 'git shortlog -sn | cut -c8-', which sorts by commits, manually ordered the first four authors, merged duplicates
-Michael Byrne (McBrain)
Tord Romstad
Marco Costalba (mcostalba)
Joona Kiiski (zamar)
@@ -95,4 +94,5 @@ ppigazzini
renouve
sf-x
thaspel
+unknown
diff --git a/Engines/Linux64/mcbrain/McBrain-9_x64_linux b/Engines/Linux64/mcbrain/McBrain-9_x64_linux
new file mode 100644
index 0000000..26fd9a3
Binary files /dev/null and b/Engines/Linux64/mcbrain/McBrain-9_x64_linux differ
diff --git a/Engines/Linux64/mcbrain/Readme.md b/Engines/Linux64/mcbrain/Readme.md
index e3b36cc..46f2609 100644
--- a/Engines/Linux64/mcbrain/Readme.md
+++ b/Engines/Linux64/mcbrain/Readme.md
@@ -98,9 +98,9 @@ for a quick reference.
### Resource For Understanding the Code Base
-* [Chessprogramingwiki](https://chessprogramming.wikispaces.com) has good overall chess engines explanations
+* [Chess Programming Wiki](https://chessprogramming.wikispaces.com) has good overall chess engines explanations
(techniques used here are well explained like hash maps etc), it was
-also recommended by the [support at stockfish.](http://support.stockfishchess.org/discussions/questions/1132-how-to-understand-stockfish-sources)
+also recommended by the [support team at stockfish.](http://support.stockfishchess.org/discussions/questions/1132-how-to-understand-stockfish-sources)
* [Here](https://chessprogramming.wikispaces.com/Stockfish) you can find a set of features and techniques used by stockfish and each of them is explained at the wiki, however, it's a generic way rather than focusing on stockfish's own implementation, but it will still help you.
diff --git a/Engines/Linux64/mcbrain/SF-McBrain-v40_x64_linux b/Engines/Linux64/mcbrain/SF-McBrain-v40_x64_linux
deleted file mode 100644
index 0979c1e..0000000
Binary files a/Engines/Linux64/mcbrain/SF-McBrain-v40_x64_linux and /dev/null differ
diff --git a/Engines/Linux64/mcbrain/Top CPU Contributors.txt b/Engines/Linux64/mcbrain/Top CPU Contributors.txt
index 0bb2a92..4c2aa47 100644
--- a/Engines/Linux64/mcbrain/Top CPU Contributors.txt
+++ b/Engines/Linux64/mcbrain/Top CPU Contributors.txt
@@ -1,93 +1,132 @@
-Contributors with >10,000 CPU hours as of November 3, 2016
+Contributors with >10,000 CPU hours as of January 23, 2018
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
+Username CPU Hours Games played
+mibere 518300 41835669
+crunchy 375564 29121434
+cw 371664 28748719
+fastgm 299773 20765374
+JojoM 220590 15299913
+glinscott 204517 13932027
+bking_US 187568 12233168
+ctoks 169342 13475495
+spams 149531 10940322
+Thanar 137015 11714855
+velislav 127305 10047749
+vdbergh 121741 9056874
+malala 117291 8126488
+vdv 117218 8289983
+leszek 114825 8331897
+dsmith 114010 7622414
+CSU_Dynasty 113516 9582758
+sqrt2 112407 8782694
+marrco 111143 8222921
+drabel 108168 9061580
+BrunoBanani 104938 7448565
+Data 94621 8433010
+CoffeeOne 90394 3964243
+BRAVONE 80811 5341681
+psk 77195 6156031
+brabos 70284 5685893
+Fisherman 66650 5572406
+nssy 64587 5369140
+Pking_cda 64499 5704075
+sterni1971 63488 5070004
+mgrabiak 62385 5420812
+tvijlbrief 58957 4154234
+jromang 58854 4704502
+dv8silencer 57421 3961325
+sunu 56620 4609155
+tinker 56039 4204914
+biffhero 55743 4810039
+teddybaer 52982 4740444
+bcross 50548 5071599
+renouve 50318 3544864
+Freja 50296 3805120
+robnjr 47504 4131742
+eva42 46542 4044694
+davar 46538 4030604
+finfish 46244 3481661
+rap 46201 3219490
+ttruscott 45037 3645430
+solarlight 44155 4074841
+TueRens 41372 3891510
+ElbertoOne 41321 3920894
+Antihistamine 39218 2792761
+mhunt 38991 2697512
+bigpen0r 37820 3149955
+homyur 35569 3009637
+VoyagerOne 35137 3302650
+mhoram 34770 2684128
+racerschmacer 33022 3231055
+speedycpu 32043 2531964
+EthanOConnor 31638 2143255
+oryx 29574 2767730
+Pyafue 28885 1986098
+jkiiski 28014 1923255
+Garf 27579 2770144
+slakovv 27017 2031279
+Bobo1239 27000 2488707
+pb00067 26817 2306694
+robal 26337 2316795
+hyperbolic.tom 26248 2200777
+rkl 24898 2236013
+SC 23988 2126825
+nabildanial 23524 1586321
+achambord 23495 1942546
+Sharaf_DG 22975 1790697
+chriswk 22876 1947731
+anst 22568 2013953
+Patrick_G 22435 1682293
+cuistot 22201 1383031
+gri 21901 1820968
+Prcuvu 21182 1890546
+Zirie 21171 1493227
+JanErik 20596 1791991
+Isidor 20560 1730290
+xor12 20535 1819280
+team-oh 20364 1653708
+nesoneg 20264 1493435
+rstoesser 19802 1335177
+grandphish2 19402 1834196
+sg4032 18427 1671742
+dew 18263 1423326
+ianh2105 18133 1668562
+MazeOfGalious 18022 1644593
+ville 17900 1539130
+j3corre 17607 975954
+eudhan 17502 1424648
+iisiraider 17175 1118788
+jundery 17172 1115855
+SFTUser 16635 1363975
+purplefishies 16621 1106850
+DragonLord 16599 1252348
+chris 15274 1575333
+xoto 14900 1486261
+dju 14861 901552
+dex 14647 1228763
+nordlandia 14551 1369718
+ronaldjerum 14361 1210607
+OssumOpossum 14149 1029265
+IgorLeMasson 13844 1228391
+enedene 13762 935618
+ako027ako 13442 1250249
+AdrianSA 13324 924980
+bpfliegel 13318 886523
+ncfish1 13056 932344
+wei 12863 1369596
+jpulman 12776 854815
+horst.prack 12436 1151505
+joster 12424 986622
+cisco2015 12265 1205019
+fatmurphy 12015 901134
+modolief 11228 926456
+Dark_wizzie 11214 1017910
+mschmidt 10973 818594
+eastorwest 10970 1117836
+infinity 10762 746397
+SapphireBrand 10692 1024604
+Thomas A. 10553 736094
+pgontarz 10294 878746
+Andrew Grant 10195 922933
+stocky 10083 718114
diff --git a/Engines/Linux64/mcbrain/appveyor.yml b/Engines/Linux64/mcbrain/appveyor.yml
index a46a0f3..c711dd6 100644
--- a/Engines/Linux64/mcbrain/appveyor.yml
+++ b/Engines/Linux64/mcbrain/appveyor.yml
@@ -1,5 +1,5 @@
version: 1.0.{build}
-clone_depth: 5
+clone_depth: 50
branches:
only:
@@ -13,10 +13,11 @@ os: Visual Studio 2015
platform:
- x86
- x64
- - Any CPU
# build Configuration, i.e. Debug, Release, etc.
-configuration: Debug
+configuration:
+ - Debug
+ - Release
matrix:
# The build fail immediately once one of the job fails
@@ -28,18 +29,43 @@ init:
- msbuild /version
before_build:
- - cd src
- - echo project (Stockfish) >> CMakeLists.txt
- - echo add_executable(stockfish benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp >> CMakeLists.txt
- - echo main.cpp material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp >> CMakeLists.txt
- - echo search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp syzygy/tbprobe.cpp) >> CMakeLists.txt
- - echo set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src) >> CMakeLists.txt
-# - echo target_compile_options(stockfish PUBLIC "/Ox") >> CMakeLists.txt
+ - ps: |
+ # Get sources
+ $src = get-childitem -Path *.cpp -Recurse | select -ExpandProperty FullName
+ $src = $src -join ' '
+ $src = $src.Replace("\", "/")
+
+ # Build CMakeLists.txt
+ $t = 'cmake_minimum_required(VERSION 3.8)',
+ 'project(Stockfish)',
+ 'set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src)',
+ 'set(source_files', $src, ')',
+ 'add_executable(stockfish ${source_files})'
+
+ # Write CMakeLists.txt withouth BOM
+ $MyPath = (Get-Item -Path "." -Verbose).FullName + '\CMakeLists.txt'
+ $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
+ [System.IO.File]::WriteAllLines($MyPath, $t, $Utf8NoBomEncoding)
+
+ # Obtain bench reference from git log
+ $b = git log HEAD | sls "\b[Bb]ench[ :]+[0-9]{7}" | select -first 1
+ $bench = $b -match '\D+(\d+)' | % { $matches[1] }
+ Write-Host "Reference bench:" $bench
+ $g = "Visual Studio 14 2015"
+ If (${env:PLATFORM} -eq 'x64') { $g = $g + ' Win64' }
+ cmake -G "${g}" .
+ Write-Host "Generated files for: " $g
build_script:
- - cmake -G "Visual Studio 14 2015 Win64" .
- - cmake --build .
+ - cmake --build . --config %CONFIGURATION% -- /verbosity:minimal
before_test:
- - cd Debug
- - stockfish.exe bench > null
+ - cd src/%CONFIGURATION%
+ - ps: |
+ # Verify bench number
+ ./stockfish bench 2> out.txt 1> null
+ $s = (gc "./out.txt" | out-string)
+ $r = ($s -match 'Nodes searched \D+(\d+)' | % { $matches[1] })
+ Write-Host "Engine bench:" $r
+ Write-Host "Reference bench:" $bench
+ If ($r -ne $bench) { exit 1 }
diff --git a/Engines/Linux64/mcbrain/src/Makefile b/Engines/Linux64/mcbrain/src/Makefile
index f1d5dec..6e66fbb 100644
--- a/Engines/Linux64/mcbrain/src/Makefile
+++ b/Engines/Linux64/mcbrain/src/Makefile
@@ -5,7 +5,7 @@
# Copyright (C) 2004-2008 Tord Romstad (Glaurung Author)
# Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
# Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
-# Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+# Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
# McBrain is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -30,8 +30,8 @@ ifeq ($(KERNEL),Linux)
endif
### Executable name
-EXE = SF-McBrain-v40
-### bench nodes -> Nodes searched : 6376731
+EXE = McBrain-9
+### bench nodes -> Nodes searched : 6871658
### Installation dir definitions
PREFIX = /usr/local
@@ -156,7 +156,7 @@ endif
ifeq ($(COMP),gcc)
comp=gcc
CXX=g++
- CXXFLAGS += -pedantic -Wextra -Wshadow -static-libstdc++
+ CXXFLAGS += -pedantic -Wextra -Wshadow
ifeq ($(ARCH),armv7)
ifeq ($(OS),Android)
@@ -280,9 +280,7 @@ endif
### 3.3 Optimization
ifeq ($(optimize),yes)
-CXXFLAGS += -O1 -O3 -msse4.2 -mpopcnt -mtune=native
-####-Os -O1 -mtune=native
-#### for those on macOS High Sierra 10.13 and higher use, "-Os -O1 -mtune=native" for PGO using gcc7
+ CXXFLAGS += -O3 -mtune=native
ifeq ($(comp),gcc)
@@ -308,8 +306,6 @@ CXXFLAGS += -O1 -O3 -msse4.2 -mpopcnt -mtune=native
ifeq ($(comp),clang)
ifeq ($(KERNEL),Darwin)
- CXXFLAGS += -flto
- LDFLAGS += $(CXXFLAGS)
ifeq ($(arch),i386)
CXXFLAGS += -mdynamic-no-pic
endif
@@ -355,24 +351,20 @@ endif
### 3.8 Link Time Optimization, it works since gcc 4.5 but not on mingw under Windows.
### This is a mix of compile and link time options because the lto link phase
### needs access to the optimization flags.
-ifeq ($(comp),gcc)
- ifeq ($(optimize),yes)
- ifeq ($(debug),no)
+ifeq ($(optimize),yes)
+ifeq ($(debug), no)
+ ifeq ($(comp),$(filter $(comp),gcc clang))
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS)
endif
- endif
-endif
-ifeq ($(comp),mingw)
+ ifeq ($(comp),mingw)
ifeq ($(KERNEL),Linux)
- ifeq ($(optimize),yes)
- ifeq ($(debug),no)
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS)
endif
endif
- endif
+endif
endif
### 3.9 Android 5 can only run position independent executables. Note that this
@@ -440,7 +432,6 @@ help:
build: config-sanity
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) all
strip $(EXE)
- cp $(EXE) /Users/michaelbyrne/cluster.mfb/$(EXE)
profile-build: config-sanity objclean profileclean
@echo ""
@@ -460,7 +451,12 @@ profile-build: config-sanity objclean profileclean
@echo "Step 5/5. Deleting profile data ..."
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) profileclean
strip $(EXE)
- cp $(EXE) /Users/michaelbyrne/cluster.mfb/$(EXE)
+
+cprom:
+ make -j profile-build ARCH=x86-64-modern COMP=clang
+
+cprob:
+ make -j profile-build ARCH=x86-64-bmi2 COMP=clang
strip:
strip $(EXE)
diff --git a/Engines/Linux64/mcbrain/src/benchmark.cpp b/Engines/Linux64/mcbrain/src/benchmark.cpp
index f5499ef..807f9de 100644
--- a/Engines/Linux64/mcbrain/src/benchmark.cpp
+++ b/Engines/Linux64/mcbrain/src/benchmark.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/bitbase.cpp b/Engines/Linux64/mcbrain/src/bitbase.cpp
index ae5c879..a651e27 100644
--- a/Engines/Linux64/mcbrain/src/bitbase.cpp
+++ b/Engines/Linux64/mcbrain/src/bitbase.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/bitboard.cpp b/Engines/Linux64/mcbrain/src/bitboard.cpp
index d84d447..9dd637b 100644
--- a/Engines/Linux64/mcbrain/src/bitboard.cpp
+++ b/Engines/Linux64/mcbrain/src/bitboard.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/bitboard.h b/Engines/Linux64/mcbrain/src/bitboard.h
index 598bbbc..c964d1e 100644
--- a/Engines/Linux64/mcbrain/src/bitboard.h
+++ b/Engines/Linux64/mcbrain/src/bitboard.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/endgame.cpp b/Engines/Linux64/mcbrain/src/endgame.cpp
index 2bf6501..3d568f5 100644
--- a/Engines/Linux64/mcbrain/src/endgame.cpp
+++ b/Engines/Linux64/mcbrain/src/endgame.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/endgame.h b/Engines/Linux64/mcbrain/src/endgame.h
index 3bc3a02..3bace6f 100644
--- a/Engines/Linux64/mcbrain/src/endgame.h
+++ b/Engines/Linux64/mcbrain/src/endgame.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
diff --git a/Engines/Linux64/mcbrain/src/evaluate.cpp b/Engines/Linux64/mcbrain/src/evaluate.cpp
index a7d304a..e420d3d 100644
--- a/Engines/Linux64/mcbrain/src/evaluate.cpp
+++ b/Engines/Linux64/mcbrain/src/evaluate.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -98,6 +98,7 @@ namespace {
template void initialize();
template Score evaluate_king();
template Score evaluate_threats();
+ int king_distance(Color c, Square s);
template Score evaluate_passed_pawns();
template Score evaluate_space();
template Score evaluate_pieces();
@@ -112,7 +113,8 @@ namespace {
Score mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO };
// attackedBy[color][piece type] is a bitboard representing all squares
- // attacked by a given color and piece type (can be also ALL_PIECES).
+ // attacked by a given color and piece type. Special "piece types" which are
+ // also calculated are QUEEN_DIAGONAL and ALL_PIECES.
Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB];
// attackedBy2[color] are the squares attacked by 2 pieces of a given color,
@@ -184,23 +186,23 @@ namespace {
// 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)
- };
+ S(0, 0), S(0, 31), S(39, 42), S(57, 44), S(68, 112), S(47, 120)
+ }; //Fauzi Akram
const Score ThreatByRook[PIECE_TYPE_NB] = {
- S(0, 0), S(0, 25), S(40, 62), S(40, 59), S(0, 34), S(35, 48)
- };
+ S(0, 0), S(0, 24), S(38, 71), S(38, 61), S(0, 38), S(36, 38)
+ }; //Fauzi Akram
// ThreatByKing[on one/on many] contains bonuses for king attacks on
// pawns or pieces which are not pawn-defended.
- const Score ThreatByKing[] = { S(3, 62), S(9, 138) };
+ const Score ThreatByKing[] = { S(3, 65), S(9, 145) }; //Fauzi Akram
// Passed[mg/eg][Rank] contains midgame and endgame bonuses for passed pawns.
// We don't use a Score because we process the two components independently.
const Value Passed[][RANK_NB] = {
- { V(5), V( 5), V(31), V(73), V(166), V(252) },
- { V(7), V(14), V(38), V(73), V(166), V(252) }
- };
+ { V(0), V(5), V( 5), V(32), V(70), V(172), V(217) },
+ { V(0), V(7), V(13), V(42), V(70), V(170), V(269) }
+ }; //Fauzi Akram
// PassedFile[File] contains a bonus according to the file of a passed pawn
const Score PassedFile[FILE_NB] = {
@@ -208,6 +210,9 @@ namespace {
S(-20,-12), S( 1, -8), S( 2, 10), S( 9, 10)
};
+ // Rank factor applied on some bonus for passed pawn on rank 4 or beyond
+ const int RankFactor[RANK_NB] = {0, 0, 0, 2, 7, 12, 19}; //Fauzi Akram
+
// KingProtector[PieceType-2] contains a bonus according to distance from king
const Score KingProtector[] = { S(-3, -5), S(-4, -3), S(-3, 0), S(-1, 1) };
@@ -218,17 +223,15 @@ namespace {
const Score RookOnPawn = S( 8, 24);
const Score TrappedRook = S( 92, 0);
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 ThreatBySafePawn = S(192,175);
+ const Score ThreatBySafePawn = S(175,168); //Fauzi Akram
const Score ThreatByRank = S( 16, 3);
- const Score Hanging = S( 48, 27);
+ const Score Hanging = S( 52, 30); //Fauzi Akram
const Score WeakUnopposedPawn = S( 5, 25);
- const Score ThreatByPawnPush = S( 38, 22);
- const Score ThreatByAttackOnQueen = S( 38, 22);
- const Score HinderPassedPawn = S( 7, 0);
+ const Score ThreatByPawnPush = S( 47, 26); //Fauzi Akram
+ const Score ThreatByAttackOnQueen = S( 42, 21); //Fauzi Akram
+ const Score HinderPassedPawn = S( 8, 1); //Fauzi Akram
const Score TrappedBishopA1H1 = S( 50, 50);
#undef S
@@ -238,10 +241,10 @@ namespace {
const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 78, 56, 45, 11 };
// Penalties for enemy's safe checks
- const int QueenCheck = 780;
- const int RookCheck = 880;
- const int BishopCheck = 435;
- const int KnightCheck = 790;
+ const int QueenSafeCheck = 780;
+ const int RookSafeCheck = 880;
+ const int BishopSafeCheck = 435;
+ const int KnightSafeCheck = 790;
// Threshold for lazy and space evaluation
const Value LazyThreshold = Value(1500);
@@ -312,8 +315,8 @@ namespace {
while ((s = *pl++) != SQ_NONE)
{
// Find attacked squares, including x-ray attacks for bishops and rooks
- b = Pt == BISHOP ? attacks_bb(s, pos.pieces() ^ pos.pieces(Us, QUEEN))
- : Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(Us, ROOK, QUEEN))
+ b = Pt == BISHOP ? attacks_bb(s, pos.pieces() ^ pos.pieces(QUEEN))
+ : Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(QUEEN) ^ pos.pieces(Us, ROOK))
: pos.attacks_from(s);
if (pos.pinned_pieces(Us) & s)
@@ -428,17 +431,29 @@ namespace {
Score Evaluation::evaluate_king() {
const Color Them = (Us == WHITE ? BLACK : WHITE);
- const Direction Up = (Us == WHITE ? NORTH : SOUTH);
const Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
: AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
const Square ksq = pos.square(Us);
- Bitboard weak, b, b1, b2, safe, other;
- int kingDanger;
+ Bitboard weak, b, b1, b2, safe, unsafeChecks;
// King shelter and enemy pawns storm
Score score = pe->king_safety(pos, ksq);
+ // King tropism: firstly, find squares that opponent attacks in our king flank
+ File kf = file_of(ksq);
+ b = 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));
+
+ // Secondly, add the squares which are attacked twice in that flank and
+ // which are not defended by our pawns.
+ b = (Us == WHITE ? b << 4 : b >> 4)
+ | (b & attackedBy2[Them] & ~attackedBy[Us][PAWN]);
+
+ int tropism = popcount(b);
+
// Main king safety evaluation
if (kingAttackersCount[Them] > (1 - pos.count(Them)))
{
@@ -447,18 +462,7 @@ namespace {
& ~attackedBy2[Us]
& (attackedBy[Us][KING] | attackedBy[Us][QUEEN] | ~attackedBy[Us][ALL_PIECES]);
- // 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 weak squares around our king, the absence of queen and
- // the quality of the pawn shelter (current 'score' value).
- kingDanger = kingAttackersCount[Them] * kingAttackersWeight[Them]
- + 102 * kingAdjacentZoneAttacksCount[Them]
- + 191 * popcount(kingRing[Us] & weak)
- + 143 * bool(pos.pinned_pieces(Us))
- - 848 * !pos.count(Them)
- - 9 * mg_value(score) / 8
- + 40;
+ int kingDanger = unsafeChecks = 0;
// Analyse the safe enemy's checks which are possible on next move
safe = ~pos.pieces(Them);
@@ -469,54 +473,52 @@ namespace {
// Enemy queen safe checks
if ((b1 | b2) & attackedBy[Them][QUEEN] & safe & ~attackedBy[Us][QUEEN])
- kingDanger += QueenCheck;
-
- // 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 = ~( attackedBy[Us][PAWN]
- | (pos.pieces(Them, PAWN) & shift(pos.pieces(PAWN))));
-
- // Enemy rooks safe and other checks
- if (b1 & attackedBy[Them][ROOK] & safe)
- kingDanger += RookCheck;
+ kingDanger += QueenSafeCheck;
- else if (b1 & attackedBy[Them][ROOK] & other)
- score -= OtherCheck;
+ b1 &= attackedBy[Them][ROOK];
+ b2 &= attackedBy[Them][BISHOP];
- // Enemy bishops safe and other checks
- if (b2 & attackedBy[Them][BISHOP] & safe)
- kingDanger += BishopCheck;
+ // Enemy rooks checks
+ if (b1 & safe)
+ kingDanger += RookSafeCheck;
+ else
+ unsafeChecks |= b1;
- else if (b2 & attackedBy[Them][BISHOP] & other)
- score -= OtherCheck;
+ // Enemy bishops checks
+ if (b2 & safe)
+ kingDanger += BishopSafeCheck;
+ else
+ unsafeChecks |= b2;
- // Enemy knights safe and other checks
+ // Enemy knights checks
b = pos.attacks_from(ksq) & attackedBy[Them][KNIGHT];
if (b & safe)
- kingDanger += KnightCheck;
-
- else if (b & other)
- score -= OtherCheck;
-
- // Transform the kingDanger units into a Score, and substract it from the evaluation
+ kingDanger += KnightSafeCheck;
+ else
+ unsafeChecks |= b;
+
+ // Unsafe or occupied checking squares will also be considered, as long as
+ // the square is in the attacker's mobility area.
+ unsafeChecks &= mobilityArea[Them];
+
+ kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
+ + 102 * kingAdjacentZoneAttacksCount[Them]
+ + 191 * popcount(kingRing[Us] & weak)
+ + 143 * popcount(pos.pinned_pieces(Us) | unsafeChecks)
+ - 848 * !pos.count(Them)
+ - 9 * mg_value(score) / 8
+ + 4 * tropism;
+
+ // Transform the kingDanger units into a Score, and subtract it from the evaluation
if (kingDanger > 0)
+ {
+ int mobilityDanger = (mg_value(mobility[Them] - mobility[Us])) * 2;
+ kingDanger = std::max(0, kingDanger + mobilityDanger);
score -= make_score(kingDanger * kingDanger / 4096, kingDanger / 16);
+ }
}
- // King tropism: firstly, find squares that opponent attacks in our king flank
- File kf = file_of(ksq);
- b = 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));
-
- // Secondly, add the squares which are attacked twice in that flank and
- // which are not defended by our pawns.
- b = (Us == WHITE ? b << 4 : b >> 4)
- | (b & attackedBy2[Them] & ~attackedBy[Us][PAWN]);
-
- score -= CloseEnemies * popcount(b);
+ score -= CloseEnemies * tropism;
// Penalty when our king is on a pawnless flank
if (!(pos.pieces(PAWN) & KingFlank[kf]))
@@ -555,9 +557,6 @@ namespace {
safeThreats = (shift(b) | shift(b)) & weak;
score += ThreatBySafePawn * popcount(safeThreats);
-
- if (weak ^ safeThreats)
- score += ThreatByHangingPawn;
}
// Squares strongly protected by the opponent, either because they attack the
@@ -634,6 +633,11 @@ namespace {
return score;
}
+ // helper used by evaluate_passed_pawns to cap the distance
+ template
+ int Evaluation::king_distance(Color c, Square s) {
+ return std::min(distance(pos.square(c), s), 5);
+ }
// evaluate_passed_pawns() evaluates the passed pawns and candidate passed
// pawns of the given color.
@@ -658,8 +662,8 @@ namespace {
bb = forward_file_bb(Us, s) & (attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
score -= HinderPassedPawn * popcount(bb);
- int r = relative_rank(Us, s) - RANK_2;
- int rr = r * (r - 1);
+ int r = relative_rank(Us, s);
+ int rr = RankFactor[r];
Value mbonus = Passed[MG][r], ebonus = Passed[EG][r];
@@ -668,12 +672,11 @@ namespace {
Square blockSq = s + Up;
// Adjust bonus based on the king's proximity
- ebonus += distance(pos.square(Them), blockSq) * 5 * rr
- - distance(pos.square( Us), blockSq) * 2 * rr;
+ ebonus += (king_distance(Them, blockSq) * 5 - king_distance(Us, blockSq) * 2) * rr;
// If blockSq is not the queening square then consider also a second push
- if (relative_rank(Us, blockSq) != RANK_8)
- ebonus -= distance(pos.square(Us), blockSq + Up) * rr;
+ if (r != RANK_7)
+ ebonus -= king_distance(Us, blockSq + Up) * rr;
// If the pawn is free to advance, then increase the bonus
if (pos.empty(blockSq))
@@ -693,7 +696,7 @@ namespace {
// If there aren't any enemy attacks, assign a big bonus. Otherwise
// assign a smaller bonus if the block square isn't attacked.
- int k = !unsafeSquares ? 18 : !(unsafeSquares & blockSq) ? 8 : 0;
+ int k = !unsafeSquares ? 20 : !(unsafeSquares & blockSq) ? 9 : 0; //Fauzi Akram
// If the path to the queen is fully defended, assign a big bonus.
// Otherwise assign a smaller bonus if the block square is defended.
@@ -903,7 +906,7 @@ namespace {
Trace::add(TOTAL, score);
}
- return (pos.side_to_move() == WHITE ? v : -v) + Eval::Tempo; // Side to move point of view
+ return pos.side_to_move() == WHITE ? v : -v; // Side to move point of view
}
} // namespace
@@ -915,7 +918,7 @@ Score Eval::Contempt = SCORE_ZERO;
Value Eval::evaluate(const Position& pos)
{
- return Evaluation<>(pos).value();
+ return Evaluation<>(pos).value() + Eval::Tempo;
}
/// trace() is like evaluate(), but instead of returning a value, it returns
@@ -926,7 +929,7 @@ std::string Eval::trace(const Position& pos) {
std::memset(scores, 0, sizeof(scores));
- Value v = Evaluation(pos).value();
+ Value v = Evaluation(pos).value() + Eval::Tempo;
v = pos.side_to_move() == WHITE ? v : -v; // White's point of view
std::stringstream ss;
diff --git a/Engines/Linux64/mcbrain/src/evaluate.h b/Engines/Linux64/mcbrain/src/evaluate.h
index 3772c3f..8d388fa 100644
--- a/Engines/Linux64/mcbrain/src/evaluate.h
+++ b/Engines/Linux64/mcbrain/src/evaluate.h
@@ -30,7 +30,7 @@ class Position;
namespace Eval {
-const Value Tempo = Value(24); // Must be visible to search
+const Value Tempo = Value(20); // Must be visible to search
extern Score Contempt;
diff --git a/Engines/Linux64/mcbrain/src/main.cpp b/Engines/Linux64/mcbrain/src/main.cpp
index a7beca8..637dc3b 100644
--- a/Engines/Linux64/mcbrain/src/main.cpp
+++ b/Engines/Linux64/mcbrain/src/main.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -48,11 +48,11 @@ int main(int argc, char* argv[]) {
polybook.init(Options["BookFile"]);
Tablebases::init(Options["SyzygyPath"]);
TT.resize(Options["Hash"]);
- Threads.init(Options["Threads"]);
+ Threads.set(Options["Threads"]);
Search::clear(); // After threads are up
UCI::loop(argc, argv);
- Threads.exit();
+ Threads.set(0);
return 0;
}
diff --git a/Engines/Linux64/mcbrain/src/material.cpp b/Engines/Linux64/mcbrain/src/material.cpp
index a58d52f..2b28837 100644
--- a/Engines/Linux64/mcbrain/src/material.cpp
+++ b/Engines/Linux64/mcbrain/src/material.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -40,7 +40,7 @@ namespace {
{ 32, 255, -3 }, // Knight OUR PIECES
{ 0, 104, 4, 0 }, // Bishop
{ -26, -2, 47, 105, -149 }, // Rook
- {-185, 24, 122, 137, -134, 0 } // Queen
+ {-189, 24, 117, 133, -134, -10 } // Queen
};
const int QuadraticTheirs[][PIECE_TYPE_NB] = {
@@ -51,18 +51,7 @@ namespace {
{ 9, 63, 0 }, // Knight OUR PIECES
{ 59, 65, 42, 0 }, // Bishop
{ 46, 39, 24, -24, 0 }, // Rook
- { 101, 100, -37, 141, 268, 0 } // Queen
- };
-
- // PawnSet[pawn count] contains a bonus/malus indexed by number of pawns
- const int PawnSet[] = {
- 24, -32, 107, -51, 117, -9, -126, -21, 31
- };
-
- // QueenMinorsImbalance[opp_minor_count] is applied when only one side has a queen.
- // It contains a bonus/malus for the side with the queen.
- const int QueenMinorsImbalance[13] = {
- 31, -8, -15, -25, -5
+ { 97, 100, -42, 137, 268, 0 } // Queen
};
// Endgame evaluation and scaling functions are accessed directly and not through
@@ -101,7 +90,7 @@ namespace {
const Color Them = (Us == WHITE ? BLACK : WHITE);
- int bonus = PawnSet[pieceCount[Us][PAWN]];
+ int bonus = 0;
// Second-degree polynomial material imbalance, by Tord Romstad
for (int pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1)
@@ -118,10 +107,6 @@ namespace {
bonus += pieceCount[Us][pt1] * v;
}
- // Special handling of Queen vs. Minors
- if (pieceCount[Us][QUEEN] == 1 && pieceCount[Them][QUEEN] == 0)
- bonus += QueenMinorsImbalance[pieceCount[Them][KNIGHT] + pieceCount[Them][BISHOP]];
-
return bonus;
}
diff --git a/Engines/Linux64/mcbrain/src/material.h b/Engines/Linux64/mcbrain/src/material.h
index b412bb1..95d6c84 100644
--- a/Engines/Linux64/mcbrain/src/material.h
+++ b/Engines/Linux64/mcbrain/src/material.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/misc.cpp b/Engines/Linux64/mcbrain/src/misc.cpp
index 2d48cb0..a14d9c4 100644
--- a/Engines/Linux64/mcbrain/src/misc.cpp
+++ b/Engines/Linux64/mcbrain/src/misc.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -52,7 +52,7 @@ namespace {
/// Version number. If Version is left empty, then compile date in the format
/// DD-MM-YY and show in engine_info.
-const string Version = "v4.0";
+const string Version = "9";
/// 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
@@ -123,7 +123,7 @@ const string engine_info(bool to_uci) {
string month, day, year;
stringstream ss, date(__DATE__); // From compiler, format is "Sep 21 2008"
- ss << "SF-McBrain " << Version << setfill('0');
+ ss << "McBrain " << Version << setfill('0');
if (Version.empty())
{
@@ -134,7 +134,7 @@ const string engine_info(bool to_uci) {
ss << (Is64Bit ? " 64" : "")
<< (HasPext ? " BMI2" : (HasPopCnt ? " POPCNT" : ""))
<< (to_uci ? "\nid author ": " by ")
- << "M. Byrne and others (C) 2017";
+ << "M. Byrne, Stockfish authors and others";
return ss.str();
}
@@ -294,14 +294,6 @@ int get_group(size_t idx) {
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);
diff --git a/Engines/Linux64/mcbrain/src/misc.h b/Engines/Linux64/mcbrain/src/misc.h
index f907c96..98b5202 100644
--- a/Engines/Linux64/mcbrain/src/misc.h
+++ b/Engines/Linux64/mcbrain/src/misc.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/movegen.cpp b/Engines/Linux64/mcbrain/src/movegen.cpp
index e75ccbb..d06bc86 100644
--- a/Engines/Linux64/mcbrain/src/movegen.cpp
+++ b/Engines/Linux64/mcbrain/src/movegen.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/movegen.h b/Engines/Linux64/mcbrain/src/movegen.h
index 1a02a2a..666e4ef 100644
--- a/Engines/Linux64/mcbrain/src/movegen.h
+++ b/Engines/Linux64/mcbrain/src/movegen.h
@@ -46,7 +46,7 @@ struct ExtMove {
// Inhibit unwanted implicit conversions to Move
// with an ambiguity that yields to a compile error.
- operator float() const;
+ operator float() const = delete;
};
inline bool operator<(const ExtMove& f, const ExtMove& s) {
diff --git a/Engines/Linux64/mcbrain/src/movepick.cpp b/Engines/Linux64/mcbrain/src/movepick.cpp
index ef169ff..f62ca2b 100644
--- a/Engines/Linux64/mcbrain/src/movepick.cpp
+++ b/Engines/Linux64/mcbrain/src/movepick.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,12 +26,11 @@
namespace {
enum Stages {
- MAIN_SEARCH, CAPTURES_INIT, CAPTURE_KILLERS, 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
+ MAIN_SEARCH, CAPTURES_INIT, GOOD_CAPTURES, KILLERS, COUNTERMOVE, QUIET_INIT, QUIET, BAD_CAPTURES,
+ EVASION, EVASIONS_INIT, ALL_EVASIONS,
+ PROBCUT, PROBCUT_INIT, PROBCUT_CAPTURES,
+ QSEARCH, QCAPTURES_INIT, QCAPTURES, QCHECKS,
+ QSEARCH_RECAPTURES, QRECAPTURES
};
// partial_insertion_sort() sorts moves in descending order up to and including
@@ -69,10 +68,10 @@ namespace {
/// MovePicker constructor for the main search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh,
- const CapturePieceToHistory* cph, const PieceToHistory** ch, Move cm,
- Move* killers_p) :
- pos(p), mainHistory(mh), captureHistory(cph), contHistory(ch), countermove(cm),
- killers{killers_p[0], killers_p[1], killers_p[2], killers_p[3]}, depth(d){
+ const CapturePieceToHistory* cph, const PieceToHistory** ch, Move cm, Move* killers_p)
+ : pos(p), mainHistory(mh), captureHistory(cph), contHistory(ch), countermove(cm),
+ killers{killers_p[0], killers_p[1]}, depth(d){
+
assert(d > DEPTH_ZERO);
stage = pos.checkers() ? EVASION : MAIN_SEARCH;
@@ -82,18 +81,15 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHist
/// MovePicker constructor for quiescence search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, const CapturePieceToHistory* cph, Square s)
- : pos(p), mainHistory(mh), captureHistory(cph) {
+ : pos(p), mainHistory(mh), captureHistory(cph), depth(d) {
assert(d <= DEPTH_ZERO);
if (pos.checkers())
stage = EVASION;
- else if (d > DEPTH_QS_NO_CHECKS)
- stage = QSEARCH_WITH_CHECKS;
-
else if (d > DEPTH_QS_RECAPTURES)
- stage = QSEARCH_NO_CHECKS;
+ stage = QSEARCH;
else
{
@@ -162,8 +158,7 @@ Move MovePicker::next_move(bool skipQuiets) {
switch (stage) {
- case MAIN_SEARCH: case EVASION: case QSEARCH_WITH_CHECKS:
- case QSEARCH_NO_CHECKS: case PROBCUT:
+ case MAIN_SEARCH: case EVASION: case QSEARCH: case PROBCUT:
++stage;
return ttMove;
@@ -172,34 +167,16 @@ Move MovePicker::next_move(bool skipQuiets) {
endMoves = generate(pos, cur);
score();
++stage;
- move = killers[2]; // First capture killer move
- if( move != MOVE_NONE
- && move != ttMove
- && pos.pseudo_legal(move)
- && pos.capture_or_promotion(move))
- return move;
/* fallthrough */
-
- case CAPTURE_KILLERS:
- ++stage;
- move = killers[3]; // Second capture killer move
- if( move != MOVE_NONE
- && move != ttMove
- && pos.pseudo_legal(move)
- && pos.capture_or_promotion(move))
- return move;
- /* fallthrough */
case GOOD_CAPTURES:
while (cur < endMoves)
{
move = pick_best(cur++, endMoves);
- if ( move != ttMove
- && move != killers[2]
- && move != killers[3])
- {
- if (pos.see_ge(move, Value(-55 * (cur-1)->value / 1024)))
- return move;
+ if (move != ttMove)
+ {
+ if (pos.see_ge(move, Value(-55 * (cur-1)->value / 1024)))
+ return move;
// Losing capture, move it to the beginning of the array
*endBadCaptures++ = move;
@@ -299,21 +276,21 @@ Move MovePicker::next_move(bool skipQuiets) {
}
break;
- case QCAPTURES_1_INIT: case QCAPTURES_2_INIT:
+ case QCAPTURES_INIT:
cur = moves;
endMoves = generate(pos, cur);
score();
++stage;
/* fallthrough */
- case QCAPTURES_1: case QCAPTURES_2:
+ case QCAPTURES:
while (cur < endMoves)
{
move = pick_best(cur++, endMoves);
if (move != ttMove)
return move;
}
- if (stage == QCAPTURES_2)
+ if (depth <= DEPTH_QS_NO_CHECKS)
break;
cur = moves;
endMoves = generate(pos, cur);
@@ -332,14 +309,13 @@ Move MovePicker::next_move(bool skipQuiets) {
case QSEARCH_RECAPTURES:
cur = moves;
endMoves = generate(pos, cur);
- score();
++stage;
/* fallthrough */
case QRECAPTURES:
while (cur < endMoves)
{
- move = pick_best(cur++, endMoves);
+ move = *cur++;
if (to_sq(move) == recaptureSquare)
return move;
}
diff --git a/Engines/Linux64/mcbrain/src/movepick.h b/Engines/Linux64/mcbrain/src/movepick.h
index c651aaf..26e2a14 100644
--- a/Engines/Linux64/mcbrain/src/movepick.h
+++ b/Engines/Linux64/mcbrain/src/movepick.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/pawns.cpp b/Engines/Linux64/mcbrain/src/pawns.cpp
index d9e789d..3e5c2ed 100644
--- a/Engines/Linux64/mcbrain/src/pawns.cpp
+++ b/Engines/Linux64/mcbrain/src/pawns.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -44,23 +44,17 @@ namespace {
// Doubled pawn penalty
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)
- };
-
// Weakness of our pawn shelter in front of the king by [isKingFile][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[][int(FILE_NB) / 2][RANK_NB] = {
- { { V( 98), V(20), V(11), V(42), V( 83), V( 84), V(101) }, // Not On King file
- { V(103), V( 8), V(33), V(86), V( 87), V(105), V(113) },
- { V(100), V( 2), V(65), V(95), V( 59), V( 89), V(115) },
- { V( 72), V( 6), V(52), V(74), V( 83), V( 84), V(112) } },
- { { V(105), V(19), V( 3), V(27), V( 85), V( 93), V( 84) }, // On King file
- { V(121), V( 7), V(33), V(95), V(112), V( 86), V( 72) },
- { V(121), V(26), V(65), V(90), V( 65), V( 76), V(117) },
- { V( 79), V( 0), V(45), V(65), V( 94), V( 92), V(105) } }
+ { { V( 97), V(17), V( 9), V(44), V( 84), V( 87), V( 99) }, // Not On King file
+ { V(106), V( 6), V(33), V(86), V( 87), V(104), V(112) },
+ { V(101), V( 2), V(65), V(98), V( 58), V( 89), V(115) },
+ { V( 73), V( 7), V(54), V(73), V( 84), V( 83), V(111) } },
+ { { V(104), V(20), V( 6), V(27), V( 86), V( 93), V( 82) }, // On King file
+ { V(123), V( 9), V(34), V(96), V(112), V( 88), V( 75) },
+ { V(120), V(25), V(65), V(91), V( 66), V( 78), V(117) },
+ { V( 81), V( 2), V(47), V(63), V( 94), V( 93), V(104) } }
};
// Danger of enemy pawns moving toward our king by [type][distance from edge][rank].
@@ -185,9 +179,6 @@ namespace {
if (doubled && !supported)
score -= Doubled;
-
- if (lever)
- score += Lever[relative_rank(Us, s)];
}
return score;
diff --git a/Engines/Linux64/mcbrain/src/pawns.h b/Engines/Linux64/mcbrain/src/pawns.h
index 586a056..e834e18 100644
--- a/Engines/Linux64/mcbrain/src/pawns.h
+++ b/Engines/Linux64/mcbrain/src/pawns.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-218 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/polybook.cpp b/Engines/Linux64/mcbrain/src/polybook.cpp
index aebc91b..9aaacb4 100644
--- a/Engines/Linux64/mcbrain/src/polybook.cpp
+++ b/Engines/Linux64/mcbrain/src/polybook.cpp
@@ -1,3 +1,24 @@
+/*
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 .
+ */
+// polybook.cpp was written by Thomas Ziproth
/*
BrainFish, a UCI chess playing engine derived from Stockfish
Copyright (C) 2016-2017 Thomas Zipproth
diff --git a/Engines/Linux64/mcbrain/src/polybook.h b/Engines/Linux64/mcbrain/src/polybook.h
index 2e79b60..8696eda 100644
--- a/Engines/Linux64/mcbrain/src/polybook.h
+++ b/Engines/Linux64/mcbrain/src/polybook.h
@@ -1,6 +1,28 @@
/*
+ McBrain, a UCI chess playing engine derived from Stockfish and Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+
+ McBrain 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.
+
+ McBrain 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 .
+ */
+//polybook.h was wriiten by Thomas Zipproth
+/*
+polybook.h was written by Thomas Zipproth
BrainFish, a UCI chess playing engine derived from Stockfish
-Copyright (C) 2016-2017 Thomas Zipproth
+Copyright (C) 2016-2018 Thomas Zipproth
BrainFish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -88,4 +110,4 @@ class PolyBook
extern PolyBook polybook;
-#endif // #ifndef POLYBOOK_H_INCLUDED
\ No newline at end of file
+#endif // #ifndef POLYBOOK_H_INCLUDED
diff --git a/Engines/Linux64/mcbrain/src/position.cpp b/Engines/Linux64/mcbrain/src/position.cpp
index 253d4b3..acef66b 100644
--- a/Engines/Linux64/mcbrain/src/position.cpp
+++ b/Engines/Linux64/mcbrain/src/position.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/position.h b/Engines/Linux64/mcbrain/src/position.h
index 17c559e..c809549 100644
--- a/Engines/Linux64/mcbrain/src/position.h
+++ b/Engines/Linux64/mcbrain/src/position.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/psqt.cpp b/Engines/Linux64/mcbrain/src/psqt.cpp
index 6f7d210..55a2e72 100644
--- a/Engines/Linux64/mcbrain/src/psqt.cpp
+++ b/Engines/Linux64/mcbrain/src/psqt.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -39,13 +39,13 @@ namespace PSQT {
const Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
{ },
{ // Pawn
- { S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0) },
- { S(-11, 7), S( 6,-4), S( 7, 8), S( 3,-2) },
- { S(-18,-4), S( -2,-5), S( 19, 5), S(24, 4) },
- { S(-17, 3), S( -9, 3), S( 20,-8), S(35,-3) },
- { S( -6, 7), S( 5, 8), S( 3, 7), S(21, 6) },
- { S( -6, 8), S( -8, 9), S( -6, 8), S(-2, 7) },
- { S( -4, 9), S( 20, 10), S( -8, 9), S(-4, 8) }
+ { S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0) },
+ { S(-11, 7), S( 6,-4), S( 7, 8), S( 3,-2) },
+ { S(-18,-4), S( -2,-5), S( 19, 5), S(24, 4) },
+ { S(-17, 3), S( -9, 3), S( 20,-8), S(35,-3) },
+ { S( -6, 8), S( 5, 9), S( 3, 7), S(21,-6) },
+ { S( -6, 8), S( -8,-5), S( -6, 2), S(-2, 4) },
+ { S( -4, 3), S( 20,-9), S( -8, 1), S(-4,18) }
},
{ // Knight
{ S(-161,-105), S(-96,-82), S(-80,-46), S(-73,-14) },
diff --git a/Engines/Linux64/mcbrain/src/search.cpp b/Engines/Linux64/mcbrain/src/search.cpp
index 7935441..92753c0 100644
--- a/Engines/Linux64/mcbrain/src/search.cpp
+++ b/Engines/Linux64/mcbrain/src/search.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,16 +23,16 @@
#include
#include
#include // For std::memset
-#include //for sleep
+#include //for sleep //MichaelB7
#include
#include
-#include
+#include // ELO MichaelB7
#include "evaluate.h"
#include "misc.h"
#include "movegen.h"
#include "movepick.h"
-#include "polybook.h"
+#include "polybook.h" // Cerebellum
#include "position.h"
#include "search.h"
#include "timeman.h"
@@ -71,16 +71,16 @@ namespace {
const int skipPhase[] = { 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7 };
// Razoring and futility margin based on depth
- // razor_margin[0] is unused as long as depth >= ONE_PLY in search
- const int razor_margin[] = { 0, 570, 603, 554 };
- Value futility_margin(Depth d) { return Value(150 * d / ONE_PLY); }
+ const int razor_margin = 600;
+ //Value futility_margin(Depth d) { return Value(150 * d / ONE_PLY); }
+ Value futility_margin(Depth d) { return Value(16 * d^2 / ONE_PLY + 200 * d / ONE_PLY);} // idea from JD Watson, code modfied by MichaelB7
// Futility and reductions lookup tables, initialized at startup
int FutilityMoveCounts[2][16]; // [improving][depth]
- int Reductions[2][2][128][96]; // [pv][improving][depth][moveNumber]
+ int Reductions[2][2][128][96]; // [pv][improving][depth][moveNumber] //MichaelB7
template Depth reduction(bool i, Depth d, int mn) {
- return Reductions[PvNode][i][std::min(d / ONE_PLY, 127)][std::min(mn, 95)] * ONE_PLY;
+ return Reductions[PvNode][i][std::min(d / ONE_PLY, 127)][std::min(mn, 95)] * ONE_PLY; //MichaelB7
}
// History and stats update bonus, based on depth
@@ -102,7 +102,7 @@ namespace {
int tactical;
- bool bruteForce, limitStrength, noNULL;
+ bool bookEnabled, bruteForce, limitStrength, noNULL;
template
Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode, bool skipEarlyPruning);
@@ -152,10 +152,10 @@ namespace {
void Search::init() {
for (int imp = 0; imp <= 1; ++imp)
- for (int d = 1; d < 128; ++d)
- for (int mc = 1; mc < 96; ++mc)
+ for (int d = 1; d < 128; ++d) // MichaelB7
+ for (int mc = 1; mc < 96; ++mc) // MichaelB7
{
- double r = log(d) * log(mc) / 1.89;
+ double r = log(d) * log(mc) / 1.89 ;
Reductions[NonPV][imp][d][mc] = int(std::round(r));
Reductions[PV][imp][d][mc] = std::max(Reductions[NonPV][imp][d][mc] - 1, 0);
@@ -181,13 +181,7 @@ void Search::clear() {
Time.availableNodes = 0;
TT.clear();
-
- for (Thread* th : Threads)
- th->clear();
-
- Threads.main()->callsCnt = 0;
- Threads.main()->previousScore = VALUE_INFINITE;
- Threads.main()->previousTimeReduction = 1;
+ Threads.clear();
}
@@ -207,6 +201,7 @@ void MainThread::search() {
limitStrength = Options["UCI_LimitStrength"];
noNULL = Options["No_Null_Moves"];
tactical = Options["Tactical"];
+ bookEnabled = Options["Book_Enabled"];
Color us = rootPos.side_to_move();
Time.init(Limits, us, rootPos.game_ply());
@@ -214,6 +209,14 @@ void MainThread::search() {
int contempt = Options["Contempt"] * PawnValueEg / 100; // From centipawns
+ // In analysis mode, adjust contempt in accordance with user preference
+ if (Limits.infinite || Options["UCI_AnalyseMode"])
+ contempt = Options["Analysis Contempt"] == "Off" ? 0
+ : Options["Analysis Contempt"] == "White" && us == BLACK ? -contempt
+ : Options["Analysis Contempt"] == "Black" && us == WHITE ? -contempt
+ : contempt; // contempt remains with the side to move
+
+ // Eval::Contempt is from white's point of view
Eval::Contempt = (us == WHITE ? make_score(contempt, contempt / 2)
: -make_score(contempt, contempt / 2));
@@ -231,7 +234,7 @@ void MainThread::search() {
if (!Limits.infinite && !Limits.mate)
bookMove = polybook.probe(rootPos);
- if (bookMove && std::count(rootMoves.begin(), rootMoves.end(), bookMove))
+ if (bookEnabled && bookMove && std::count(rootMoves.begin(), rootMoves.end(), bookMove))
{
for (Thread* th : Threads)
std::swap(th->rootMoves[0], *std::find(th->rootMoves.begin(), th->rootMoves.end(), bookMove));
@@ -240,9 +243,7 @@ void MainThread::search() {
{
if (limitStrength)
{
-
int uci_elo = (Options["UCI_ELO"]);
-
std::mt19937 gen(now());
std::uniform_int_distribution dis(-33, 33);
int rand = dis(gen);
@@ -346,10 +347,10 @@ void Thread::search() {
mainThread->bestMoveChanges = 0;
}
- size_t multiPV = Options["MultiPV"];
+ multiPV = Options["MultiPV"];
Skill skill(Options["Skill Level"]);
if (tactical) multiPV = pow(2, tactical);
- if (::pv_is_draw(rootPos)) multiPV = 8 ;
+
// When playing with strength handicap enable MultiPV search that we will
// use behind the scenes to retrieve a set of possible moves.
@@ -357,19 +358,25 @@ void Thread::search() {
multiPV = std::max(multiPV, (size_t)4);
multiPV = std::min(multiPV, rootMoves.size());
+
+ // UCI options specify 256 as the max MultiPv option
+ int consecutiveEarlyExits[257] = {0};
// Iterative deepening loop until requested to stop or the target depth is reached
while ( (rootDepth += ONE_PLY) < DEPTH_MAX
&& !Threads.stop
&& !(Limits.depth && mainThread && rootDepth / ONE_PLY > Limits.depth))
{
- // Distribute search depths across the threads
- if (idx)
- {
- int i = (idx - 1) % 20;
- if (((rootDepth / ONE_PLY + rootPos.game_ply() + skipPhase[i]) / skipSize[i]) % 2)
- continue;
- }
+ // Distribute search depths across the threads
+ if (idx)
+ {
+ int i = (idx - 1) % 20;
+ if (idx == Threads.size() - 1 && !ss->excludedMove && rootDepth < 14 * ONE_PLY && rootMoves.size() > 1 && rootPos.see_ge(rootMoves[0].pv[0], VALUE_ZERO + 1))
+ ss->excludedMove = rootMoves[0].pv[0]; //lazy_or_stubborn by pb00068
+ else
+ if (((rootDepth / ONE_PLY + rootPos.game_ply() + skipPhase[i]) / skipSize[i]) % 2)
+ continue;
+ }
// Age out PV variability metric
if (mainThread)
@@ -409,7 +416,8 @@ void Thread::search() {
// and we want to keep the same order for all the moves except the
// new PV that goes to the front. Note that in case of MultiPV
// search the already searched PV lines are preserved.
- std::stable_sort(rootMoves.begin() + PVIdx, rootMoves.end());
+ if (PVIdx + 1 == multiPV)
+ std::stable_sort(rootMoves.begin() + PVIdx, rootMoves.end());
// If search has been stopped, we break immediately. Sorting and
// writing PV back to TT is safe because RootMoves is still
@@ -438,15 +446,20 @@ void Thread::search() {
Threads.stopOnPonderhit = false;
}
}
- else if (bestValue >= beta)
- beta = std::min(bestValue + delta2, VALUE_INFINITE);
+
+ else if ( bestValue >= beta)
+ beta = std::min(bestValue + delta2, VALUE_INFINITE); //Ivan Ivec
+
else
+ {
+ delta1 += delta1 / 4 + 5; //Ivan Ivec
+ delta2 += delta2 / 4 + 5; //Ivan Ivec
+
+ assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
+
+ consecutiveEarlyExits[PVIdx] = (bestValue >= beta) ? consecutiveEarlyExits[PVIdx] + 1 : 0;
break;
-
- delta1 += delta1 / 4 + 5;
- delta2 += delta2 / 4 + 5;
-
- assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
+ }
}
// Sort the PV lines searched so far and update the GUI
@@ -473,14 +486,14 @@ void Thread::search() {
if (!mainThread)
continue;
-
- if (Options["FastPlay"])
- {
- if ( Time.elapsed() > Time.optimum() / 256
- && ( abs(bestValue) > 12300 || abs(bestValue) >= VALUE_MATE_IN_MAX_PLY ))
- Threads.stop = true;
- }
-
+//BEGINS MichaelB7
+ if (Options["FastPlay"])
+ {
+ if ( Time.elapsed() > Time.optimum() / 256
+ && ( abs(bestValue) > 12300 || abs(bestValue) >= VALUE_MATE_IN_MAX_PLY ))
+ Threads.stop = true;
+ }
+//ENDS MichaelB7
// If skill level is enabled and time is up, pick a sub-optimal best move
if (skill.enabled() && skill.time_to_pick(rootDepth))
skill.pick_best(multiPV);
@@ -618,7 +631,7 @@ namespace {
// search to overwrite a previous full search TT value, so we use a different
// position key in case of an excluded move.
excludedMove = ss->excludedMove;
- posKey = pos.key() ^ Key(excludedMove);
+ posKey = pos.key() ^ Key(excludedMove << 16); // isn't a very good hash
tte = TT.probe(posKey, ttHit);
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
ttMove = rootNode ? thisThread->rootMoves[thisThread->PVIdx].pv[0]
@@ -739,18 +752,18 @@ namespace {
ss->staticEval, TT.generation());
}
- if (skipEarlyPruning || !pos.non_pawn_material())
+ if (skipEarlyPruning || !pos.non_pawn_material(pos.side_to_move()))
goto moves_loop;
// Step 6. Razoring (skipped when in check)
if ( !bruteForce && !PvNode
&& depth < 4 * ONE_PLY
- && eval + razor_margin[depth / ONE_PLY] <= alpha)
+ && eval + razor_margin <= alpha)
{
if (depth <= ONE_PLY)
return qsearch(pos, ss, alpha, alpha+1);
- Value ralpha = alpha - razor_margin[depth / ONE_PLY];
+ Value ralpha = alpha - razor_margin;
Value v = qsearch(pos, ss, ralpha, ralpha+1);
if (v <= ralpha)
return v;
@@ -760,18 +773,17 @@ namespace {
if ( !bruteForce && !rootNode
&& depth < 7 * ONE_PLY
&& eval - futility_margin(depth) >= beta
- && eval < VALUE_KNOWN_WIN ) // Do not return unproven wins
+ && eval < VALUE_KNOWN_WIN) // Do not return unproven wins
return eval;
// Step 8. Null move search with verification search (is omitted in PV nodes)
- if ( !noNULL
- && !PvNode
+ if ( !PvNode
&& eval >= beta
- && (ss->staticEval >= beta - int(320 * log(depth / ONE_PLY)) + 500)
- && thisThread->selDepth + 3 > thisThread->rootDepth / ONE_PLY
- && (ss->ply >= thisThread->nmp_ply || ss->ply % 2 == thisThread->pair)
- && !(MoveList(pos).size() < 4)
- )
+ && ss->staticEval >= beta - int(320 * log(depth / ONE_PLY)) + 500 //Corchess/IIvec
+ && (((ss-2)->currentMove != MOVE_NULL) || (ss-2)->staticEval >= beta - 36 * depth / ONE_PLY + 225)
+ && thisThread->selDepth + 3 > thisThread->rootDepth / ONE_PLY // idea from Corchess/IIvec
+ && (ss->ply >= thisThread->nmp_ply || ss->ply % 2 != thisThread->pair)
+ && !(MoveList(pos).size() < 4)) //MichaelB7
{
assert(eval - beta >= 0);
@@ -874,7 +886,7 @@ namespace {
&& tte->depth() >= depth - 3 * ONE_PLY;
skipQuiets = false;
ttCapture = false;
- goodCap = false;
+ goodCap = false;
pvExact = PvNode && ttHit && tte->bound() == BOUND_EXACT;
// Step 11. Loop through moves
@@ -886,12 +898,20 @@ namespace {
if (move == excludedMove)
continue;
- // At root obey the "searchmoves" option and skip moves not listed in Root
- // Move List. As a consequence any illegal move is also skipped. In MultiPV
- // mode we also skip PV moves which have been already searched.
- if (rootNode && !std::count(thisThread->rootMoves.begin() + thisThread->PVIdx,
- thisThread->rootMoves.end(), move))
- continue;
+ if (rootNode)
+ {
+ // At root obey the "searchmoves" option and skip moves not listed in Root
+ // Move List. As a consequence any illegal move is also skipped.
+ if (!std::count(thisThread->rootMoves.begin() + thisThread->PVIdx,
+ thisThread->rootMoves.end(), move))
+ continue;
+
+ // In MultiPV mode we not only skip PV moves which have already been searched,
+ // but also any other move except we have reached the last PV line.
+ if ( thisThread->PVIdx + 1 < thisThread->multiPV
+ && move != ttMove)
+ continue;
+ }
ss->moveCount = ++moveCount;
@@ -933,31 +953,22 @@ namespace {
ss->excludedMove = MOVE_NONE;
if (value < rBeta)
- extension = ONE_PLY;
+ extension = ONE_PLY;
}
- else if ( givesCheck
- && !moveCountPruning
- && (pos.see_ge(move) || PvNode ))
- extension = ONE_PLY;
-
- else if ( PvNode
- && depth < 13 * ONE_PLY
- && pos.advanced_pawn_push(move)
- && !moveCountPruning)
- extension = ONE_PLY;
+ else if (!moveCountPruning)
+ {
+ if ( givesCheck
+ && (pos.see_ge(move) || PvNode ))
+ extension = ONE_PLY;
+
+ else if ( PvNode
+ && depth < 13 * ONE_PLY
+ && ( givesCheck || pos.advanced_pawn_push(move)
+ || ( ss->forcingTree && (ss)->newDepth - depth > 1)))
+ extension = ONE_PLY;
+ }
- else if ( PvNode
- && depth < 13 * ONE_PLY
- && ss->forcingTree && (ss)->newDepth - depth > 1
- && !moveCountPruning)
- extension = ONE_PLY;
- else if ( depth % 5 == 0
- && !pos.non_pawn_material()
- && type_of(movedPiece) == KING
- && !moveCountPruning)
- extension = ONE_PLY;
-
// Calculate new depth for this move
newDepth = depth - ONE_PLY + extension;
@@ -989,7 +1000,7 @@ namespace {
// Futility pruning: parent node
if ( lmrDepth < 7
&& !inCheck
- && ss->staticEval + 256 + 200 * lmrDepth <= alpha)
+ && ss->staticEval + 256 + futility_margin(lmrDepth * ONE_PLY) <= alpha)// idea from JD Watson, modifed by MichaelB7
continue;
// Prune moves with negative SEE
@@ -1031,7 +1042,7 @@ namespace {
if ( !bruteForce && depth >= 3 * ONE_PLY
&& moveCount > 1
&& (!captureOrPromotion || moveCountPruning)
- && (ss+2)->killers[0] != move
+ && (ss+2)->killers[0] != move
&& (ss+2)->killers[1] != move)
{
Depth r = reduction(improving, depth, moveCount);
@@ -1041,7 +1052,7 @@ namespace {
else
{
// Decrease reduction if opponent's move count is high
- if ((ss-1)->moveCount > 15)
+ if ((ss-1)->moveCount > 13 )
r -= ONE_PLY;
// Decrease reduction for exact PV nodes
@@ -1049,7 +1060,7 @@ namespace {
r -= ONE_PLY;
// Increase reduction if ttMove is a capture
- if (ttCapture)
+ if (ttCapture || (!pvExact && depth > 13 * ONE_PLY))
r += ONE_PLY;
else if(goodCap && !inCheck && !givesCheck)
r += ONE_PLY;
@@ -1068,7 +1079,7 @@ namespace {
ss->statScore = thisThread->mainHistory[~pos.side_to_move()][from_to(move)]
+ (*contHist[0])[movedPiece][to_sq(move)]
+ (*contHist[1])[movedPiece][to_sq(move)]
- + (*contHist[3])[movedPiece][to_sq(move)]
+ + (*contHist[3])[movedPiece][to_sq(move)]
- 4000;
// Decrease/increase reduction by comparing opponent's stat score
@@ -1388,7 +1399,6 @@ namespace {
// Don't search moves with negative SEE values
if ( (!InCheck || evasionPrunable)
- && type_of(move) != PROMOTION
&& !pos.see_ge(move))
continue;
@@ -1643,12 +1653,19 @@ namespace {
string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
std::stringstream ss;
+ int temp = 0;
int elapsed = Time.elapsed() + 1;
const RootMoves& rootMoves = pos.this_thread()->rootMoves;
size_t PVIdx = pos.this_thread()->PVIdx;
- size_t multiPV = std::min((size_t)Options["MultiPV"], rootMoves.size());
+ size_t multiPV = pos.this_thread()->multiPV;
uint64_t nodesSearched = Threads.nodes_searched();
uint64_t tbHits = Threads.tb_hits() + (TB::RootInTB ? rootMoves.size() : 0);
+
+ if (tactical)
+ {
+ temp = multiPV;
+ multiPV = 1;
+ }
for (size_t i = 0; i < multiPV; ++i)
{
@@ -1688,11 +1705,10 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
for (Move m : rootMoves[i].pv)
ss << " " << UCI::move(m, pos.is_chess960());
}
-
+ if (tactical) multiPV = temp;
return ss.str();
}
-
/// RootMove::extract_ponder_from_tt() is called in case we have no ponder move
/// before exiting the search, for instance, in case we stop the search during a
/// fail high at root. We try hard to have a ponder move to return to the GUI,
diff --git a/Engines/Linux64/mcbrain/src/search.h b/Engines/Linux64/mcbrain/src/search.h
index 90842f6..f1ac439 100644
--- a/Engines/Linux64/mcbrain/src/search.h
+++ b/Engines/Linux64/mcbrain/src/search.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -104,8 +104,7 @@ extern LimitsType Limits;
void init();
void clear();
-Value respect(const Position& pos, Color c);
-
+
} // namespace Search
#endif // #ifndef SEARCH_H_INCLUDED
diff --git a/Engines/Linux64/mcbrain/src/tbprobe.cpp b/Engines/Linux64/mcbrain/src/tbprobe.cpp
index d019f28..09e031c 100644
--- a/Engines/Linux64/mcbrain/src/tbprobe.cpp
+++ b/Engines/Linux64/mcbrain/src/tbprobe.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/tbprobe.h b/Engines/Linux64/mcbrain/src/tbprobe.h
index 7c0bbe7..97ec7b1 100644
--- a/Engines/Linux64/mcbrain/src/tbprobe.h
+++ b/Engines/Linux64/mcbrain/src/tbprobe.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/thread.cpp b/Engines/Linux64/mcbrain/src/thread.cpp
index 616b88f..47a21c1 100644
--- a/Engines/Linux64/mcbrain/src/thread.cpp
+++ b/Engines/Linux64/mcbrain/src/thread.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017*2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
#include "movegen.h"
#include "search.h"
#include "thread.h"
+#include "uci.h"
#include "tbprobe.h"
ThreadPool Threads; // Global object
@@ -36,7 +37,6 @@ ThreadPool Threads; // Global object
Thread::Thread(size_t n) : idx(n), stdThread(&Thread::idle_loop, this) {
wait_for_search_finished();
- clear(); // Zero-init histories (based on std::array)
}
@@ -93,7 +93,13 @@ void Thread::wait_for_search_finished() {
void Thread::idle_loop() {
- WinProcGroup::bindThisThread(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 (Options["Threads"] >= 8)
+ WinProcGroup::bindThisThread(idx);
while (true)
{
@@ -111,42 +117,40 @@ void Thread::idle_loop() {
}
}
+/// ThreadPool::set() creates/destroys threads to match the requested number.
+/// Created and launced threads wil go immediately to sleep in idle_loop.
+/// Upon resizing, threads are recreated to allow for binding if necessary.
-/// ThreadPool::init() creates and launches the threads that will go
-/// immediately to sleep in idle_loop. We cannot use the constructor because
-/// Threads is a static object and we need a fully initialized engine at
-/// this point due to allocation of Endgames in the Thread constructor.
-
-void ThreadPool::init(size_t requested) {
-
- push_back(new MainThread(0));
- set(requested);
-}
+void ThreadPool::set(size_t requested) {
+ if (size() > 0) { // destroy any existing thread(s)
+ main()->wait_for_search_finished();
-/// ThreadPool::exit() terminates threads before the program exits. Cannot be
-/// done in the destructor because threads must be terminated before deleting
-/// any static object, so before main() returns.
+ while (size() > 0)
+ delete back(), pop_back();
+ }
-void ThreadPool::exit() {
+ if (requested > 0) { // create new thread(s)
+ push_back(new MainThread(0));
- main()->wait_for_search_finished();
- set(0);
+ while (size() < requested)
+ push_back(new Thread(size()));
+ clear();
+ }
}
+/// ThreadPool::clear() sets threadPool data to initial values.
-/// ThreadPool::set() creates/destroys threads to match the requested number
+void ThreadPool::clear() {
-void ThreadPool::set(size_t requested) {
+ for (Thread* th : *this)
+ th->clear();
- while (size() < requested)
- push_back(new Thread(size()));
-
- while (size() > requested)
- delete back(), pop_back();
+ main()->callsCnt = 0;
+ main()->previousScore = VALUE_INFINITE;
+ main()->previousTimeReduction = 1;
}
-
/// ThreadPool::start_thinking() wakes up main thread waiting in idle_loop() and
/// returns immediately. Main thread will wake up other threads and start the search.
@@ -182,7 +186,7 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states,
// is shared by threads but is accessed in read-only mode.
StateInfo tmp = setupStates->back();
- for (Thread* th : Threads)
+ for (Thread* th : *this)
{
th->nodes = th->tbHits = 0;
th->rootDepth = th->completedDepth = DEPTH_ZERO;
diff --git a/Engines/Linux64/mcbrain/src/thread.h b/Engines/Linux64/mcbrain/src/thread.h
index 87c5029..25a6511 100644
--- a/Engines/Linux64/mcbrain/src/thread.h
+++ b/Engines/Linux64/mcbrain/src/thread.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -61,8 +61,8 @@ class Thread {
Pawns::Table pawnsTable;
Material::Table materialTable;
Endgames endgames;
- size_t PVIdx;
- int selDepth, nmp_ply, pair;
+ size_t PVIdx, multiPV;
+ int selDepth, nmp_ply, pair;
std::atomic nodes, tbHits;
Position rootPos;
@@ -100,11 +100,19 @@ struct ThreadPool : public std::vector {
void init(size_t); // No constructor and destructor, threads rely on globals that should
void exit(); // be initialized and valid during the whole thread lifetime.
void start_thinking(Position&, StateListPtr&, const Search::LimitsType&, bool = false);
+ void clear();
void set(size_t);
MainThread* main() const { return static_cast(front()); }
uint64_t nodes_searched() const { return accumulate(&Thread::nodes); }
uint64_t tb_hits() const { return accumulate(&Thread::tbHits); }
+
+ Depth lowestDepth(){
+ Depth lowest = DEPTH_MAX;
+ for (Thread* th: *this)
+ lowest = std::min(lowest, th->rootDepth);
+ return lowest;
+ }
std::atomic_bool stop, ponder, stopOnPonderhit;
diff --git a/Engines/Linux64/mcbrain/src/thread_win32.h b/Engines/Linux64/mcbrain/src/thread_win32.h
index ca737e9..d69e817 100644
--- a/Engines/Linux64/mcbrain/src/thread_win32.h
+++ b/Engines/Linux64/mcbrain/src/thread_win32.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/timeman.cpp b/Engines/Linux64/mcbrain/src/timeman.cpp
index 579921e..6a854c9 100644
--- a/Engines/Linux64/mcbrain/src/timeman.cpp
+++ b/Engines/Linux64/mcbrain/src/timeman.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,6 +20,8 @@
*/
#include
+#include
+#include
#include "search.h"
#include "timeman.h"
@@ -31,46 +33,41 @@ namespace {
enum TimeType { OptimumTime, MaxTime };
- int remaining(int myTime, int myInc, int moveOverhead, int movesToGo,
- int moveNum, bool ponder, TimeType type) {
+ const int MoveHorizon = 50; // Plan time management at most this many moves ahead
+ const double MaxRatio = 7.09; // When in trouble, we can step over reserved time with this ratio
+ const double StealRatio = 0.35; // However we must not steal time from remaining moves over this ratio
- if (myTime <= 0)
- return 0;
- double ratio; // Which ratio of myTime we are going to use
+ // move_importance() is a skew-logistic function based on naive statistical
+ // analysis of "how many games are still undecided after n half-moves". Game
+ // is considered "undecided" as long as neither side has >275cp advantage.
+ // Data was extracted from the CCRL game database with some simple filtering criteria.
- // Usage of increment follows quadratic distribution with the maximum at move 25
- double inc = myInc * std::max(55.0, 120 - 0.12 * (moveNum - 25) * (moveNum - 25));
+ double move_importance(int ply) {
- // In moves-to-go we distribute time according to a quadratic function with
- // the maximum around move 20 for 40 moves in y time case.
- if (movesToGo)
- {
- ratio = (type == OptimumTime ? 1.0 : 6.0) / std::min(50, movesToGo);
+ const double XScale = 7.64;
+ const double XShift = 58.4;
+ const double Skew = 0.183;
- if (moveNum <= 40)
- ratio *= 1.1 - 0.001 * (moveNum - 20) * (moveNum - 20);
- else
- ratio *= 1.5;
+ return pow((1 + exp((ply - XShift) / XScale)), -Skew) + DBL_MIN; // Ensure non-zero
+ }
+
+ template
+ int remaining(int myTime, int movesToGo, int ply, int slowMover) {
- if (movesToGo > 1)
- ratio = std::min(0.75, ratio);
+ const double TMaxRatio = (T == OptimumTime ? 1 : MaxRatio);
+ const double TStealRatio = (T == OptimumTime ? 0 : StealRatio);
- ratio *= 1 + inc / (myTime * 8.5);
- }
- // Otherwise we increase usage of remaining time as the game goes on
- else
- {
- double k = 1 + 20 * moveNum / (500.0 + moveNum);
- ratio = (type == OptimumTime ? 0.017 : 0.07) * (k + inc / myTime);
- }
+ double moveImportance = (move_importance(ply) * slowMover) / 100;
+ double otherMovesImportance = 0;
- int time = int(std::min(1.0, ratio) * std::max(0, myTime - moveOverhead));
+ for (int i = 1; i < movesToGo; ++i)
+ otherMovesImportance += move_importance(ply + 2 * i);
- if (type == OptimumTime && ponder)
- time = 5 * time / 4;
+ double ratio1 = (TMaxRatio * moveImportance) / (TMaxRatio * moveImportance + otherMovesImportance);
+ double ratio2 = (moveImportance + TStealRatio * otherMovesImportance) / (moveImportance + otherMovesImportance);
- return time;
+ return int(myTime * std::min(ratio1, ratio2)); // Intel C++ asks for an explicit cast
}
} // namespace
@@ -85,11 +82,12 @@ namespace {
/// inc > 0 && movestogo == 0 means: x basetime + z increment
/// inc > 0 && movestogo != 0 means: x moves in y minutes + z increment
-void TimeManagement::init(Search::LimitsType& limits, Color us, int ply)
-{
- int moveOverhead = Options["Move Overhead"];
- int npmsec = Options["nodestime"];
- bool ponder = Options["Ponder"];
+void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
+
+ int minThinkingTime = Options["Minimum Thinking Time"];
+ int moveOverhead = Options["Move Overhead"];
+ int slowMover = Options["Slow Mover"];
+ int npmsec = Options["nodestime"];
// If we have to play in 'nodes as time' mode, then convert from time
// to nodes, and use resulting values in time management formulas.
@@ -106,11 +104,30 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply)
limits.npmsec = npmsec;
}
- int moveNum = (ply + 1) / 2;
-
startTime = limits.startTime;
- optimumTime = remaining(limits.time[us], limits.inc[us], moveOverhead,
- limits.movestogo, moveNum, ponder, OptimumTime);
- maximumTime = remaining(limits.time[us], limits.inc[us], moveOverhead,
- limits.movestogo, moveNum, ponder, MaxTime);
+ optimumTime = maximumTime = std::max(limits.time[us], minThinkingTime);
+
+ const int MaxMTG = limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon;
+
+ // We calculate optimum time usage for different hypothetical "moves to go"-values
+ // and choose the minimum of calculated search time values. Usually the greatest
+ // hypMTG gives the minimum values.
+ for (int hypMTG = 1; hypMTG <= MaxMTG; ++hypMTG)
+ {
+ // Calculate thinking time for hypothetical "moves to go"-value
+ int hypMyTime = limits.time[us]
+ + limits.inc[us] * (hypMTG - 1)
+ - moveOverhead * (2 + std::min(hypMTG, 40));
+
+ hypMyTime = std::max(hypMyTime, 0);
+
+ int t1 = minThinkingTime + remaining(hypMyTime, hypMTG, ply, slowMover);
+ int t2 = minThinkingTime + remaining(hypMyTime, hypMTG, ply, slowMover);
+
+ optimumTime = std::min(t1, optimumTime);
+ maximumTime = std::min(t2, maximumTime);
+ }
+
+ if (Options["Ponder"])
+ optimumTime += optimumTime / 4;
}
diff --git a/Engines/Linux64/mcbrain/src/timeman.h b/Engines/Linux64/mcbrain/src/timeman.h
index 427271a..4d3172b 100644
--- a/Engines/Linux64/mcbrain/src/timeman.h
+++ b/Engines/Linux64/mcbrain/src/timeman.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain 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/Linux64/mcbrain/src/tt.cpp b/Engines/Linux64/mcbrain/src/tt.cpp
index 9bb093d..1aed0f3 100644
--- a/Engines/Linux64/mcbrain/src/tt.cpp
+++ b/Engines/Linux64/mcbrain/src/tt.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -34,7 +34,7 @@ TranspositionTable TT; // Our global transposition table
void TranspositionTable::resize(size_t mbSize) {
- size_t newClusterCount = size_t(1) << msb((mbSize * 1024 * 1024) / sizeof(Cluster));
+ size_t newClusterCount = mbSize * 1024 * 1024 / sizeof(Cluster);
if (newClusterCount == clusterCount)
return;
@@ -42,7 +42,7 @@ void TranspositionTable::resize(size_t mbSize) {
clusterCount = newClusterCount;
free(mem);
- mem = calloc(clusterCount * sizeof(Cluster) + CacheLineSize - 1, 1);
+ mem = malloc(clusterCount * sizeof(Cluster) + CacheLineSize - 1);
if (!mem)
{
@@ -52,6 +52,7 @@ void TranspositionTable::resize(size_t mbSize) {
}
table = (Cluster*)((uintptr_t(mem) + CacheLineSize - 1) & ~(CacheLineSize - 1));
+ clear();
}
diff --git a/Engines/Linux64/mcbrain/src/tt.h b/Engines/Linux64/mcbrain/src/tt.h
index 56646a6..e0dc386 100644
--- a/Engines/Linux64/mcbrain/src/tt.h
+++ b/Engines/Linux64/mcbrain/src/tt.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -105,9 +105,9 @@ class TranspositionTable {
void resize(size_t mbSize);
void clear();
- // The lowest order bits of the key are used to get the index of the cluster
+ // The 32 lowest order bits of the key are used to get the index of the cluster
TTEntry* first_entry(const Key key) const {
- return &table[(size_t)key & (clusterCount - 1)].entry[0];
+ return &table[(uint32_t(key) * uint64_t(clusterCount)) >> 32].entry[0];
}
private:
diff --git a/Engines/Linux64/mcbrain/src/types.h b/Engines/Linux64/mcbrain/src/types.h
index 77acc44..7b4318e 100644
--- a/Engines/Linux64/mcbrain/src/types.h
+++ b/Engines/Linux64/mcbrain/src/types.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -334,7 +334,7 @@ inline Square& operator-=(Square &s, Direction d) { return s = s - d; }
/// Only declared but not defined. We don't want to multiply two scores due to
/// a very high risk of overflow. So user should explicitly convert to integer.
-Score operator*(Score s1, Score s2) = delete;
+Score operator*(Score, Score) = delete;
/// Division of a Score must be handled separately for each term
inline Score operator/(Score s, int i) {
diff --git a/Engines/Linux64/mcbrain/src/tzbook.cpp b/Engines/Linux64/mcbrain/src/tzbook.cpp
deleted file mode 100644
index 4052256..0000000
--- a/Engines/Linux64/mcbrain/src/tzbook.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-#include "tzbook.h"
-#include "uci.h"
-#include "movegen.h"
-#include "thread.h"
-#include
-#include "misc.h"
-#include
-
-TZBook tzbook; // global TZBook
-
-using namespace std;
-
-int qsort_compare_int(const void* a, const void* b)
-{
- const int int_a = *((const int*)a);
- const int int_b = *((const int*)b);
-
- if (int_a == int_b) return 0;
- else if (int_a < int_b) return -1;
- else return 1;
-}
-
-TZBook::TZBook()
-{
- keycount = 0;
- book_move2_probability = 0;
- last_position = 0;
- akt_position = 0;
- last_anz_pieces = 0;
- akt_anz_pieces = 0;
- search_counter = 0;
- tzhash2 = NULL;
- do_search = true;
- enabled = false;
-}
-
-TZBook::~TZBook()
-{
-}
-
-
-void TZBook::init(const std::string& path)
-{
- if (path.length() == 0) return;
-
- const char *p = path.c_str();
- if (strcmp(p, "") == 0)
- return;
-
- FILE *fpt = fopen(p, "rb");
- if (fpt == NULL)
- {
- sync_cout << "info string Could not open " << path << sync_endl;
- return;
- }
-
- if (tzhash2 != NULL)
- {
- free(tzhash2);
- tzhash2 = NULL;
- }
-
- fseek(fpt, 0L, SEEK_END);
- int filesize = ftell(fpt);
- fseek(fpt, 0L, SEEK_SET);
-
- keycount = filesize / 8;
- tzhash2 = new TZHash2[keycount];
-
- fread(tzhash2, 1, filesize, fpt);
- fclose(fpt);
-
- sync_cout << "info string Book loaded: " << path << sync_endl;
-
- srand((int)time(NULL));
- enabled = true;
-}
-
-
-void TZBook::set_book_move2_probability(int book_move2_prob)
-{
- book_move2_probability = book_move2_prob;
-}
-
-
-Move TZBook::probe2(Position& pos)
-{
- Move m = MOVE_NONE;
- if (!enabled) return m;
-
- akt_position = pos.pieces();
- akt_anz_pieces = popcount(akt_position);
-
- if (do_search == false)
- {
- Bitboard b = akt_position ^ last_position;
- int n2 = popcount(b);
-
- if (n2 > 4) do_search = true;
- if (akt_anz_pieces > last_anz_pieces) do_search = true;
- if (akt_anz_pieces < last_anz_pieces - 2) do_search = true;
- }
-
- last_position = akt_position;
- last_anz_pieces = akt_anz_pieces;
-
- if (do_search)
- {
- TZHash2 *tz = probe2(pos.key());
- if (tz == NULL)
- {
- search_counter++;
- if (search_counter > 2)
- {
- do_search = false;
- search_counter = 0;
- }
- }
- else
- {
- if (pos.is_draw(64))
- m = get_move_from_draw_position(pos, tz);
- else
- m = get_move(pos, tz);
- }
- }
-
- return m;
-}
-
-
-TZHash2 *TZBook::probe2(Key key)
-{
- uint32_t key1 = key >> 32;
- unsigned short key2 = key >> 16 & 0xFFFF;
-
- int start = 0;
- int end = keycount;
-
- for (;;)
- {
- int mid = (end + start) / 2;
-
- if (tzhash2[mid].key1 < key1)
- start = mid;
- else
- {
- if (tzhash2[mid].key1 > key1)
- end = mid;
- else
- {
- start = max(mid - 4, 0);
- end = min(mid + 4, keycount);
- }
- }
-
- if (end - start < 9)
- break;
- }
-
- for (int i = start; i < end; i++)
- if ((key1 == tzhash2[i].key1) && (key2 == tzhash2[i].key2))
- return &(tzhash2[i]);
-
- return NULL;
-}
-
-Move TZBook::movenumber_to_move(Position& pos, int n)
-{
- const ExtMove *m = MoveList(pos).begin();
- size_t size = MoveList(pos).size();
- Move *mv = new Move[size];
- for (unsigned int i = 0; i < size; i++)
- mv[i] = m[i].move;
-
- qsort(mv, size, sizeof(mv[0]), qsort_compare_int);
-
- return mv[n];
-}
-
-bool TZBook::check_draw(Move m, Position& pos)
-{
- StateInfo st;
-
- pos.do_move(m, st, pos.gives_check(m));
- bool draw = pos.is_draw(64);
- pos.undo_move(m);
-
- return draw;
-}
-
-
-Move TZBook::get_move_from_draw_position(Position& pos, TZHash2 *tz)
-{
- Move m = movenumber_to_move(pos, tz->move_number);
- if (!check_draw(m, pos))
- return m;
-
- if (tz->move_number2 == 255)
- return m;
-
- m = movenumber_to_move(pos, tz->move_number2);
- if (!check_draw(m, pos))
- return m;
-
- return MOVE_NONE;
-}
-
-
-Move TZBook::get_move(Position& pos, TZHash2 *tz)
-{
- Move m1 = movenumber_to_move(pos, tz->move_number);
- if ((book_move2_probability == 0) || (tz->move_number2 == 255))
- return m1;
-
- Move m2 = movenumber_to_move(pos, tz->move_number2);
- if ((book_move2_probability == 100) || (rand() % 100 < book_move2_probability))
- return m2;
-
- return m1;
-}
\ No newline at end of file
diff --git a/Engines/Linux64/mcbrain/src/tzbook.h b/Engines/Linux64/mcbrain/src/tzbook.h
deleted file mode 100644
index 744618a..0000000
--- a/Engines/Linux64/mcbrain/src/tzbook.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef TZBOOK_H_INCLUDED
-#define TZBOOK_H_INCLUDED
-
-#include "bitboard.h"
-#include "position.h"
-#include "string.h"
-
-struct TZHash2
-{
- uint32_t key1;
- uint16_t key2;
- unsigned char move_number;
- unsigned char move_number2;
-};
-
-class TZBook
-{
- public:
-
- Bitboard last_position;
- Bitboard akt_position;
- int last_anz_pieces;
- int akt_anz_pieces;
- int search_counter;
-
- bool enabled, do_search;
- int book_move2_probability;
-
- TZBook();
- ~TZBook();
-
- void init(const std::string& path);
- void set_book_move2_probability(int book_move2_prob);
-
- Move probe2(Position& pos);
- TZHash2 *probe2(Key key);
-
-private:
-
- int keycount;
- TZHash2 *tzhash2;
- bool check_draw(Move m, Position& pos);
- Move get_move_from_draw_position(Position& pos, TZHash2 *tz);
- Move get_move(Position& pos, TZHash2 *tz);
- Move movenumber_to_move(Position& pos, int n);
-};
-
-extern TZBook tzbook;
-
-#endif // #ifndef TZBOOK_H_INCLUDED
\ No newline at end of file
diff --git a/Engines/Linux64/mcbrain/src/uci.cpp b/Engines/Linux64/mcbrain/src/uci.cpp
index ecbbe8b..40efb6d 100644
--- a/Engines/Linux64/mcbrain/src/uci.cpp
+++ b/Engines/Linux64/mcbrain/src/uci.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -273,13 +273,13 @@ void UCI::loop(int argc, char* argv[]) {
else if (token == "position")
{
position(pos, is, states);
- if (Options["Clean_Search"] == 1)
+ if (Options["Clean_Search"] == true)
Search::clear();
}
else if (token == "p")
{
position(pos, is, states);
- if (Options["Clean Search"] == 1)
+ if (Options["Clean_Search"] == true)
Search::clear();
}
else if (token == "ucinewgame") Search::clear();
diff --git a/Engines/Linux64/mcbrain/src/uci.h b/Engines/Linux64/mcbrain/src/uci.h
index 1564f72..713468b 100644
--- a/Engines/Linux64/mcbrain/src/uci.h
+++ b/Engines/Linux64/mcbrain/src/uci.h
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -51,11 +51,13 @@ class Option {
Option(bool v, OnChange = nullptr);
Option(const char* v, OnChange = nullptr);
Option(int v, int minv, int maxv, OnChange = nullptr);
+ Option(const char* v, const char *cur, OnChange = nullptr);
Option& operator=(const std::string&);
void operator<<(const Option&);
operator int() const;
operator std::string() const;
+ bool operator==(const char*);
private:
friend std::ostream& operator<<(std::ostream&, const OptionsMap&);
diff --git a/Engines/Linux64/mcbrain/src/ucioption.cpp b/Engines/Linux64/mcbrain/src/ucioption.cpp
index 8389ca1..3c31396 100644
--- a/Engines/Linux64/mcbrain/src/ucioption.cpp
+++ b/Engines/Linux64/mcbrain/src/ucioption.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish Authors)
Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish Authors)
- Copyright (C) 2017 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
+ Copyright (C) 2017-2018 Michael Byrne, Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (McBrain Authors)
McBrain is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -60,8 +60,15 @@ bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const
void init(OptionsMap& o) {
- const int MaxHashMB = Is64Bit ? 1024 * 1024 : 2048;
+ // at most 2^32 clusters.
+ const int MaxHashMB = Is64Bit ? 131072 : 2048;
+ o["Debug Log File"] << Option("", on_logger);
+ o["Contempt"] << Option(20, -100, 100);
+ o["Analysis Contempt"] << Option("Off var Off var White var Black var Both", "Off");
+ o["UCI_AnalyseMode"] << Option(false);
+ o["Tactical"] << Option(0, 0, 8);
+ o["Threads"] << Option(1, 1, 512, on_threads);
o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size);
o["Ponder"] << Option(false);
o["Threads"] << Option(1, 1, 512, on_threads);
@@ -70,21 +77,25 @@ void init(OptionsMap& o) {
o["BruteForce"] << Option(false);
o["FastPlay"] << Option(false);
o["No_Null_Moves"] << Option(false);
-
+ o["UCI_Chess960"] << Option(false);
o["UCI_LimitStrength"] << Option(false);
+
o["UCI_ELO"] << Option(1500, 1500, 2800);
- o["MultiPV"] << Option(1, 1, 500);
o["Skill Level"] << Option(20, 0, 20);
- o["Contempt"] << Option(2, -150, 150);
- o["Tactical"] << Option(0, 0, 8);
- o["Move Overhead"] << Option(100, 0, 5000);
+ o["MultiPV"] << Option(1, 1, 256);
+
+
+ o["Move Overhead"] << Option(30, 0, 5000);
+ o["Minimum Thinking Time"] << Option(20, 0, 5000);
+ o["Slow Mover"] << Option(89, 10, 1000);
o["nodestime"] << Option(0, 0, 10000);
- o["UCI_Chess960"] << Option(false);
+
o["SyzygyPath"] << Option("", on_tb_path);
o["SyzygyProbeDepth"] << Option(1, 1, 100);
o["Syzygy50MoveRule"] << Option(true);
o["SyzygyProbeLimit"] << Option(6, 0, 6);
+ o["Book_Enabled"] << Option(false);
o["BookFile"] << Option("", on_book_file);
o["BestBookMove"] << Option(true, on_best_book_move);
o["BookDepth"] << Option(255, 1, 255, on_book_depth);
@@ -131,6 +142,9 @@ Option::Option(OnChange f) : type("button"), min(0), max(0), on_change(f)
Option::Option(int v, int minv, int maxv, OnChange f) : type("spin"), min(minv), max(maxv), on_change(f)
{ defaultValue = currentValue = std::to_string(v); }
+Option::Option(const char* v, const char* cur, OnChange f) : type("combo"), min(0), max(0), on_change(f)
+{ defaultValue = v; currentValue = cur; }
+
Option::operator int() const {
assert(type == "check" || type == "spin");
return (type == "spin" ? stoi(currentValue) : currentValue == "true");
@@ -141,6 +155,11 @@ Option::operator std::string() const {
return currentValue;
}
+bool Option::operator==(const char* s) {
+ assert(type == "combo");
+ return !CaseInsensitiveLess()(currentValue, s) && !CaseInsensitiveLess()(s, currentValue);
+}
+
/// operator<<() inits options and assigns idx in the correct printing order
diff --git a/Engines/Linux64/stockfish/.travis.yml b/Engines/Linux64/stockfish/.travis.yml
index af0bb2b..8586921 100644
--- a/Engines/Linux64/stockfish/.travis.yml
+++ b/Engines/Linux64/stockfish/.travis.yml
@@ -9,7 +9,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
- packages: ['g++-6', 'g++-6-multilib', 'g++-multilib', 'valgrind']
+ packages: ['g++-6', 'g++-6-multilib', 'g++-multilib', 'valgrind', 'expect']
env:
- COMPILER=g++-6
- COMP=gcc
@@ -19,7 +19,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
- packages: ['clang', 'g++-multilib', 'valgrind']
+ packages: ['clang', 'g++-multilib', 'valgrind', 'expect']
env:
- COMPILER=clang++
- COMP=clang
@@ -44,12 +44,30 @@ before_script:
- cd src
script:
- - make clean && make build ARCH=x86-64 && ./stockfish bench 2>&1 >/dev/null | grep 'Nodes searched' | tee bench1
- - make clean && make build ARCH=x86-32 && ./stockfish bench 2>&1 >/dev/null | grep 'Nodes searched' | tee bench2
- - echo "Checking for same bench numbers..."
- - diff bench1 bench2 > result
- - test ! -s result
- # if valgrind is available check the build is without error, reduce depth to speedup testing, but not too shallow to catch more cases.
- - if [ -x "$(command -v valgrind )" ] ; then make clean && make ARCH=x86-64 debug=yes build && valgrind --error-exitcode=42 ./stockfish bench 128 1 10 default depth 1>/dev/null ; fi
- # use g++-6 as a proxy for having sanitizers ... might need revision as they become available for more recent versions of clang/gcc than trusty provides
- - if [[ "$COMPILER" == "g++-6" ]]; then make clean && make ARCH=x86-64 sanitize=yes build && ! ./stockfish bench 2>&1 | grep "runtime error:" ; fi
+ # Obtain bench reference from git log
+ - git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9][0-9]*\)/\1/g" > git_sig
+ - export benchref=$(cat git_sig)
+ - echo "Reference bench:" $benchref
+ #
+ # Verify bench number against various builds
+ - export CXXFLAGS=-Werror
+ - make clean && make -j2 ARCH=x86-64 optimize=no debug=yes build && ../tests/signature.sh $benchref
+ - make clean && make -j2 ARCH=x86-32 optimize=no debug=yes build && ../tests/signature.sh $benchref
+ - make clean && make -j2 ARCH=x86-32 build && ../tests/signature.sh $benchref
+ - make clean && make -j2 ARCH=x86-64 build && ../tests/signature.sh $benchref
+ #
+ # Check perft and reproducible search
+ - ../tests/perft.sh
+ - ../tests/reprosearch.sh
+ #
+ # Valgrind
+ #
+ - export CXXFLAGS=-O1
+ - if [ -x "$(command -v valgrind )" ]; then make clean && make -j2 ARCH=x86-64 debug=yes optimize=no build > /dev/null && ../tests/instrumented.sh --valgrind; fi
+ - if [ -x "$(command -v valgrind )" ]; then ../tests/instrumented.sh --valgrind-thread; fi
+ #
+ # Sanitizer
+ #
+ # Use g++-6 as a proxy for having sanitizers, might need revision as they become available for more recent versions of clang/gcc
+ - if [[ "$COMPILER" == "g++-6" ]]; then make clean && make -j2 ARCH=x86-64 sanitize=undefined optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-undefined; fi
+ - if [[ "$COMPILER" == "g++-6" ]]; then make clean && make -j2 ARCH=x86-64 sanitize=thread optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-thread; fi
diff --git a/Engines/Linux64/stockfish/AUTHORS b/Engines/Linux64/stockfish/AUTHORS
index 5cd63d2..9b91b93 100644
--- a/Engines/Linux64/stockfish/AUTHORS
+++ b/Engines/Linux64/stockfish/AUTHORS
@@ -1,98 +1,98 @@
-# Generated with git shortlog -sn | cut -c8-', which sorts by commits (manually ordered the first four authors)
+# Generated with 'git shortlog -sn | cut -c8-', which sorts by commits, manually ordered the first four authors, merged duplicates
Tord Romstad
-Marco Costalba
-Joona Kiiski
-Gary Linscott
-lucasart
+Marco Costalba (mcostalba)
+Joona Kiiski (zamar)
+Gary Linscott (glinscott)
+Lucas Braesch (lucasart)
+Bill Henry (VoyagerOne)
mstembera
-Lucas Braesch
+Stéphane Nicolet (Stephane Nicolet, snicolet)
Stefan Geschwentner
+Alain SAVARD (Rocky640)
+Jörg Oster (Joerg Oster, joergoster)
Reuven Peleg
-Chris Caino
-joergoster
-VoyagerOne
+Chris Caino (Chris Cain, ceebo)
Jean-Francois Romang
homoSapiensSapiens
-Alain SAVARD
+Leonid Pechenik
+Stefano Cardanobile (Stefano80)
Arjun Temurnikar
-Stéphane Nicolet
-Uri Blass
+Uri Blass (uriblass)
jundery
-Ralph Stößer
-Ajith
-Leonid Pechenik
-Stefano80
-Tom Vijlbrief
+Ajith (ajithcj)
hxim
-snicolet
+Ralph Stößer (Ralph Stoesser)
+Guenther Demetz
+Jonathan Calovski (Mysseno)
+Tom Vijlbrief
+mbootsector
Daylen Yang
+ElbertoOne
Henri Wiechers
-Jonathan Calovski
-mbootsector
+loco-loco
+Joost VandeVondele (Joost Vandevondele)
+Ronald de Man (syzygy)
+DU-jdto
David Zar
Eelco de Groot
Jerry Donald
-Joerg Oster
-Jörg Oster
+NicklasPersson
Ryan Schmitt
-mcostalba
Alexander Kure
Dan Schmidt
H. Felix Wittmann
+Jacques
Joseph R. Prostko
Justin Blanchard
Linus Arver
-NicklasPersson
+Luca Brivio
+Lyudmil Antonov
Rodrigo Exterckötter Tjäder
Ron Britvich
-Ronald de Man
RyanTaker
Vince Negri
-ceebo
-jhellis3
-ppigazzini
+erbsenzaehler
+Joseph Hellis (jhellis3)
shane31
+Andrew Grant
Andy Duplain
Auguste Pop
Balint Pfliegel
-Chris Cain
-DU-jdto
Dariusz Orzechowski
DiscanX
Ernesto Gatti
Gregor Cramer
-Guenther Demetz
-Hiraoka Takuya
+Hiraoka Takuya (HiraokaTakuya)
Hongzhi Cheng
-Joseph Hellis
+IIvec
Kelly Wilson
Ken T Takusagawa
Kojirion
-Luca Brivio
+Krgp
Matt Sullivan
Matthew Lai
Matthew Sullivan
Michel Van den Bergh
-Mysseno
+Niklas Fiekas
Oskar Werkelin Ahlin
Pablo Vazquez
Pascal Romaret
-Ralph Stoesser
-Ralph Stößer
Raminder Singh
Richard Lloyd
Ryan Takker
-Stephane Nicolet
Thanar2
absimaldata
+atumanian
braich
+fanon
+gamander
gguliash
kinderchocolate
-loco-loco
pellanda
+ppigazzini
renouve
sf-x
thaspel
unknown
-uriblass
+
diff --git a/Engines/Linux64/stockfish/Linux/stockfish-9-64 b/Engines/Linux64/stockfish/Linux/stockfish-9-64
new file mode 100644
index 0000000..69e30cc
Binary files /dev/null and b/Engines/Linux64/stockfish/Linux/stockfish-9-64 differ
diff --git a/Engines/Linux64/stockfish/Readme.md b/Engines/Linux64/stockfish/Readme.md
index 29ebf59..e3b36cc 100644
--- a/Engines/Linux64/stockfish/Readme.md
+++ b/Engines/Linux64/stockfish/Readme.md
@@ -10,7 +10,7 @@ Partner or Fritz) in order to be used comfortably. Read the
documentation for your GUI of choice for information about how to use
Stockfish with it.
-This version of Stockfish supports up to 128 cores. The engine defaults
+This version of Stockfish supports up to 512 cores. The engine defaults
to one search thread, so it is therefore recommended to inspect the value of
the *Threads* UCI parameter, and to make sure it equals the number of CPU
cores on your computer.
@@ -96,6 +96,14 @@ compile (for instance with Microsoft MSVC) you need to manually
set/unset some switches in the compiler command line; see file *types.h*
for a quick reference.
+### Resource For Understanding the Code Base
+
+* [Chessprogramingwiki](https://chessprogramming.wikispaces.com) has good overall chess engines explanations
+(techniques used here are well explained like hash maps etc), it was
+also recommended by the [support at stockfish.](http://support.stockfishchess.org/discussions/questions/1132-how-to-understand-stockfish-sources)
+
+* [Here](https://chessprogramming.wikispaces.com/Stockfish) you can find a set of features and techniques used by stockfish and each of them is explained at the wiki, however, it's a generic way rather than focusing on stockfish's own implementation, but it will still help you.
+
### Terms of use
diff --git a/Engines/Linux64/stockfish/Top CPU Contributors.txt b/Engines/Linux64/stockfish/Top CPU Contributors.txt
new file mode 100644
index 0000000..4c2aa47
--- /dev/null
+++ b/Engines/Linux64/stockfish/Top CPU Contributors.txt
@@ -0,0 +1,132 @@
+Contributors with >10,000 CPU hours as of January 23, 2018
+Thank you!
+
+Username CPU Hours Games played
+mibere 518300 41835669
+crunchy 375564 29121434
+cw 371664 28748719
+fastgm 299773 20765374
+JojoM 220590 15299913
+glinscott 204517 13932027
+bking_US 187568 12233168
+ctoks 169342 13475495
+spams 149531 10940322
+Thanar 137015 11714855
+velislav 127305 10047749
+vdbergh 121741 9056874
+malala 117291 8126488
+vdv 117218 8289983
+leszek 114825 8331897
+dsmith 114010 7622414
+CSU_Dynasty 113516 9582758
+sqrt2 112407 8782694
+marrco 111143 8222921
+drabel 108168 9061580
+BrunoBanani 104938 7448565
+Data 94621 8433010
+CoffeeOne 90394 3964243
+BRAVONE 80811 5341681
+psk 77195 6156031
+brabos 70284 5685893
+Fisherman 66650 5572406
+nssy 64587 5369140
+Pking_cda 64499 5704075
+sterni1971 63488 5070004
+mgrabiak 62385 5420812
+tvijlbrief 58957 4154234
+jromang 58854 4704502
+dv8silencer 57421 3961325
+sunu 56620 4609155
+tinker 56039 4204914
+biffhero 55743 4810039
+teddybaer 52982 4740444
+bcross 50548 5071599
+renouve 50318 3544864
+Freja 50296 3805120
+robnjr 47504 4131742
+eva42 46542 4044694
+davar 46538 4030604
+finfish 46244 3481661
+rap 46201 3219490
+ttruscott 45037 3645430
+solarlight 44155 4074841
+TueRens 41372 3891510
+ElbertoOne 41321 3920894
+Antihistamine 39218 2792761
+mhunt 38991 2697512
+bigpen0r 37820 3149955
+homyur 35569 3009637
+VoyagerOne 35137 3302650
+mhoram 34770 2684128
+racerschmacer 33022 3231055
+speedycpu 32043 2531964
+EthanOConnor 31638 2143255
+oryx 29574 2767730
+Pyafue 28885 1986098
+jkiiski 28014 1923255
+Garf 27579 2770144
+slakovv 27017 2031279
+Bobo1239 27000 2488707
+pb00067 26817 2306694
+robal 26337 2316795
+hyperbolic.tom 26248 2200777
+rkl 24898 2236013
+SC 23988 2126825
+nabildanial 23524 1586321
+achambord 23495 1942546
+Sharaf_DG 22975 1790697
+chriswk 22876 1947731
+anst 22568 2013953
+Patrick_G 22435 1682293
+cuistot 22201 1383031
+gri 21901 1820968
+Prcuvu 21182 1890546
+Zirie 21171 1493227
+JanErik 20596 1791991
+Isidor 20560 1730290
+xor12 20535 1819280
+team-oh 20364 1653708
+nesoneg 20264 1493435
+rstoesser 19802 1335177
+grandphish2 19402 1834196
+sg4032 18427 1671742
+dew 18263 1423326
+ianh2105 18133 1668562
+MazeOfGalious 18022 1644593
+ville 17900 1539130
+j3corre 17607 975954
+eudhan 17502 1424648
+iisiraider 17175 1118788
+jundery 17172 1115855
+SFTUser 16635 1363975
+purplefishies 16621 1106850
+DragonLord 16599 1252348
+chris 15274 1575333
+xoto 14900 1486261
+dju 14861 901552
+dex 14647 1228763
+nordlandia 14551 1369718
+ronaldjerum 14361 1210607
+OssumOpossum 14149 1029265
+IgorLeMasson 13844 1228391
+enedene 13762 935618
+ako027ako 13442 1250249
+AdrianSA 13324 924980
+bpfliegel 13318 886523
+ncfish1 13056 932344
+wei 12863 1369596
+jpulman 12776 854815
+horst.prack 12436 1151505
+joster 12424 986622
+cisco2015 12265 1205019
+fatmurphy 12015 901134
+modolief 11228 926456
+Dark_wizzie 11214 1017910
+mschmidt 10973 818594
+eastorwest 10970 1117836
+infinity 10762 746397
+SapphireBrand 10692 1024604
+Thomas A. 10553 736094
+pgontarz 10294 878746
+Andrew Grant 10195 922933
+stocky 10083 718114
diff --git a/Engines/Linux64/stockfish/appveyor.yml b/Engines/Linux64/stockfish/appveyor.yml
index a46a0f3..c711dd6 100644
--- a/Engines/Linux64/stockfish/appveyor.yml
+++ b/Engines/Linux64/stockfish/appveyor.yml
@@ -1,5 +1,5 @@
version: 1.0.{build}
-clone_depth: 5
+clone_depth: 50
branches:
only:
@@ -13,10 +13,11 @@ os: Visual Studio 2015
platform:
- x86
- x64
- - Any CPU
# build Configuration, i.e. Debug, Release, etc.
-configuration: Debug
+configuration:
+ - Debug
+ - Release
matrix:
# The build fail immediately once one of the job fails
@@ -28,18 +29,43 @@ init:
- msbuild /version
before_build:
- - cd src
- - echo project (Stockfish) >> CMakeLists.txt
- - echo add_executable(stockfish benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp >> CMakeLists.txt
- - echo main.cpp material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp >> CMakeLists.txt
- - echo search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp syzygy/tbprobe.cpp) >> CMakeLists.txt
- - echo set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src) >> CMakeLists.txt
-# - echo target_compile_options(stockfish PUBLIC "/Ox") >> CMakeLists.txt
+ - ps: |
+ # Get sources
+ $src = get-childitem -Path *.cpp -Recurse | select -ExpandProperty FullName
+ $src = $src -join ' '
+ $src = $src.Replace("\", "/")
+
+ # Build CMakeLists.txt
+ $t = 'cmake_minimum_required(VERSION 3.8)',
+ 'project(Stockfish)',
+ 'set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src)',
+ 'set(source_files', $src, ')',
+ 'add_executable(stockfish ${source_files})'
+
+ # Write CMakeLists.txt withouth BOM
+ $MyPath = (Get-Item -Path "." -Verbose).FullName + '\CMakeLists.txt'
+ $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
+ [System.IO.File]::WriteAllLines($MyPath, $t, $Utf8NoBomEncoding)
+
+ # Obtain bench reference from git log
+ $b = git log HEAD | sls "\b[Bb]ench[ :]+[0-9]{7}" | select -first 1
+ $bench = $b -match '\D+(\d+)' | % { $matches[1] }
+ Write-Host "Reference bench:" $bench
+ $g = "Visual Studio 14 2015"
+ If (${env:PLATFORM} -eq 'x64') { $g = $g + ' Win64' }
+ cmake -G "${g}" .
+ Write-Host "Generated files for: " $g
build_script:
- - cmake -G "Visual Studio 14 2015 Win64" .
- - cmake --build .
+ - cmake --build . --config %CONFIGURATION% -- /verbosity:minimal
before_test:
- - cd Debug
- - stockfish.exe bench > null
+ - cd src/%CONFIGURATION%
+ - ps: |
+ # Verify bench number
+ ./stockfish bench 2> out.txt 1> null
+ $s = (gc "./out.txt" | out-string)
+ $r = ($s -match 'Nodes searched \D+(\d+)' | % { $matches[1] })
+ Write-Host "Engine bench:" $r
+ Write-Host "Reference bench:" $bench
+ If ($r -ne $bench) { exit 1 }
diff --git a/Engines/Linux64/stockfish/src/Makefile b/Engines/Linux64/stockfish/src/Makefile
index cdedd25..72afcc3 100644
--- a/Engines/Linux64/stockfish/src/Makefile
+++ b/Engines/Linux64/stockfish/src/Makefile
@@ -1,7 +1,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-2018 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
@@ -50,7 +50,9 @@ 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
+# sanitize = undefined/thread/no (-fsanitize )
+# --- ( undefined ) --- enable undefined behavior checks
+# --- ( thread ) --- enable threading error 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
@@ -139,7 +141,7 @@ endif
### 3.1 Selecting compiler (default = gcc)
-CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -fno-rtti -std=c++11 $(EXTRACXXFLAGS)
+CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++11 $(EXTRACXXFLAGS)
DEPENDFLAGS += -std=c++11
LDFLAGS += $(EXTRALDFLAGS)
@@ -155,9 +157,11 @@ ifeq ($(COMP),gcc)
ifeq ($(ARCH),armv7)
ifeq ($(OS),Android)
CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
endif
else
CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
endif
ifneq ($(KERNEL),Darwin)
@@ -200,6 +204,11 @@ ifeq ($(COMP),clang)
comp=clang
CXX=clang++
CXXFLAGS += -pedantic -Wextra -Wshadow
+ifneq ($(KERNEL),Darwin)
+ifneq ($(KERNEL),OpenBSD)
+ LDFLAGS += -latomic
+endif
+endif
ifeq ($(ARCH),armv7)
ifeq ($(OS),Android)
@@ -210,23 +219,19 @@ ifeq ($(COMP),clang)
CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits)
endif
-
- ifeq ($(KERNEL),Darwin)
- CXXFLAGS += -stdlib=libc++
- DEPENDFLAGS += -stdlib=libc++
- 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 ($(KERNEL),Darwin)
@@ -263,8 +268,9 @@ else
endif
### 3.2.2 Debugging with undefined behavior sanitizers
-ifeq ($(sanitize),yes)
- CXXFLAGS += -g3 -fsanitize=undefined
+ifneq ($(sanitize),no)
+ CXXFLAGS += -g3 -fsanitize=$(sanitize) -fuse-ld=gold
+ LDFLAGS += -fsanitize=$(sanitize) -fuse-ld=gold
endif
### 3.3 Optimization
@@ -296,10 +302,8 @@ ifeq ($(optimize),yes)
ifeq ($(comp),clang)
ifeq ($(KERNEL),Darwin)
- ifeq ($(pext),no)
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS)
- endif
ifeq ($(arch),i386)
CXXFLAGS += -mdynamic-no-pic
endif
@@ -423,30 +427,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
- @echo ""
- @echo "Step 0/4. Preparing for profile build."
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_prepare)
+profile-build: config-sanity objclean profileclean
@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)
@@ -456,8 +457,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
@@ -472,6 +484,7 @@ config-sanity:
@echo ""
@echo "Config:"
@echo "debug: '$(debug)'"
+ @echo "sanitize: '$(sanitize)'"
@echo "optimize: '$(optimize)'"
@echo "arch: '$(arch)'"
@echo "bits: '$(bits)'"
@@ -490,6 +503,7 @@ config-sanity:
@echo "Testing config sanity. If this fails, try 'make help' ..."
@echo ""
@test "$(debug)" = "yes" || test "$(debug)" = "no"
+ @test "$(sanitize)" = "undefined" || test "$(sanitize)" = "thread" || 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"
@@ -503,8 +517,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) \
@@ -518,14 +542,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
@@ -535,9 +553,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/Linux64/stockfish/src/benchmark.cpp b/Engines/Linux64/stockfish/src/benchmark.cpp
index f2d1f06..1c69dca 100644
--- a/Engines/Linux64/stockfish/src/benchmark.cpp
+++ b/Engines/Linux64/stockfish/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-2018 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
@@ -23,23 +23,20 @@
#include
#include
-#include "misc.h"
#include "position.h"
-#include "search.h"
-#include "thread.h"
-#include "uci.h"
using namespace std;
namespace {
const vector Defaults = {
+ "setoption name UCI_Chess960 value false",
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
"r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 10",
"8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 11",
"4rrk1/pp1n3p/3q2pQ/2p1pb2/2PP4/2P3N1/P2B2PP/4RRK1 b - - 7 19",
- "rq3rk1/ppp2ppp/1bnpb3/3N2B1/3NP3/7P/PPPQ1PP1/2KR3R w - - 7 14",
- "r1bq1r1k/1pp1n1pp/1p1p4/4p2Q/4Pp2/1BNP4/PPP2PPP/3R1RK1 w - - 2 14",
+ "rq3rk1/ppp2ppp/1bnpb3/3N2B1/3NP3/7P/PPPQ1PP1/2KR3R w - - 7 14 moves d4e6",
+ "r1bq1r1k/1pp1n1pp/1p1p4/4p2Q/4Pp2/1BNP4/PPP2PPP/3R1RK1 w - - 2 14 moves g2g4",
"r3r1k1/2p2ppp/p1p1bn2/8/1q2P3/2NPQN2/PPP3PP/R4RK1 b - - 2 15",
"r1bbk1nr/pp3p1p/2n5/1N4p1/2Np1B2/8/PPP2PPP/2KR1B1R w kq - 0 13",
"r1bq1rk1/ppp1nppp/4n3/3p3Q/3P4/1BP1B3/PP1N2PP/R4RK1 w - - 1 16",
@@ -52,7 +49,7 @@ const vector Defaults = {
"3q2k1/pb3p1p/4pbp1/2r5/PpN2N2/1P2P2P/5PP1/Q2R2K1 b - - 4 26",
"6k1/6p1/6Pp/ppp5/3pn2P/1P3K2/1PP2P2/3N4 b - - 0 1",
"3b4/5kp1/1p1p1p1p/pP1PpP1P/P1P1P3/3KN3/8/8 w - - 0 1",
- "2K5/p7/7P/5pR1/8/5k2/r7/8 w - - 0 1",
+ "2K5/p7/7P/5pR1/8/5k2/r7/8 w - - 0 1 moves g5g6 f3e3 g6g5 e3f3",
"8/6pk/1p6/8/PP3p1p/5P2/4KP1q/3Q4 w - - 0 1",
"7k/3p2pp/4q3/8/4Q3/5Kp1/P6b/8 w - - 0 1",
"8/2p5/8/2kPKp1p/2p4P/2P5/3P4/8 w - - 0 1",
@@ -79,28 +76,35 @@ const vector Defaults = {
"8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124", // Draw
// Mate and stalemate positions
+ "6k1/3b3r/1p1p4/p1n2p2/1PPNpP1q/P3Q1p1/1R1RB1P1/5K2 b - - 0 1",
+ "r2r1n2/pp2bk2/2p1p2p/3q4/3PN1QP/2P3R1/P4PP1/5RK1 w - - 0 1",
"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 - -"
+ "7k/7P/6K1/8/3B4/8/8/8 b - -",
+
+ // Chess 960
+ "setoption name UCI_Chess960 value true",
+ "bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w KQkq - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6",
+ "setoption name UCI_Chess960 value false"
};
} // namespace
-/// benchmark() runs a simple benchmark by letting Stockfish analyze a set
-/// of positions for a given limit each. There are five parameters: the
-/// transposition table size, the number of search threads that should
-/// be used, the limit value spent for each position (optional, default is
-/// depth 13), an optional file name where to look for positions in FEN
-/// format (defaults are the positions defined above) and the type of the
-/// limit value: depth (default), time in millisecs or number of nodes.
+/// setup_bench() builds a list of UCI commands to be run by bench. There
+/// are five parameters: TT size in MB, number of search threads that
+/// should be used, the limit value spent for each position, a file name
+/// where to look for positions in FEN format and the type of the limit:
+/// depth, perft, nodes and movetime (in millisecs).
+///
+/// bench -> search default positions up to depth 13
+/// bench 64 1 15 -> search default positions up to depth 15 (TT = 64MB)
+/// bench 64 4 5000 current movetime -> search current position with 4 threads for 5 sec
+/// bench 64 1 100000 default nodes -> search default positions for 100K nodes each
+/// bench 16 1 5 default perft -> run a perft 5 on default positions
-void benchmark(const Position& current, istream& is) {
+vector setup_bench(const Position& current, istream& is) {
- string token;
- vector fens;
- Search::LimitsType limits;
+ vector fens, list;
+ string go, token;
// Assign default values to missing arguments
string ttSize = (is >> token) ? token : "16";
@@ -109,21 +113,7 @@ void benchmark(const Position& current, istream& is) {
string fenFile = (is >> token) ? token : "default";
string limitType = (is >> token) ? token : "depth";
- Options["Hash"] = ttSize;
- Options["Threads"] = threads;
- Search::clear();
-
- if (limitType == "time")
- limits.movetime = stoi(limit); // movetime is in millisecs
-
- else if (limitType == "nodes")
- limits.nodes = stoi(limit);
-
- else if (limitType == "mate")
- limits.mate = stoi(limit);
-
- else
- limits.depth = stoi(limit);
+ go = "go " + limitType + " " + limit;
if (fenFile == "default")
fens = Defaults;
@@ -139,7 +129,7 @@ void benchmark(const Position& current, istream& is) {
if (!file.is_open())
{
cerr << "Unable to open file " << fenFile << endl;
- return;
+ exit(EXIT_FAILURE);
}
while (getline(file, fen))
@@ -149,35 +139,18 @@ void benchmark(const Position& current, istream& is) {
file.close();
}
- uint64_t nodes = 0;
- TimePoint elapsed = now();
- Position pos;
-
- for (size_t i = 0; i < fens.size(); ++i)
- {
- StateListPtr states(new std::deque(1));
- pos.set(fens[i], Options["UCI_Chess960"], &states->back(), Threads.main());
-
- cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
-
- if (limitType == "perft")
- nodes += Search::perft(pos, limits.depth * ONE_PLY);
+ list.emplace_back("ucinewgame");
+ list.emplace_back("setoption name Threads value " + threads);
+ list.emplace_back("setoption name Hash value " + ttSize);
+ for (const string& fen : fens)
+ if (fen.find("setoption") != string::npos)
+ list.emplace_back(fen);
else
{
- limits.startTime = now();
- Threads.start_thinking(pos, states, limits);
- Threads.main()->wait_for_search_finished();
- nodes += Threads.nodes_searched();
+ list.emplace_back("position fen " + fen);
+ list.emplace_back(go);
}
- }
-
- elapsed = now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero'
-
- dbg_print(); // Just before exiting
- cerr << "\n==========================="
- << "\nTotal time (ms) : " << elapsed
- << "\nNodes searched : " << nodes
- << "\nNodes/second : " << 1000 * nodes / elapsed << endl;
+ return list;
}
diff --git a/Engines/Linux64/stockfish/src/bitbase.cpp b/Engines/Linux64/stockfish/src/bitbase.cpp
index 4170952..3c9bf6e 100644
--- a/Engines/Linux64/stockfish/src/bitbase.cpp
+++ b/Engines/Linux64/stockfish/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-2018 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
@@ -111,13 +111,13 @@ namespace {
ksq[WHITE] = Square((idx >> 0) & 0x3F);
ksq[BLACK] = Square((idx >> 6) & 0x3F);
us = Color ((idx >> 12) & 0x01);
- psq = make_square(File((idx >> 13) & 0x3), RANK_7 - Rank((idx >> 15) & 0x7));
+ psq = make_square(File((idx >> 13) & 0x3), Rank(RANK_7 - ((idx >> 15) & 0x7)));
// Check if two pieces are on the same square or if a king can be captured
if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
|| ksq[WHITE] == psq
|| ksq[BLACK] == psq
- || (us == WHITE && (StepAttacksBB[PAWN][psq] & ksq[BLACK])))
+ || (us == WHITE && (PawnAttacks[WHITE][psq] & ksq[BLACK])))
result = INVALID;
// Immediate win if a pawn can be promoted without getting captured
@@ -125,13 +125,13 @@ namespace {
&& rank_of(psq) == RANK_7
&& ksq[us] != psq + NORTH
&& ( distance(ksq[~us], psq + NORTH) > 1
- || (StepAttacksBB[KING][ksq[us]] & (psq + NORTH))))
+ || (PseudoAttacks[KING][ksq[us]] & (psq + NORTH))))
result = WIN;
// Immediate draw if it is a stalemate or a king captures undefended pawn
else if ( us == BLACK
- && ( !(StepAttacksBB[KING][ksq[us]] & ~(StepAttacksBB[KING][ksq[~us]] | StepAttacksBB[PAWN][psq]))
- || (StepAttacksBB[KING][ksq[us]] & psq & ~StepAttacksBB[KING][ksq[~us]])))
+ && ( !(PseudoAttacks[KING][ksq[us]] & ~(PseudoAttacks[KING][ksq[~us]] | PawnAttacks[~us][psq]))
+ || (PseudoAttacks[KING][ksq[us]] & psq & ~PseudoAttacks[KING][ksq[~us]])))
result = DRAW;
// Position will be classified later
@@ -157,7 +157,7 @@ namespace {
const Result Bad = (Us == WHITE ? DRAW : WIN);
Result r = INVALID;
- Bitboard b = StepAttacksBB[KING][ksq[Us]];
+ Bitboard b = PseudoAttacks[KING][ksq[Us]];
while (b)
r |= Us == WHITE ? db[index(Them, ksq[Them] , pop_lsb(&b), psq)]
diff --git a/Engines/Linux64/stockfish/src/bitboard.cpp b/Engines/Linux64/stockfish/src/bitboard.cpp
index e329ab5..ba00c78 100644
--- a/Engines/Linux64/stockfish/src/bitboard.cpp
+++ b/Engines/Linux64/stockfish/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-2018 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,29 +26,22 @@
uint8_t PopCnt16[1 << 16];
int SquareDistance[SQUARE_NB][SQUARE_NB];
-Bitboard RookMasks [SQUARE_NB];
-Bitboard RookMagics [SQUARE_NB];
-Bitboard* RookAttacks[SQUARE_NB];
-unsigned RookShifts [SQUARE_NB];
-
-Bitboard BishopMasks [SQUARE_NB];
-Bitboard BishopMagics [SQUARE_NB];
-Bitboard* BishopAttacks[SQUARE_NB];
-unsigned BishopShifts [SQUARE_NB];
-
Bitboard SquareBB[SQUARE_NB];
Bitboard FileBB[FILE_NB];
Bitboard RankBB[RANK_NB];
Bitboard AdjacentFilesBB[FILE_NB];
-Bitboard InFrontBB[COLOR_NB][RANK_NB];
-Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB];
+Bitboard ForwardRanksBB[COLOR_NB][RANK_NB];
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
Bitboard DistanceRingBB[SQUARE_NB][8];
-Bitboard ForwardBB[COLOR_NB][SQUARE_NB];
+Bitboard ForwardFileBB[COLOR_NB][SQUARE_NB];
Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
+Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
+
+Magic RookMagics[SQUARE_NB];
+Magic BishopMagics[SQUARE_NB];
namespace {
@@ -61,10 +54,7 @@ namespace {
Bitboard RookTable[0x19000]; // To store rook attacks
Bitboard BishopTable[0x1480]; // To store bishop attacks
- typedef unsigned (Fn)(Square, Bitboard);
-
- void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[],
- Bitboard masks[], unsigned shifts[], Square deltas[], Fn index);
+ void init_magics(Bitboard table[], Magic magics[], Direction directions[]);
// bsf_index() returns the index into BSFTable[] to look up the bitscan. Uses
// Matt Taylor's folding for 32 bit case, extended to 64 bit by Kim Walisch.
@@ -173,14 +163,14 @@ void Bitboards::init() {
AdjacentFilesBB[f] = (f > FILE_A ? FileBB[f - 1] : 0) | (f < FILE_H ? FileBB[f + 1] : 0);
for (Rank r = RANK_1; r < RANK_8; ++r)
- InFrontBB[WHITE][r] = ~(InFrontBB[BLACK][r + 1] = InFrontBB[BLACK][r] | RankBB[r]);
+ ForwardRanksBB[WHITE][r] = ~(ForwardRanksBB[BLACK][r + 1] = ForwardRanksBB[BLACK][r] | RankBB[r]);
for (Color c = WHITE; c <= BLACK; ++c)
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
- ForwardBB[c][s] = InFrontBB[c][rank_of(s)] & FileBB[file_of(s)];
- PawnAttackSpan[c][s] = InFrontBB[c][rank_of(s)] & AdjacentFilesBB[file_of(s)];
- PassedPawnMask[c][s] = ForwardBB[c][s] | PawnAttackSpan[c][s];
+ ForwardFileBB [c][s] = ForwardRanksBB[c][rank_of(s)] & FileBB[file_of(s)];
+ PawnAttackSpan[c][s] = ForwardRanksBB[c][rank_of(s)] & AdjacentFilesBB[file_of(s)];
+ PassedPawnMask[c][s] = ForwardFileBB [c][s] | PawnAttackSpan[c][s];
}
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
@@ -191,39 +181,43 @@ void Bitboards::init() {
DistanceRingBB[s1][SquareDistance[s1][s2] - 1] |= s2;
}
- int steps[][9] = { {}, { 7, 9 }, { 17, 15, 10, 6, -6, -10, -15, -17 },
- {}, {}, {}, { 9, 7, -7, -9, 8, 1, -1, -8 } };
+ int steps[][5] = { {}, { 7, 9 }, { 6, 10, 15, 17 }, {}, {}, {}, { 1, 7, 8, 9 } };
for (Color c = WHITE; c <= BLACK; ++c)
- for (PieceType pt = PAWN; pt <= KING; ++pt)
+ for (PieceType pt : { PAWN, KNIGHT, KING })
for (Square s = SQ_A1; s <= SQ_H8; ++s)
for (int i = 0; steps[pt][i]; ++i)
{
- Square to = s + Square(c == WHITE ? steps[pt][i] : -steps[pt][i]);
+ Square to = s + Direction(c == WHITE ? steps[pt][i] : -steps[pt][i]);
if (is_ok(to) && distance(s, to) < 3)
- StepAttacksBB[make_piece(c, pt)][s] |= to;
+ {
+ if (pt == PAWN)
+ PawnAttacks[c][s] |= to;
+ else
+ PseudoAttacks[pt][s] |= to;
+ }
}
- Square RookDeltas[] = { NORTH, EAST, SOUTH, WEST };
- Square BishopDeltas[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
+ Direction RookDirections[] = { NORTH, EAST, SOUTH, WEST };
+ Direction BishopDirections[] = { 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);
+ init_magics(RookTable, RookMagics, RookDirections);
+ init_magics(BishopTable, BishopMagics, BishopDirections);
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
{
PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb(s1, 0);
PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0);
- for (Piece pc = W_BISHOP; pc <= W_ROOK; ++pc)
+ for (PieceType pt : { BISHOP, ROOK })
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
{
- if (!(PseudoAttacks[pc][s1] & s2))
+ if (!(PseudoAttacks[pt][s1] & s2))
continue;
- LineBB[s1][s2] = (attacks_bb(pc, s1, 0) & attacks_bb(pc, s2, 0)) | s1 | s2;
- BetweenBB[s1][s2] = attacks_bb(pc, s1, SquareBB[s2]) & attacks_bb(pc, s2, SquareBB[s1]);
+ LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2;
+ BetweenBB[s1][s2] = attacks_bb(pt, s1, SquareBB[s2]) & attacks_bb(pt, s2, SquareBB[s1]);
}
}
}
@@ -231,14 +225,14 @@ void Bitboards::init() {
namespace {
- Bitboard sliding_attack(Square deltas[], Square sq, Bitboard occupied) {
+ Bitboard sliding_attack(Direction directions[], Square sq, Bitboard occupied) {
Bitboard attack = 0;
for (int i = 0; i < 4; ++i)
- for (Square s = sq + deltas[i];
- is_ok(s) && distance(s, s - deltas[i]) == 1;
- s += deltas[i])
+ for (Square s = sq + directions[i];
+ is_ok(s) && distance(s, s - directions[i]) == 1;
+ s += directions[i])
{
attack |= s;
@@ -255,17 +249,14 @@ namespace {
// chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
// use the so called "fancy" approach.
- void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[],
- Bitboard masks[], unsigned shifts[], Square deltas[], Fn index) {
+ void init_magics(Bitboard table[], Magic magics[], Direction directions[]) {
+ // Optimal PRNG seeds to pick the correct magics in the shortest time
int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 },
{ 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } };
Bitboard occupancy[4096], reference[4096], edges, b;
- int age[4096] = {0}, current = 0, i, size;
-
- // attacks[s] is a pointer to the beginning of the attacks table for square 's'
- attacks[SQ_A1] = table;
+ int epoch[4096] = {}, cnt = 0, size = 0;
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
@@ -277,28 +268,28 @@ namespace {
// all the attacks for each possible subset of the mask and so is 2 power
// the number of 1s of the mask. Hence we deduce the size of the shift to
// apply to the 64 or 32 bits word to get the index.
- masks[s] = sliding_attack(deltas, s, 0) & ~edges;
- shifts[s] = (Is64Bit ? 64 : 32) - popcount(masks[s]);
+ Magic& m = magics[s];
+ m.mask = sliding_attack(directions, s, 0) & ~edges;
+ m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
+
+ // Set the offset for the attacks table of the square. We have individual
+ // table sizes for each square with "Fancy Magic Bitboards".
+ m.attacks = s == SQ_A1 ? table : magics[s - 1].attacks + size;
// Use Carry-Rippler trick to enumerate all subsets of masks[s] and
// store the corresponding sliding attack bitboard in reference[].
b = size = 0;
do {
occupancy[size] = b;
- reference[size] = sliding_attack(deltas, s, b);
+ reference[size] = sliding_attack(directions, s, b);
if (HasPext)
- attacks[s][pext(b, masks[s])] = reference[size];
+ m.attacks[pext(b, m.mask)] = reference[size];
size++;
- b = (b - masks[s]) & masks[s];
+ b = (b - m.mask) & m.mask;
} while (b);
- // Set the offset for the table of the next square. We have individual
- // table sizes for each square with "Fancy Magic Bitboards".
- if (s < SQ_H8)
- attacks[s + 1] = attacks[s] + size;
-
if (HasPext)
continue;
@@ -306,28 +297,30 @@ namespace {
// Find a magic for square 's' picking up an (almost) random number
// until we find the one that passes the verification test.
- do {
- do
- magics[s] = rng.sparse_rand();
- while (popcount((magics[s] * masks[s]) >> 56) < 6);
+ for (int i = 0; i < size; )
+ {
+ for (m.magic = 0; popcount((m.magic * m.mask) >> 56) < 6; )
+ m.magic = rng.sparse_rand();
// A good magic must map every possible occupancy to an index that
// looks up the correct sliding attack in the attacks[s] database.
// Note that we build up the database for square 's' as a side
- // effect of verifying the magic.
- for (++current, i = 0; i < size; ++i)
+ // effect of verifying the magic. Keep track of the attempt count
+ // and save it in epoch[], little speed-up trick to avoid resetting
+ // m.attacks[] after every failed attempt.
+ for (++cnt, i = 0; i < size; ++i)
{
- unsigned idx = index(s, occupancy[i]);
+ unsigned idx = m.index(occupancy[i]);
- if (age[idx] < current)
+ if (epoch[idx] < cnt)
{
- age[idx] = current;
- attacks[s][idx] = reference[i];
+ epoch[idx] = cnt;
+ m.attacks[idx] = reference[i];
}
- else if (attacks[s][idx] != reference[i])
+ else if (m.attacks[idx] != reference[i])
break;
}
- } while (i < size);
+ }
}
}
}
diff --git a/Engines/Linux64/stockfish/src/bitboard.h b/Engines/Linux64/stockfish/src/bitboard.h
index 715f6c4..c9f7242 100644
--- a/Engines/Linux64/stockfish/src/bitboard.h
+++ b/Engines/Linux64/stockfish/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-2018 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
@@ -39,6 +39,7 @@ const std::string pretty(Bitboard b);
}
+const Bitboard AllSquares = ~Bitboard(0);
const Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL;
const Bitboard FileABB = 0x0101010101010101ULL;
@@ -65,15 +66,41 @@ extern Bitboard SquareBB[SQUARE_NB];
extern Bitboard FileBB[FILE_NB];
extern Bitboard RankBB[RANK_NB];
extern Bitboard AdjacentFilesBB[FILE_NB];
-extern Bitboard InFrontBB[COLOR_NB][RANK_NB];
-extern Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB];
+extern Bitboard ForwardRanksBB[COLOR_NB][RANK_NB];
extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
extern Bitboard DistanceRingBB[SQUARE_NB][8];
-extern Bitboard ForwardBB[COLOR_NB][SQUARE_NB];
+extern Bitboard ForwardFileBB[COLOR_NB][SQUARE_NB];
extern Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
extern Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
+extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
+
+
+/// Magic holds all magic bitboards relevant data for a single square
+struct Magic {
+ Bitboard mask;
+ Bitboard magic;
+ Bitboard* attacks;
+ unsigned shift;
+
+ // Compute the attack's index using the 'magic bitboards' approach
+ unsigned index(Bitboard occupied) const {
+
+ if (HasPext)
+ return unsigned(pext(occupied, mask));
+
+ if (Is64Bit)
+ return unsigned(((occupied & mask) * magic) >> shift);
+
+ unsigned lo = unsigned(occupied) & unsigned(mask);
+ unsigned hi = unsigned(occupied >> 32) & unsigned(mask >> 32);
+ return (lo * unsigned(magic) ^ hi * unsigned(magic >> 32)) >> shift;
+ }
+};
+
+extern Magic RookMagics[SQUARE_NB];
+extern Magic BishopMagics[SQUARE_NB];
/// Overloads of bitwise operators between a Bitboard and a Square for testing
@@ -99,11 +126,10 @@ inline Bitboard& operator^=(Bitboard& b, Square s) {
return b ^= SquareBB[s];
}
-inline bool more_than_one(Bitboard b) {
+constexpr bool more_than_one(Bitboard b) {
return b & (b - 1);
}
-
/// rank_bb() and file_bb() return a bitboard representing all the squares on
/// the given file or rank.
@@ -126,8 +152,8 @@ inline Bitboard file_bb(Square s) {
/// shift() moves a bitboard one step along direction D. Mainly for pawns
-template
-inline Bitboard shift(Bitboard b) {
+template
+constexpr 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
@@ -153,28 +179,28 @@ inline Bitboard between_bb(Square s1, Square s2) {
}
-/// in_front_bb() returns a bitboard representing all the squares on all the ranks
+/// forward_ranks_bb() returns a bitboard representing all the squares on all the ranks
/// in front of the given one, from the point of view of the given color. For
-/// instance, in_front_bb(BLACK, RANK_3) will return the squares on ranks 1 and 2.
+/// instance, forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2.
-inline Bitboard in_front_bb(Color c, Rank r) {
- return InFrontBB[c][r];
+inline Bitboard forward_ranks_bb(Color c, Square s) {
+ return ForwardRanksBB[c][rank_of(s)];
}
-/// forward_bb() returns a bitboard representing all the squares along the line
+/// forward_file_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)
+/// ForwardFileBB[c][s] = forward_ranks_bb(c, s) & file_bb(s)
-inline Bitboard forward_bb(Color c, Square s) {
- return ForwardBB[c][s];
+inline Bitboard forward_file_bb(Color c, Square s) {
+ return ForwardFileBB[c][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] = forward_ranks_bb(c, s) & adjacent_files_bb(file_of(s));
inline Bitboard pawn_attack_span(Color c, Square s) {
return PawnAttackSpan[c][s];
@@ -183,7 +209,7 @@ inline Bitboard pawn_attack_span(Color c, Square s) {
/// passed_pawn_mask() returns a bitboard mask which can be used to test if a
/// pawn of the given color and on the given square is a passed pawn:
-/// PassedPawnMask[c][s] = pawn_attack_span(c, s) | forward_bb(c, s)
+/// PassedPawnMask[c][s] = pawn_attack_span(c, s) | forward_file_bb(c, s)
inline Bitboard passed_pawn_mask(Color c, Square s) {
return PassedPawnMask[c][s];
@@ -210,50 +236,25 @@ template<> inline int distance(Square x, Square y) { return distance(rank_
/// attacks_bb() returns a bitboard representing all the squares attacked by a
-/// piece of type Pt (bishop or rook) placed on 's'. The helper magic_index()
-/// looks up the index using the 'magic bitboards' approach.
-template
-inline unsigned magic_index(Square s, Bitboard occupied) {
-
- extern Bitboard RookMasks[SQUARE_NB];
- extern Bitboard RookMagics[SQUARE_NB];
- extern unsigned RookShifts[SQUARE_NB];
- extern Bitboard BishopMasks[SQUARE_NB];
- extern Bitboard BishopMagics[SQUARE_NB];
- extern unsigned BishopShifts[SQUARE_NB];
-
- Bitboard* const Masks = Pt == ROOK ? RookMasks : BishopMasks;
- Bitboard* const Magics = Pt == ROOK ? RookMagics : BishopMagics;
- unsigned* const Shifts = Pt == ROOK ? RookShifts : BishopShifts;
-
- if (HasPext)
- return unsigned(pext(occupied, Masks[s]));
-
- if (Is64Bit)
- return unsigned(((occupied & Masks[s]) * Magics[s]) >> Shifts[s]);
-
- unsigned lo = unsigned(occupied) & unsigned(Masks[s]);
- unsigned hi = unsigned(occupied >> 32) & unsigned(Masks[s] >> 32);
- return (lo * unsigned(Magics[s]) ^ hi * unsigned(Magics[s] >> 32)) >> Shifts[s];
-}
+/// piece of type Pt (bishop or rook) placed on 's'.
template
inline Bitboard attacks_bb(Square s, Bitboard occupied) {
- extern Bitboard* RookAttacks[SQUARE_NB];
- extern Bitboard* BishopAttacks[SQUARE_NB];
-
- return (Pt == ROOK ? RookAttacks : BishopAttacks)[s][magic_index(s, occupied)];
+ const Magic& m = Pt == ROOK ? RookMagics[s] : BishopMagics[s];
+ return m.attacks[m.index(occupied)];
}
-inline Bitboard attacks_bb(Piece pc, Square s, Bitboard occupied) {
+inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) {
+
+ assert(pt != PAWN);
- switch (type_of(pc))
+ switch (pt)
{
case BISHOP: return attacks_bb(s, occupied);
- case ROOK : return attacks_bb(s, occupied);
+ case ROOK : return attacks_bb< ROOK>(s, occupied);
case QUEEN : return attacks_bb(s, occupied) | attacks_bb(s, occupied);
- default : return StepAttacksBB[pc][s];
+ default : return PseudoAttacks[pt][s];
}
}
@@ -291,7 +292,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/Linux64/stockfish/src/endgame.cpp b/Engines/Linux64/stockfish/src/endgame.cpp
index cbca34b..39db219 100644
--- a/Engines/Linux64/stockfish/src/endgame.cpp
+++ b/Engines/Linux64/stockfish/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-2018 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
@@ -130,13 +110,6 @@ Endgames::Endgames() {
}
-template