diff --git a/Code/AnalisisIndexes.py b/Code/AnalisisIndexes.py index d3334ba..9863f10 100644 --- a/Code/AnalisisIndexes.py +++ b/Code/AnalisisIndexes.py @@ -368,7 +368,7 @@ def genIndexes(partida, elos, elosFORM, alm): # for std, tit in ((Partida.OPENING, _("Opening")), (Partida.MIDDLEGAME, _("Middle game")), (Partida.ENDGAME, _("End game"))): # if elos[None][std]: # txt += plantillaC % ( tit, int(elos[True][std]), int(elos[False][std]), int(elos[None][std])) - # + # txt += plantillaC % ("Elo WITH FORMULA", elosFORM[True][Partida.ALLGAME], elosFORM[False][Partida.ALLGAME], elosFORM[None][Partida.ALLGAME]) # for std, tit in ((Partida.OPENING, _("Opening")), (Partida.MIDDLEGAME, _("Middle game")), (Partida.ENDGAME, _("End game"))): # if elos[None][std]: diff --git a/Code/Books.py b/Code/Books.py index d72fe83..9393920 100644 --- a/Code/Books.py +++ b/Code/Books.py @@ -54,6 +54,12 @@ def porDefecto(self, book=None): return book return self.lista[0] + def buscaLibro(self, nombre): + for book in self.lista: + if book.nombre == nombre: + return book + return None + def cambiaModo(self, apli): if apli in self._modoAnalisis: self._modoAnalisis = self._modoAnalisis.replace(apli, "") @@ -231,7 +237,6 @@ def almListaJugadas(self, fen): return listaJugadas - def eligeJugadaTipo(self, fen, tipo): maxim = 0 liMax = [] @@ -276,7 +281,7 @@ def eligeJugadaTipo(self, fen, tipo): return pv.lower() - def miraListaPV(self, fen, siMax): + def miraListaPV(self, fen, siMax, onlyone=True): li = self.book.lista(self.path, fen) liResp = [] @@ -287,8 +292,8 @@ def miraListaPV(self, fen, siMax): if w > maxim: maxim = w liResp = [entry.pv()] - # elif w == maxim: - # liResp.append(entry.pv()) + elif w == maxim and not onlyone: + liResp.append(entry.pv()) else: for entry in li: liResp.append(entry.pv()) diff --git a/Code/Configuracion.py b/Code/Configuracion.py index ca2dee8..90ed3b6 100644 --- a/Code/Configuracion.py +++ b/Code/Configuracion.py @@ -792,7 +792,6 @@ def lee(self): if not os.path.isdir(self.folderOpenings): self.folderOpenings = self.folderBaseOpenings - for k in dic.keys(): if k.startswith("RIVAL_"): claveK = k[6:] diff --git a/Code/ControlPosicion.py b/Code/ControlPosicion.py index 42eb2aa..eebfb4e 100644 --- a/Code/ControlPosicion.py +++ b/Code/ControlPosicion.py @@ -345,6 +345,24 @@ def siFaltaMaterial(self): return False + def siFaltaMaterialColor(self, siBlancas): + piezas = "" + nb = "nb" + prq = "prq" + if siBlancas: + nb = nb.upper() + prq = prq.upper() + for v in self.casillas.itervalues(): + if v: + if v in prq: + return False + if v in nb: + if piezas: + return False + else: + piezas = v + return False + def numPiezas(self, pieza): if not self.siBlancas: pieza = pieza.lower() @@ -435,5 +453,58 @@ def siPeonCoronando(self, desdeA1H8, hastaA1H8): return True + def aura(self): + lista = [] + + def add(lipos): + for pos in lipos: + lista.append(LCEngine.posA1(pos)) + + def liBR(npos, fi, ci): + fil, col = LCEngine.posFC(npos) + liM = [] + ft = fil + fi + ct = col + ci + while True: + if ft < 0 or ft > 7 or ct < 0 or ct > 7: + break + t = LCEngine.FCpos(ft, ct) + liM.append(t) + + pz = self.casillas[LCEngine.posA1(t)] + if pz: + break + ft += fi + ct += ci + add(liM) + + pzs = "KQRBNP" if self.siBlancas else "kqrbnp" + + for i in range(8): + for j in range(8): + a1 = chr(i + 97) + chr(j + 49) + pz = self.casillas[a1] + if pz and pz in pzs: + pz = pz.upper() + npos = LCEngine.a1Pos(a1) + if pz == "K": + add(LCEngine.liK(npos)) + elif pz == "Q": + for f_i, c_i in ((1, 1), (1, -1), (-1, 1), (-1, -1), (1, 0), (-1, 0), (0, 1), (0, -1)): + liBR(npos, f_i, c_i) + elif pz == "R": + for f_i, c_i in ((1, 0), (-1, 0), (0, 1), (0, -1)): + liBR(npos, f_i, c_i) + elif pz == "B": + for f_i, c_i in ((1, 1), (1, -1), (-1, 1), (-1, -1)): + liBR(npos, f_i, c_i) + elif pz == "N": + add(LCEngine.liN(npos)) + elif pz == "P": + lim, lix = LCEngine.liP(npos, self.siBlancas) + add(lix) + return lista + + 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/EngineThread.py b/Code/EngineThread.py index ab301d9..724a1f1 100644 --- a/Code/EngineThread.py +++ b/Code/EngineThread.py @@ -10,7 +10,8 @@ DEBUG_ENGINE = False -def xpr(line): + +def xpr(exe, line): if DEBUG_ENGINE: t = time.time() prlk("%0.04f %s" % (t - tdbg[0], line)) @@ -29,7 +30,7 @@ def xprli(li): if DEBUG_ENGINE: tdbg = [time.time()] - xpr("DEBUG XMOTOR") + xpr("", "DEBUG XMOTOR") class Priorities: @@ -87,7 +88,7 @@ def cerrar(self): self.working = False def put_line(self, line): - assert xpr("put>>> %s\n" % line) + assert xpr(self.exe, "put>>> %s\n" % line) self.stdin_lock.acquire() self.stdin.write(line + "\n") self.stdin_lock.release() @@ -109,7 +110,7 @@ def xstdout_thread(self, stdout, lock): try: while self.working: line = stdout.readline() - assert xpr(line) + assert xpr(self.exe, line) if not line: break lock.acquire() diff --git a/Code/EnginesWindows.py b/Code/EnginesWindows.py index 8c579e1..ec7defd 100644 --- a/Code/EnginesWindows.py +++ b/Code/EnginesWindows.py @@ -137,7 +137,7 @@ def mas(cm): cm.ponMultiPV(1, 4) mas(cm) - cm = ConfigMotor("cheng", "Martin Sedlák", "4 0.39", "http://www.vlasak.biz/cheng") + cm = ConfigMotor("cheng", "Martin Sedlák".decode("utf-8"), "4 0.39", "http://www.vlasak.biz/cheng") cm.path = "cheng4.exe" cm.elo = 2750 cm.ponMultiPV(20, 256) @@ -200,7 +200,7 @@ def mas(cm): cm.ponMultiPV(20, 100) mas(cm) - cm = ConfigMotor("texel", "Peter Österlund", "1.07 32bit", "http://hem.bredband.net/petero2b/javachess/index.html#texel") + cm = ConfigMotor("texel", "Peter Österlund".decode("utf-8"), "1.07 32bit", "http://hem.bredband.net/petero2b/javachess/index.html#texel") cm.path = "texel32old.exe" cm.elo = 3100 cm.ordenUCI("Hash", "32") @@ -288,7 +288,7 @@ def mas(cm): cm.elo = 2100 mas(cm) - cm = ConfigMotor("andscacs", "Daniel José Queraltó", "0.9032n", "http://www.andscacs.com/") + cm = ConfigMotor("andscacs", "Daniel José Queraltó".decode("utf-8"), "0.9032n", "http://www.andscacs.com/") cm.path = "andscacs32.exe" cm.elo = 3150 mas(cm) @@ -308,12 +308,12 @@ def mas(cm): cm.elo = 2627 mas(cm) - cm = ConfigMotor("spike", "Volker Böhm and Ralf Schäfer", "1.4", "http://spike.lazypics.de/index_en.html") + cm = ConfigMotor("spike", "Volker Böhm and Ralf Schäfer".decode("utf-8"), "1.4", "http://spike.lazypics.de/index_en.html") cm.path = "Spike1.4.exe" cm.elo = 2921 mas(cm) - cm = ConfigMotor("zappa", "Anthony Cozzie", "1.1", "http://www.acoz.net/zappa/") + cm = ConfigMotor("zappa", "Anthony Cozzie", "1.1", "http://www.acoz.net/zappa/") cm.path = "zappa.exe" cm.elo = 2581 cm.removeLog("zappa_log.txt") diff --git a/Code/Entrenamientos.py b/Code/Entrenamientos.py index 9cb6e51..fab613c 100644 --- a/Code/Entrenamientos.py +++ b/Code/Entrenamientos.py @@ -140,7 +140,6 @@ def xopcion(menu, clave, texto, icono, siDeshabilitado=False): xopcion(menu, "wgm", _("Play like a Woman Grandmaster"), Iconos.WGranMaestro()) menu.separador() - # Mate -------------------------------------------------------------------------------------------------- menu1 = menu.submenu(_("Training mates"), Iconos.Mate()) for mate in range(1, 5): @@ -190,7 +189,6 @@ def menuTacticas(submenu, tipo, carpetaBase, lista): menuTacticas(submenu1, tipo, carpeta, lista) return lista - menuTacticas(menu1, "B", "Tactics", []) lista = [] carpetaTacticasP = os.path.join(self.configuracion.dirPersonalTraining, "Tactics") @@ -718,4 +716,4 @@ def xopcion(menu, clave, texto, icono, siDeshabilitado=False): td.reduce() td.menu(menu, xopcion) resp = menu.lanza() - return resp if resp is None else resp[3:] \ No newline at end of file + return resp if resp is None else resp[3:] diff --git a/Code/Gestor.py b/Code/Gestor.py index 2c1717d..c27dbd6 100644 --- a/Code/Gestor.py +++ b/Code/Gestor.py @@ -9,6 +9,7 @@ from Code import AnalisisIndexes from Code import AperturasStd from Code import ControlPGN +from Code import ControlPosicion from Code import DGT from Code import Jugada from Code import Partida @@ -28,6 +29,7 @@ from Code.QT import QTUtil2 from Code.QT import QTVarios from Code.QT import WOpeningGuide +from Code.QT import TabTipos from Code import Util from Code import VarGen from Code import Kibitzers @@ -285,11 +287,12 @@ def showCandidates(): if not self.configuracion.siAtajosRaton: if li_destinos: self.atajosRatonOrigen = a1h8 - if self.atajosRatonDestino and self.atajosRatonDestino in li_destinos: - mueve() - else: - self.atajosRatonDestino = None - showCandidates() + self.atajosRatonDestino = None + # if self.atajosRatonDestino and self.atajosRatonDestino in li_destinos: + # mueve() + # else: + # self.atajosRatonDestino = None + showCandidates() return elif li_origenes: self.atajosRatonDestino = a1h8 @@ -297,6 +300,7 @@ def showCandidates(): mueve() else: self.atajosRatonOrigen = None + self.atajosRatonDestino = None showCandidates() return @@ -520,6 +524,8 @@ def miraKibitzers(self, jg, columnaClave, soloNuevo=False): def paraKibitzers(self): for n, xkibitzer in enumerate(self.liKibitzersActivas): xkibitzer.terminar() #ponFen(None) + self.procesador.quitaKibitzers() + self.liKibitzersActivas = [] def ponPiezasAbajo(self, siBlancas): self.tablero.ponerPiezasAbajo(siBlancas) @@ -829,7 +835,6 @@ def gridRightMouse(self, siShift, siControl, siAlt): self.pgnInformacion() self.pantalla.ajustaTam() - def listado(self, tipo): if tipo == "pgn": return self.pgn.actual() @@ -899,7 +904,7 @@ def cambioTutor(self): self.siAnalizadoTutor = False if self.tipoJuego == kJugEntMaq: - self.analizaTutorInicio() + self.analizaInicio() def siTerminada(self): return self.partida.ultPosicion.siTerminada() @@ -1054,6 +1059,44 @@ def exePulsadoNum(self, siActivar, numero): if self.tablero.flechaSC: self.tablero.flechaSC.show() + elif numero in [2, 7]: + if siActivar: + # Que jugada esta en el tablero + fen = self.fenActivoConInicio() + siBlancas = " w " in fen + if numero == 2: + siMB = siBlancas + else: + siMB = not siBlancas + if siMB != siBlancas: + fen = LCEngine.fenOB(fen) + cp = ControlPosicion.ControlPosicion() + cp.leeFen(fen) + liMovs = cp.aura() + + self.liMarcosTmp = [] + regMarco = TabTipos.Marco() + color = self.tablero.confTablero.flechaActivoDefecto().colorinterior + if color == -1: + color = self.tablero.confTablero.flechaActivoDefecto().color + + st = set() + for h8 in liMovs: + if h8 not in st: + regMarco.a1h8 = h8 + h8 + regMarco.siMovible = True + regMarco.color = color + regMarco.colorinterior = color + regMarco.opacidad = 0.5 + marco = self.tablero.creaMarco(regMarco) + self.liMarcosTmp.append(marco) + st.add(h8) + + else: + for marco in self.liMarcosTmp: + self.tablero.xremoveItem(marco) + self.liMarcosTmp = [] + def exePulsadaLetra(self, siActivar, letra): if siActivar: dic = { 'a':kMoverInicio, @@ -1296,7 +1339,6 @@ def configurar(self, liMasOpciones=None, siCambioTutor=False, siSonidos=False, s modoPosicionBlind = True self.tablero.blindfoldChange(modoPosicionBlind) - elif orden == "conf": self.tablero.blindfoldConfig() @@ -1505,6 +1547,11 @@ def utilidades(self, liMasOpciones=None, siArbol=True): return None + def mensajeEnPGN(self, mens, titulo=None): + p0 = self.pantalla.base.pgn.pos() + p = self.pantalla.mapToGlobal(p0) + QTUtil2.mensajeEnPunto(self.pantalla, mens, titulo, p) + def showAnalisis(self): um = self.procesador.unMomento() elos = self.partida.calc_elos(self.configuracion) diff --git a/Code/GestorAlbum.py b/Code/GestorAlbum.py index b3ed1c1..0e18186 100644 --- a/Code/GestorAlbum.py +++ b/Code/GestorAlbum.py @@ -283,7 +283,7 @@ def ponResultado(self, quien): self.resultado = kTablas self.guardarGanados(quien == kGanamos) - QTUtil2.mensaje(self.pantalla, mensaje) + self.mensajeEnPGN(mensaje) self.ponFinJuego() self.xrival.cerrar() self.pantalla.ponToolBar((k_mainmenu, k_configurar, k_utilidades)) diff --git a/Code/GestorBooks.py b/Code/GestorBooks.py index 77edaa9..f90398d 100644 --- a/Code/GestorBooks.py +++ b/Code/GestorBooks.py @@ -3,7 +3,6 @@ from Code import Gestor from Code import Jugada from Code.QT import PantallaBooks -from Code.QT import QTUtil2 from Code import XMotorRespuesta from Code.Constantes import * @@ -411,5 +410,4 @@ def ponResultado(self): txt = self.txtAciertos() mensaje = "%s\n%s\n" % (_("Line completed"), txt) - - QTUtil2.mensaje(self.pantalla, mensaje) + self.mensajeEnPGN(mensaje) diff --git a/Code/GestorCompeticion.py b/Code/GestorCompeticion.py index 5c3a09c..6dd88e0 100644 --- a/Code/GestorCompeticion.py +++ b/Code/GestorCompeticion.py @@ -418,5 +418,5 @@ def ponResultado(self, quien): self.resultado = kTablas self.guardarGanados(quien == kGanamos) - QTUtil2.mensaje(self.pantalla, mensaje) + self.mensajeEnPGN(mensaje) self.ponFinJuego() diff --git a/Code/GestorElo.py b/Code/GestorElo.py index a0d4712..dceaa25 100644 --- a/Code/GestorElo.py +++ b/Code/GestorElo.py @@ -619,9 +619,9 @@ def ponResultado(self, quien): # mensaje = _X( _("Congratulations, you win against %1 on time."), nombreContrario ) # self.resultado = kGanamos - elif quien == kGanaRivalTiempo: - mensaje = _X(_("%1 has won on time."), nombreContrario) - self.resultado = kGanaRival + # elif quien == kGanaRivalTiempo: + # mensaje = _X(_("%1 has won on time."), nombreContrario) + # self.resultado = kGanaRival elo = self.configuracion.eloActivo(self.siCompetitivo) if self.resultado == kGanamos: @@ -646,7 +646,7 @@ def ponResultado(self, quien): mensaje += "

%s : %d
" % (_("New Lucas-Elo"), self.configuracion.eloActivo(self.siCompetitivo)) self.guardarGanados(quien == kGanamos) - QTUtil2.mensaje(self.pantalla, mensaje) + self.mensajeEnPGN(mensaje) self.ponFinJuego() # def ponFinJuego( self ): diff --git a/Code/GestorEntMaq.py b/Code/GestorEntMaq.py index 2602bb7..9c11a92 100644 --- a/Code/GestorEntMaq.py +++ b/Code/GestorEntMaq.py @@ -659,7 +659,6 @@ def juegaHumano(self, siBlancas): self.timekeeper.start() self.activaColor(siBlancas) - def juegaRival(self): self.pensando(True) self.desactivaTodas() @@ -1031,18 +1030,22 @@ def ponResultado(self, quien): self.resultado = kTablas elif quien == kGanamosTiempo: + if self.partida.ultPosicion.siFaltaMaterialColor(self.siJugamosConBlancas): + return self.ponResultado(kTablasFaltaMaterial) mensaje = _X(_("Congratulations, you win %1 on time."), nombreContrario) self.resultado = kGanamos self.partida.last_jg().comentario = _X(_("%1 has won on time."), self.configuracion.jugador) elif quien == kGanaRivalTiempo: + if self.partida.ultPosicion.siFaltaMaterialColor(not self.siJugamosConBlancas): + return self.ponResultado(kTablasFaltaMaterial) mensaje = _X(_("%1 has won on time."), nombreContrario) self.resultado = kGanaRival self.partida.last_jg().comentario = _X(_("%1 has won on time."), nombreContrario) self.guardarGanados(quien == kGanamos) if quien != kGanaRivalTiempo: # Ya que el mensaje ya se ha usado, para a_adir minutos - QTUtil2.mensaje(self.pantalla, mensaje) + self.mensajeEnPGN(mensaje) if QTUtil2.pregunta(self.pantalla, _("Do you want to play again?")): self.reiniciar(False) else: diff --git a/Code/GestorEntPos.py b/Code/GestorEntPos.py index 5e06db9..2acb5e2 100644 --- a/Code/GestorEntPos.py +++ b/Code/GestorEntPos.py @@ -35,7 +35,7 @@ def guardaPosicion(self, posEntreno): db[self.entreno] = data db.close() - def inicio(self, posEntreno, numEntrenos, titEntreno, liEntrenos, siTutorActivado=None, jump=False): + def inicio(self, posEntreno, numEntrenos, titEntreno, liEntrenos, siTutorActivado=None, saltoAutomatico=False): if hasattr(self, "reiniciando"): if self.reiniciando: return @@ -49,7 +49,7 @@ def inicio(self, posEntreno, numEntrenos, titEntreno, liEntrenos, siTutorActivad self.numEntrenos = numEntrenos self.titEntreno = titEntreno self.liEntrenos = liEntrenos - self.jump = jump + self.saltoAutomatico = saltoAutomatico self.liHistorico = [self.posEntreno] @@ -238,7 +238,7 @@ def procesarAccion(self, clave): def reiniciar(self): if self.rivalPensando: return - self.inicio(self.posEntreno, self.numEntrenos, self.titEntreno, self.liEntrenos, self.siTutorActivado, self.jump) + self.inicio(self.posEntreno, self.numEntrenos, self.titEntreno, self.liEntrenos, self.siTutorActivado, self.saltoAutomatico) def ent_siguiente(self, tipo): if not (self.siJuegaHumano or self.estado == kFinJuego): @@ -248,7 +248,7 @@ def ent_siguiente(self, tipo): pos = 1 elif pos == 0: pos = self.numEntrenos - self.inicio(pos, self.numEntrenos, self.titEntreno, self.liEntrenos, self.siTutorActivado, self.jump) + self.inicio(pos, self.numEntrenos, self.titEntreno, self.liEntrenos, self.siTutorActivado, self.saltoAutomatico) def controlTeclado(self, nkey): if nkey in (Qt.Key_Plus, Qt.Key_PageDown): @@ -287,7 +287,7 @@ def atras(self): def siguienteJugada(self): if self.estado == kFinJuego: - if self.siDirigido and self.jump: + if self.siDirigido and self.saltoAutomatico: self.ent_siguiente(k_siguiente) return @@ -396,7 +396,7 @@ def sigue(self): def lineaTerminadaOpciones(self): self.estado = kFinJuego - if self.jump: + if self.saltoAutomatico: self.ent_siguiente(k_siguiente) return False else: @@ -719,9 +719,7 @@ def createTactics(self): Util.dic8ini(nomIni, dicIni) - QTUtil2.mensaje(self.pantalla, _X(_("Tactic training %1 created."), nomDir) + "
" + - _X(_( - "You can access this training from menu Trainings-Learn tactics by repetition-%1"), - nomDir)) + self.mensajeEnPGN(_X(_("Tactic training %1 created."), nomDir) + "
" + + _X(_("You can access this training from menu Trainings-Learn tactics by repetition-%1"), nomDir)) self.procesador.entrenamientos.rehaz() diff --git a/Code/GestorEverest.py b/Code/GestorEverest.py index 989288b..670c8bf 100644 --- a/Code/GestorEverest.py +++ b/Code/GestorEverest.py @@ -314,6 +314,6 @@ def ponResultado(self): mensaje = _("Congratulations you have passed this game.") self.expedition.add_try(True, self.tiempo, self.puntos) - QTUtil2.mensaje(self.pantalla, mensaje) + self.mensajeEnPGN(mensaje) self.terminar() diff --git a/Code/GestorFideFics.py b/Code/GestorFideFics.py index ee7ef5a..27f2dca 100644 --- a/Code/GestorFideFics.py +++ b/Code/GestorFideFics.py @@ -459,7 +459,7 @@ def ponResultado(self): mensaje += "

%s : %d
" % (self._newTitulo, self._activo(self.siCompetitivo)) - QTUtil2.mensaje(self.pantalla, mensaje) + self.mensajeEnPGN(mensaje) self.ponFinJuego() # def ponFinJuego( self ): diff --git a/Code/GestorGM.py b/Code/GestorGM.py index 218f87d..5d3be6d 100644 --- a/Code/GestorGM.py +++ b/Code/GestorGM.py @@ -419,7 +419,8 @@ def ponResultado(self): if self.siJuez: mensaje += "

%s = %+d
" % (_("Points accumulated"), self.puntos) - QTUtil2.mensaje(self.pantalla, mensaje, siResalta=False) + # QTUtil2.mensaje(self.pantalla, mensaje, siResalta=False) + self.mensajeEnPGN(mensaje) dbHisto = Util.DicSQL(self.configuracion.ficheroGMhisto) diff --git a/Code/GestorMate.py b/Code/GestorMate.py index 8f7a535..c2d1fdd 100644 --- a/Code/GestorMate.py +++ b/Code/GestorMate.py @@ -360,7 +360,7 @@ def siguienteMate(self): if siRecord: txt += "

%s

" % _("Congratulations you have achieved a new record in this block.") - QTUtil2.mensaje(self.pantalla, txt) + self.mensajeEnPGN(txt) self.finJuego() else: diff --git a/Code/GestorMateMap.py b/Code/GestorMateMap.py index 2d9d324..9ceb8e1 100644 --- a/Code/GestorMateMap.py +++ b/Code/GestorMateMap.py @@ -2,7 +2,6 @@ from Code import Gestor from Code import Jugada from Code.QT import QTUtil -from Code.QT import QTUtil2 from Code.Constantes import * @@ -244,7 +243,7 @@ def ponResultado(self, quien): mensaje = _("Congratulations you have won %s.") % self.workmap.nameAim() self.workmap.winAim(self.partida.pv()) - QTUtil2.mensaje(self.pantalla, mensaje) + self.mensajeEnPGN(mensaje) self.desactivaTodas() self.refresh() diff --git a/Code/GestorMicElo.py b/Code/GestorMicElo.py index cdf827a..a859337 100644 --- a/Code/GestorMicElo.py +++ b/Code/GestorMicElo.py @@ -208,7 +208,8 @@ def inicio(self, datosMotor, minutos, segundos, siCompetitivo, aplazamiento=None self.ponPosicionDGT() if not self.siJugamosConBlancas: - QTUtil2.mensaje(self.pantalla, "Press the continue button to start.") + mensaje = _("Press the continue button to start.") + self.mensajeEnPGN(mensaje) self.siguienteJugada() @@ -480,10 +481,14 @@ def ponResultado(self, quien): self.resultado = kTablas elif quien == kGanamosTiempo: + if self.partida.ultPosicion.siFaltaMaterialColor(self.siJugamosConBlancas): + return self.ponResultado(kTablasFaltaMaterial) mensaje = _X(_("Congratulations, you win against %1 on time."), nombreContrario) self.resultado = kGanamos elif quien == kGanaRivalTiempo: + if self.partida.ultPosicion.siFaltaMaterialColor(not self.siJugamosConBlancas): + return self.ponResultado(kTablasFaltaMaterial) mensaje = _X(_("%1 has won on time."), nombreContrario) self.resultado = kGanaRival @@ -524,7 +529,7 @@ def ponResultado(self, quien): self.guardarGanados(quien == kGanamos) self.puestoResultado = True - QTUtil2.mensaje(self.pantalla, mensaje) + self.mensajeEnPGN(mensaje) self.ponFinJuego() def historial(self, elo, nelo): diff --git a/Code/GestorOpeningLines.py b/Code/GestorOpeningLines.py index cfabcb9..59c7bb2 100644 --- a/Code/GestorOpeningLines.py +++ b/Code/GestorOpeningLines.py @@ -13,6 +13,375 @@ from Code.Constantes import * +class GestorOpeningEngines(Gestor.Gestor): + def inicio(self, pathFichero): + self.tablero.saveVisual() + self.pathFichero = pathFichero + dbop = OpeningLines.Opening(pathFichero) + self.tablero.dbVisual_setFichero(dbop.nomFichero) + self.reinicio(dbop) + + def reinicio(self, dbop): + self.dbop = dbop + self.dbop.open_cache_engines() + self.tipoJuego = kJugOpeningLines + + self.level = self.dbop.getconfig("ENG_LEVEL", 0) + self.numengine = self.dbop.getconfig("ENG_ENGINE", 0) + + self.trainingEngines = self.dbop.trainingEngines() + + liTimes = self.trainingEngines["TIMES"] + liEngines = self.trainingEngines["ENGINES"] + num_engines = len(liEngines) + if self.numengine >= num_engines: + self.level += 1 + self.numengine = 0 + self.dbop.setconfig("ENG_LEVEL", self.level) + self.dbop.setconfig("ENG_ENGINE", 0) + num_levels = len(liTimes) + if self.level >= num_levels: + if QTUtil2.pregunta(self.pantalla, "%s.\n%s" % (_("Training finished"), _("Do you want to reinit?"))): + self.dbop.setconfig("ENG_LEVEL", 0) + self.dbop.setconfig("ENG_ENGINE", 0) + self.reinicio(dbop) + return + + self.time = liTimes[self.level] + self.keyengine = liEngines[self.numengine] + + self.plies_mandatory = self.trainingEngines["MANDATORY"] + self.plies_control = self.trainingEngines["CONTROL"] + self.lost_points = self.trainingEngines["LOST_POINTS"] + + self.siJugamosConBlancas = self.trainingEngines["COLOR"] == "WHITE" + self.siRivalConBlancas = not self.siJugamosConBlancas + + self.siAprobado = False + + rival = self.configuracion.buscaRival(self.keyengine) + self.xrival = self.procesador.creaGestorMotor(rival, self.time, None) + self.xrival.siBlancas = self.siRivalConBlancas + + juez = self.configuracion.buscaRival(self.trainingEngines["ENGINE_CONTROL"]) + self.xjuez = self.procesador.creaGestorMotor(juez, int(self.trainingEngines["ENGINE_TIME"] * 1000), None) + self.xjuez.anulaMultiPV() + + self.li_info = [ + "%s: %d/%d - %s" % (_("Engine"), self.numengine+1, num_engines, self.xrival.nombre), + "%s: %d/%d - %0.1f\"" % (_("Level"), self.level + 1, num_levels, self.time / 1000.0), + ] + + self.dicFENm2 = self.trainingEngines["DICFENM2"] + + self.siAyuda = False + self.tablero.dbVisual_setShowAllways(False) + self.ayudas = 9999 # Para que analice sin problemas + + self.partida = Partida.Partida() + + self.pantalla.ponToolBar((k_mainmenu, k_abandonar, 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 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 + + if siRival: + self.desactivaTodas() + + if not self.runcontrol(): + if self.mueveRival(): + self.siguienteJugada() + + else: + self.activaColor(siBlancas) + self.siJuegaHumano = True + + def mueveRival(self): + si_obligatorio = self.partida.numJugadas() <= self.plies_mandatory + si_pensar = True + fenM2 = self.partida.ultPosicion.fenM2() + if si_obligatorio: + moves = self.dicFENm2.get(fenM2, set()) + nmoves = len(moves) + if nmoves == 0: + si_obligatorio = False + elif nmoves == 1: + move = list(moves)[0] + desde, hasta, coronacion = move[:2], move[2:4], move[4:] + si_pensar = False + + if si_pensar: + move = self.dbop.get_cache_engines(self.keyengine, self.time, fenM2) + if move is None: + rmRival = self.xrival.juegaPartida(self.partida) + move = rmRival.movimiento() + self.dbop.set_cache_engines(self.keyengine, self.time, fenM2, move) + desde, hasta, coronacion = move[:2], move[2:4], move[4:] + if si_obligatorio: + if move not in moves: + move = list(moves)[0] + desde, hasta, coronacion = move[:2], move[2:4], move[4:] + + 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 + + def mueveHumano(self, desde, hasta, coronacion=""): + jg = self.checkMueveHumano(desde, hasta, coronacion) + if not jg: + return False + + fenM2 = self.partida.ultPosicion.fenM2() + moves = self.dicFENm2.get(fenM2, []) + nmoves = len(moves) + if nmoves > 0: + if jg.movimiento() not in moves: + for move in moves: + self.tablero.creaFlechaMulti(move, False) + self.tablero.creaFlechaMulti(jg.movimiento(), True) + self.mensajeEnPGN(_("This is not the move in the opening lines, you must repeat the game")) + self.ponFinJuego() + return True + + self.movimientosPiezas(jg.liMovs) + + self.masJugada(jg, True) + self.siguienteJugada() + return True + + def masJugada(self, jg, siNuestra): + fenM2 = jg.posicionBase.fenM2() + if fenM2 in self.dicFENm2: + if jg.movimiento() in self.dicFENm2[fenM2]: + jg.criticaDirecta = "!" + 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 muestraInformacion(self): + li = [] + li.extend(self.li_info) + + si_obligatorio = self.partida.numJugadas() < self.plies_mandatory + if si_obligatorio and self.estado != kFinJuego: + fenM2 = self.partida.ultPosicion.fenM2() + moves = self.dicFENm2.get(fenM2, []) + if len(moves) > 0: + li.append( "%s: %d/%d" % (_("Mandatory move"), self.partida.numJugadas(), self.plies_mandatory)) + else: + si_obligatorio = False + + if not si_obligatorio and self.estado != kFinJuego: + tm = self.plies_mandatory + self.plies_control - self.partida.numJugadas() + if tm > 0: + li.append("%s: %d" % (_("Moves until the control"), tm)) + + self.ponRotulo1("
".join(li)) + + def runcontrol(self): + numJugadas = self.partida.numJugadas() + if numJugadas == 0: + return False + + def aprobado(): + mens = "%s" % _("Congratulations, goal achieved") + self.li_info.append("") + self.li_info.append(mens) + self.muestraInformacion() + self.dbop.setconfig("ENG_ENGINE", self.numengine + 1) + self.mensajeEnPGN(mens) + self.siAprobado = True + + def suspendido(): + mens = "%s" % _("You must repeat the game") + self.li_info.append("") + self.li_info.append(mens) + self.muestraInformacion() + self.mensajeEnPGN(mens) + + def calcula(fen): + um = self.unMomento() + mrm = self.xjuez.analiza(fen) + um.final() + rm = mrm.mejorMov() + return rm.puntosABS(), rm.mate + + if self.partida.siTerminada(): + self.ponFinJuego() + jg = self.partida.jugada(-1) + if jg.siJaqueMate: + if jg.siBlancas() == self.siJugamosConBlancas: + aprobado() + else: + suspendido() + self.ponFinJuego() + return True + puntosFinal, mateFinal = 0, 0 + + else: + if numJugadas < self.plies_mandatory + self.plies_control: + return False + # Si la ultima jugada es de la linea no se calcula nada + jg = self.partida.jugada(-1) + if jg.criticaDirecta == "!": + puntosFinal, mateFinal = 0, 0 + else: + puntosFinal, mateFinal = calcula(self.partida.ultPosicion.fen()) + puntosFinal, mateFinal = -puntosFinal, -mateFinal + + # Se marcan todas las jugadas que no siguen las lineas + # Y se busca la ultima del color del jugador + fenM2_inicial = None + for njg in range(numJugadas): + jg = self.partida.jugada(njg) + fenM2 = jg.posicionBase.fenM2() + if fenM2 in self.dicFENm2: + moves = self.dicFENm2[fenM2] + if jg.movimiento() not in moves: + jg.criticaDirecta = "?!" + if fenM2_inicial is None and jg.siBlancas() == self.siJugamosConBlancas: + fenM2_inicial = jg.posicion.fenM2() + elif fenM2_inicial is None and jg.siBlancas() == self.siJugamosConBlancas: + fenM2_inicial = jg.posicion.fenM2() + if fenM2_inicial: + puntosInicio, mateInicio = calcula(fenM2_inicial) + puntosInicio, mateInicio = -puntosInicio, -mateInicio + else: + puntosInicio, mateInicio = 0, 0 + + self.li_info.append("%s:" %_("Score")) + template = "    %s: %d" + def appendInfo(label, puntos, mate): + mens = template % (label, puntos) + if mate: + mens += " %s %d" % (_("Mate"), mate) + self.li_info.append(mens) + appendInfo(_("Start"), puntosInicio, mateInicio) + appendInfo(_("End"), puntosFinal, mateFinal) + perdidos = (puntosInicio-puntosFinal) + ok = perdidos < self.lost_points + mens = template % ("(%d)-(%d)" %(puntosInicio, puntosFinal), perdidos) + mens = "%s %s %d" %(mens, "<" if ok else ">", self.lost_points) + self.li_info.append(mens) + + if perdidos > self.lost_points: + suspendido() + else: + aprobado() + self.ponFinJuego() + return True + + def procesarAccion(self, clave): + if clave == k_mainmenu: + self.finPartida() + + elif clave in (k_reiniciar, k_siguiente): + self.reiniciar() + + elif clave == k_peliculaRepetir: + self.dbop.setconfig("ENG_ENGINE", self.numengine) + self.reiniciar() + + elif clave == k_abandonar: + self.ponFinJuego() + + elif clave == k_configurar: + self.configurar(siSonidos=True) + + elif clave == k_utilidades: + liMasOpciones = [] + liMasOpciones.append(("libros", _("Consult a book"), Iconos.Libros())) + if self.siAprobado: + liMasOpciones.append((None, None, None)) + liMasOpciones.append(("add_line", _("Add this line"), Iconos.OpeningLines())) + + resp = self.utilidades(liMasOpciones) + if resp == "libros": + self.librosConsulta(False) + elif resp == "add_line": + self.dbop.append(self.partida) + self.dbop.updateTrainingEngines() + + else: + Gestor.Gestor.rutinaAccionDef(self, clave) + + def finalX(self): + return self.finPartida() + + def finPartida(self): + self.dbop.close() + self.tablero.restoreVisual() + self.procesador.inicio() + self.procesador.openings() + return False + + def reiniciar(self): + self.reinicio(self.dbop) + + def ponFinJuego(self): + self.estado = kFinJuego + self.desactivaTodas() + liOpciones = [k_mainmenu] + if self.siAprobado: + liOpciones.append(k_siguiente) + liOpciones.append(k_peliculaRepetir) + else: + liOpciones.append(k_reiniciar) + liOpciones.append(k_configurar) + liOpciones.append(k_utilidades) + self.pantalla.ponToolBar(liOpciones) + + class GestorOpeningLines(Gestor.Gestor): def inicio(self, pathFichero, modo, num_linea): self.tablero.saveVisual() @@ -125,7 +494,6 @@ def muestraInformacion(self): mens3 += "\n %s" % dicNAGs[valoracion] self.ponRotulo3(mens3 if mens3 else None) - def partidaTerminada(self, siCompleta): self.estado = kFinJuego tm = time.time() - self.ini_time @@ -136,8 +504,8 @@ def partidaTerminada(self, siCompleta): li.append("%s: %d" % (_("Errors"), self.errores)) if siCompleta: - QTUtil2.mensaje(self.pantalla, "\n".join(li)) - + mensaje = "\n".join(li) + self.mensajeEnPGN(mensaje) dictry = { "DATE": Util.hoy(), "TIME": tm, @@ -194,7 +562,7 @@ def procesarAccion(self, clave): if clave == k_mainmenu: self.finPartida() - elif clave == k_reiniciar : + elif clave == k_reiniciar: self.reiniciar() elif clave == k_configurar: @@ -357,6 +725,7 @@ def reinicio(self, dbop): ] self.siAyuda = False + self.siSaltoAutomatico = True cp = ControlPosicion.ControlPosicion() cp.leeFen(self.trposition["FENM2"] + " 0 1") @@ -368,7 +737,7 @@ def reinicio(self, dbop): self.siJugamosConBlancas = self.training["COLOR"] == "WHITE" self.siRivalConBlancas = not self.siJugamosConBlancas - self.pantalla.ponToolBar((k_mainmenu, k_ayuda, k_reiniciar)) + self.pantalla.ponToolBar((k_mainmenu, k_ayuda, k_configurar)) self.pantalla.activaJuego(True, False, siAyudas=False) self.ponMensajero(self.mueveHumano) self.ponPosicion(cp) @@ -392,7 +761,7 @@ def reinicio(self, dbop): def ayuda(self): self.siAyuda = True - self.pantalla.ponToolBar((k_mainmenu, k_reiniciar)) + self.pantalla.ponToolBar((k_mainmenu, k_configurar)) self.muestraAyuda() self.muestraInformacion() @@ -419,13 +788,17 @@ def muestraInformacion(self): 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) + siSalta = self.siSaltoAutomatico and self.errores == 0 and self.siAyuda == False + + if not siSalta: + 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(), @@ -454,11 +827,13 @@ def posicionTerminada(self): if numPosics > salto: liNuevo.extend(self.liTrainPositions[salto:]) self.training["LITRAINPOSITIONS"] = liNuevo - self.pantalla.ponToolBar((k_mainmenu, k_siguiente)) + self.pantalla.ponToolBar((k_mainmenu, k_siguiente, k_configurar)) self.dbop.setTraining(self.training) self.estado = kFinJuego self.muestraInformacion() + if siSalta: + self.reinicio(self.dbop) def muestraAyuda(self): liMoves = self.trposition["MOVES"] @@ -469,11 +844,16 @@ def procesarAccion(self, clave): if clave == k_mainmenu: self.finPartida() - elif clave == k_reiniciar : - self.reiniciar() - elif clave == k_configurar: - self.configurar(siSonidos=True) + base = _("What to do after solving") + if self.siSaltoAutomatico: + liMasOpciones = [("lmo_stop", "%s: %s" % (base, _("Stop")), Iconos.PuntoRojo())] + else: + liMasOpciones = [("lmo_jump", "%s: %s" % (base, _("Jump to the next")), Iconos.PuntoVerde())] + + resp = self.configurar(siSonidos=True, siCambioTutor=False, liMasOpciones=liMasOpciones) + if resp in ("lmo_stop", "lmo_jump"): + self.siSaltoAutomatico = resp == "lmo_jump" elif clave == k_utilidades: self.utilidades() @@ -496,9 +876,6 @@ def finPartida(self): self.procesador.openings() return False - def reiniciar(self): - self.reinicio(self.dbop) - def siguienteJugada(self): self.muestraInformacion() if self.estado == kFinJuego: @@ -551,4 +928,4 @@ def masJugada(self, jg, siNuestra): self.pgnRefresh(self.partida.ultPosicion.siBlancas) self.refresh() - self.ponPosicionDGT() \ No newline at end of file + self.ponPosicionDGT() diff --git a/Code/GestorPGN.py b/Code/GestorPGN.py index ba24e05..4f5b988 100644 --- a/Code/GestorPGN.py +++ b/Code/GestorPGN.py @@ -4,7 +4,6 @@ import sys import random - from Code import Gestor from Code import PGN from Code import Partida @@ -189,7 +188,6 @@ def miniatura(self): self.pgnPaste = txt self.mostrar(pgn, False) - def mostrar(self, pgn, siRepiteFichero, siBlancas=None): self.pensando(True) self.partida.leeOtra(pgn.partida) diff --git a/Code/GestorPlayPGN.py b/Code/GestorPlayPGN.py index 2c60080..c5f9ee0 100644 --- a/Code/GestorPlayPGN.py +++ b/Code/GestorPlayPGN.py @@ -302,7 +302,7 @@ def ponResultado(self): self.beepResultado(quien) - QTUtil2.mensaje(self.pantalla, mensaje) + self.mensajeEnPGN(mensaje) self.ponFinJuego() self.guardar() diff --git a/Code/GestorResistance.py b/Code/GestorResistance.py index bd6ae69..345b068 100644 --- a/Code/GestorResistance.py +++ b/Code/GestorResistance.py @@ -237,7 +237,7 @@ def finJuego(self, siFinPartida): txt = "

%s

" % (_X(_("You have lost %1 points."), str(-self.puntosRival))) if siFinPartida: - QTUtil2.mensaje(self.pantalla, txt) + self.mensajeEnPGN(txt) else: resp = QTUtil2.pregunta(self.pantalla, txt + "
%s" % (_("Do you want to resign or continue playing?")), diff --git a/Code/GestorRoutes.py b/Code/GestorRoutes.py index d3ef4a1..4aaac48 100644 --- a/Code/GestorRoutes.py +++ b/Code/GestorRoutes.py @@ -333,9 +333,10 @@ def lineaTerminada(self): if siwin: if self.route.end_playing(): - QTUtil2.mensaje(self.pantalla, _("Congratulations, you have completed the game.")) + mensaje = _("Congratulations, you have completed the game.") else: - QTUtil2.mensaje(self.pantalla, _("Well done")) + mensaje = _("Well done") + self.mensajeEnPGN(mensaje) else: if self.must_win: QTUtil2.mensError(self.pantalla, _("You must win to pass this step.")) @@ -594,14 +595,17 @@ def lineaTerminada(self): jgUlt = self.partida.last_jg() if jgUlt.siTablas(): - QTUtil2.mensaje(self.pantalla, _("Draw") + "
" + _("You must repeat the puzzle.")) + mensaje = "%s
%s" % (_("Draw"), _("You must repeat the puzzle.")) + self.mensajeEnPGN(mensaje) self.inicio(self.route) elif self.warnings <= self.max_warnings: self.pantalla.ponToolBar([k_mainmenu, k_utilidades]) - QTUtil2.mensaje(self.pantalla, _("Done")) + self.mensajeEnPGN(_("Done")) self.route.end_ending() else: - QTUtil2.mensaje(self.pantalla, _("Done with errors.") + "
" + _("You must repeat the puzzle.")) + QTUtil2.mensaje(self.pantalla, ) + mensaje = "%s
%s" % (_("Done with errors."), _("You must repeat the puzzle.")) + self.mensajeEnPGN(mensaje) self.inicio(self.route) def actualPGN(self): @@ -770,7 +774,8 @@ def lineaTerminada(self): self.refresh() km = self.route.end_tactic() if not self.route.go_fast: - QTUtil2.mensaje(self.pantalla, _("Done") + "
" + _("You have traveled %s") % Routes.km_mi(km, self.route.is_miles)) + mensaje = "%s
%s" % (_("Done"), _("You have traveled %s") % Routes.km_mi(km, self.route.is_miles)) + self.mensajeEnPGN(mensaje) self.siJuegaHumano = False self.estado = kFinJuego if self.route.go_fast: diff --git a/Code/GestorTacticas.py b/Code/GestorTacticas.py index dcc8231..d53ab8d 100644 --- a/Code/GestorTacticas.py +++ b/Code/GestorTacticas.py @@ -30,6 +30,8 @@ def inicio(self, tactica, posSiguiente=None): self.numPosiciones = self.tactica.numPosiciones() self.posActual = self.tactica.posActual() + self.siError = False + numEnt = liOrden[self.posActual] self.siPenalizable = True @@ -37,6 +39,8 @@ def inicio(self, tactica, posSiguiente=None): self.pointView = self.tactica.pointView() + self.siSaltoAutomatico = self.tactica.siSaltoAutomatico() + txtEntreno = self.tactica.unFNS(numEnt) if posSiguiente is None: @@ -141,7 +145,7 @@ def inicio(self, tactica, posSiguiente=None): else: self.siShowText = len(etiDirigido) == 0 - liOpciones = [k_mainmenu] + liOpciones = [k_mainmenu, k_configurar] if not self.siShowText: liOpciones.append(k_showtext) if self.dicEtiquetasPGN: @@ -203,7 +207,16 @@ def procesarAccion(self, clave): self.lanzaVariantes() elif clave == k_configurar: - self.configurar(siSonidos=True, siCambioTutor=False) + base = _("What to do after solving") + if self.siSaltoAutomatico: + liMasOpciones = [("lmo_stop", "%s: %s" %(base, _("Stop")), Iconos.PuntoRojo())] + else: + liMasOpciones = [("lmo_jump", "%s: %s" %(base, _("Jump to the next")), Iconos.PuntoVerde())] + + resp = self.configurar(siSonidos=True, siCambioTutor=False, liMasOpciones=liMasOpciones) + if resp in ("lmo_stop", "lmo_jump"): + self.siSaltoAutomatico = resp == "lmo_jump" + self.tactica.setSaltoAutomatico(self.siSaltoAutomatico) elif clave == k_utilidades: self.utilidades() @@ -254,6 +267,7 @@ def reiniciar(self): self.siguienteJugada() def ent_siguiente(self): + self.siError = False # Para controlar salto, no es automatico si se produce un error if self.posSiguiente == self.numPosiciones: self.finPartida() else: @@ -351,30 +365,33 @@ def siguienteJugada(self): def finLinea(self): self.compruebaComentarios() - QTUtil2.mensajeTemporal(self.pantalla, _("This line training is completed."), 0.7) self.estado = kFinJuego self.desactivaTodas() - liOpciones = [k_mainmenu, k_reiniciar, k_cambiar] + self.tactica.ponPosActual(self.posSiguiente) + if self.tactica.terminada(): + self.finalEntrenamiento() - if not (self.siTerminada() and len(self.liVariantes) == 0): - liOpciones.append(k_variantes) + self.siPenalizable = False - if not self.siShowText: - liOpciones.append(k_showtext) # Si no se ha mostrado ahora es el momento + if self.siSaltoAutomatico and not self.siError: + self.ent_siguiente() + else: + QTUtil2.mensajeTemporal(self.pantalla, _("This line training is completed."), 0.7) + liOpciones = [k_mainmenu, k_reiniciar, k_cambiar] - if self.dicEtiquetasPGN: - liOpciones.append(k_pgnInformacion) + if not (self.siTerminada() and len(self.liVariantes) == 0): + liOpciones.append(k_variantes) - liOpciones.extend([k_configurar, k_utilidades, k_siguiente]) + if not self.siShowText: + liOpciones.append(k_showtext) # Si no se ha mostrado ahora es el momento - self.pantalla.ponToolBar(liOpciones) + if self.dicEtiquetasPGN: + liOpciones.append(k_pgnInformacion) - self.tactica.ponPosActual(self.posSiguiente) - if self.tactica.terminada(): - self.finalEntrenamiento() + liOpciones.extend([k_configurar, k_utilidades, k_siguiente]) - self.siPenalizable = False + self.pantalla.ponToolBar(liOpciones) return @@ -406,6 +423,7 @@ def mueveHumano(self, desde, hasta, coronacion=None): liMovs.append((jg1.desde, jg1.hasta, siMain)) if not siEsta: + self.siError = True self.tactica.nuevoError() self.ponPosicion(self.partida.ultPosicion) if posMain and posMain != movimiento[:2]: @@ -522,8 +540,8 @@ def lanzaVariantes(self): def finalEntrenamiento(self): self.tactica.finalEntrenamiento() - txt = "%s
%s
" % (_("Congratulations goal achieved"), _("Endgame")) - QTUtil2.mensaje(self.pantalla, txt) + mensaje = "%s
%s
" % (_("Congratulations goal achieved"), _("Endgame")) + self.mensajeEnPGN(mensaje) self.finPartida() def guardaVariantes(self): diff --git a/Code/GestorTorneo.py b/Code/GestorTorneo.py index b11ac56..ff4d85a 100644 --- a/Code/GestorTorneo.py +++ b/Code/GestorTorneo.py @@ -110,13 +110,14 @@ def siguienteJuego(self, gm, ngame, numGames): self.refresh() self.finPorTiempo = None + self.finPorError = None + self.finPorErrorMasInfo = "" self.finForce = None while self.siPausa or self.siguienteJugada(): QTUtil.refreshGUI() if self.siPausa: time.sleep(0.1) - self.xmotor[True].terminar() self.xmotor[False].terminar() self.pantalla.paraReloj() @@ -141,6 +142,9 @@ def compruebaFinal(self): if self.finPorTiempo is not None: result = self.finPorTiempo + elif self.finPorError is not None: + result = self.finPorError + elif self.finForce is not None: result = self.finForce @@ -199,6 +203,8 @@ def compruebaFinal(self): termination = "normal" if self.finPorTiempo: termination = "time forfeit" + elif self.finPorError: + termination = self.finPorErrorMasInfo elif self.finForce: termination = "adjudication" elif adjudication: @@ -223,8 +229,6 @@ def siguienteJugada(self): self.ponIndicador(siBlancas) self.refresh() - self.relojStart(siBlancas) - siEncontrada = False analisis = None bk = self.book[siBlancas] @@ -240,8 +244,16 @@ def siguienteJugada(self): segundosJugada = xrival.motorTiempoJugada if self.siTerminar: return False + self.relojStart(siBlancas) mrm = xrival.juegaTiempoTorneo(tiempoBlancas, tiempoNegras, segundosJugada) + self.relojStop(siBlancas) if mrm is None: + if self.tiempo[siBlancas].siAgotado(): + self.finPorTiempo = 2 if siBlancas else 1 + else: + self.finPorError = 2 if siBlancas else 1 + self.finPorErrorMasInfo = "Engine error" + self.compruebaFinal() return False rm = mrm.mejorMov() desde = rm.desde @@ -249,12 +261,17 @@ def siguienteJugada(self): coronacion = rm.coronacion analisis = mrm, 0 - self.relojStop(siBlancas) if self.siTerminar: return False siBien, mens, jg = Jugada.dameJugada(self.partida.ultPosicion, desde, hasta, coronacion) if not jg: + if self.tiempo[siBlancas].siAgotado(): + self.finPorTiempo = 2 if siBlancas else 1 + else: + self.finPorError = 2 if siBlancas else 1 + self.finPorErrorMasInfo = "Engine error: bad move %s-%s%s" %(desde, hasta, coronacion if coronacion else "") + self.compruebaFinal() return False if analisis: jg.analisis = analisis @@ -366,5 +383,3 @@ def assignResult(self): if resp is not None: self.finForce = resp - - diff --git a/Code/GestorWashing.py b/Code/GestorWashing.py index bc5904d..581a690 100644 --- a/Code/GestorWashing.py +++ b/Code/GestorWashing.py @@ -139,10 +139,9 @@ def finPartida(self): if ok: mens = _("Congratulations, this washing is done") - QTUtil2.mensaje(self.pantalla, mens) else: mens = "%s
%s: %d" %( _("Done with errors."), _("Errors"), self.errores) - QTUtil2.mensError(self.pantalla, mens) + self.mensajeEnPGN(mens) def mueveHumano(self, desde, hasta, coronacion=None): jg = self.checkMueveHumano(desde, hasta, coronacion) @@ -384,7 +383,7 @@ def finLinea(self): if self.num_lines == 0: mens = "%s\n%s" % (mens, _("You have solved all puzzles")) - QTUtil2.mensaje(self.pantalla, mens) + self.mensajeEnPGN(mens) else: QTUtil2.mensError(self.pantalla, "%s: %d, %s: %d" % (_("Errors"), self.errores, _("Hints"), self.ayudas)) @@ -869,7 +868,7 @@ def ponResultado(self, quien): self.resultado = kTablas self.guardarGanados(quien == kGanamos) - QTUtil2.mensaje(self.pantalla, mensaje) + self.mensajeEnPGN(mensaje) self.estado = kFinJuego self.desactivaTodas() liOpciones = [k_mainmenu, k_configurar, k_utilidades] diff --git a/Code/Init.py b/Code/Init.py index b7a351a..6ea9291 100644 --- a/Code/Init.py +++ b/Code/Init.py @@ -9,7 +9,7 @@ from Code.Constantes import * DEBUG = False -VERSION = "11.09" +VERSION = "11.10" if DEBUG: prlkn("DEBUG " * 20) diff --git a/Code/Jugada.py b/Code/Jugada.py index 740e671..e9a9be4 100644 --- a/Code/Jugada.py +++ b/Code/Jugada.py @@ -6,7 +6,6 @@ NOABANDONO, ABANDONO, ABANDONORIVAL = "N", "S", "R" - # def creaDicHTML(): # base = '' # dic = {} @@ -15,6 +14,7 @@ # dic[x] = base % ("b", x) # return dic + def creaDicHTML(): base = '%s' ori = "KQRBNPkqrbnp" diff --git a/Code/Kibitzers.py b/Code/Kibitzers.py index a40c926..ef3757e 100644 --- a/Code/Kibitzers.py +++ b/Code/Kibitzers.py @@ -19,7 +19,8 @@ def __init__(self): ("L", _("Best move in one line"), Iconos.pmPuntoMagenta()), ("J", _("Select move"), Iconos.pmPuntoNaranja()), ("C", _("Threats"), Iconos.pmPuntoAzul()), - ("E", _("Stockfish evaluation"), Iconos.pmPuntoAmarillo()) + ("E", _("Stockfish evaluation"), Iconos.pmPuntoAmarillo()), + ("B", _("Polyglot book"), Iconos.pmPuntoEstrella()) ) def combo(self): @@ -223,6 +224,17 @@ def nuevo(self, nombre, motor, tipo, prioridad): self.save() return len(self.lista)-1 + def nuevoPolyglot(self, book): + kib = Kibitzer() + kib.ponHuella(self.lista) + kib.alias = kib.nombre = book.nombre + kib.tipo = "B" + kib.exe = book.path + kib.clave = book.nombre + self.lista.append(kib) + self.save() + return len(self.lista)-1 + def __len__(self): return len(self.lista) diff --git a/Code/OpeningLines.py b/Code/OpeningLines.py index 906f8df..8122cee 100644 --- a/Code/OpeningLines.py +++ b/Code/OpeningLines.py @@ -1,6 +1,9 @@ import os +import shutil import sqlite3 import random +import datetime +import collections import LCEngineV1 as LCEngine @@ -12,6 +15,7 @@ from Code.QT import QTVarios from Code.QT import QTUtil2 + class ListaOpenings: def __init__(self, configuracion): self.folder = configuracion.folderOpenings @@ -124,6 +128,30 @@ def new(self, file, basepv, title): op.close() self.save() + def copy(self, pos): + dicline = dict(self.lista[pos]) + base = dicline["file"][:-3] + if base.split("-")[-1].isdigit(): + li = base.split("-") + base = "-".join(li[:-1]) + filenew = "%s-1.opk" % base + n = 1 + while os.path.isfile(os.path.join(self.folder, filenew)): + filenew = "%s-%d.opk" % (base, n) + n += 1 + try: + shutil.copy(self.filepath(pos), os.path.join(self.folder, filenew)) + except: + return + + dicline["file"] = filenew + dicline["title"] = dicline["title"] + " -%d"%(n-1 if n > 1 else 1) + self.lista.append(dicline) + op = Opening(self.filepath(len(self.lista)-1)) + op.settitle(dicline["title"]) + op.close() + self.save() + def change_title(self, num, title): op = Opening(self.filepath(num)) op.settitle(title) @@ -138,6 +166,13 @@ def add_training_file(self, file): self.save() return + def add_training_engines_file(self, file): + for dicline in self.lista: + if file == dicline["file"]: + dicline["withtrainings_engine"] = True + self.save() + return + class Opening: def __init__(self, nomFichero): @@ -146,20 +181,51 @@ def __init__(self, nomFichero): self._conexion = sqlite3.connect(nomFichero) self.cache = {} - self.max_cache = 4000 + self.max_cache = 14000 self.del_cache = 1000 self.grupo = 0 + self.history = collections.OrderedDict() + self.li_xpv = self.init_database() self.db_config = Util.DicSQL(nomFichero, tabla="CONFIG") self.db_fenvalues = Util.DicSQL(nomFichero, tabla="FENVALUES") + self.db_history = Util.DicSQL(nomFichero, tabla="HISTORY") + self.db_cache_engines = None self.basePV = self.getconfig("BASEPV", "") self.title = self.getconfig("TITLE", os.path.basename(nomFichero).split(".")[0]) self.tablero = None + def open_cache_engines(self): + if self.db_cache_engines is None: + self.db_cache_engines = Util.DicSQL(self.nomFichero, tabla="CACHE_ENGINES") + + def get_cache_engines(self, engine, ms, fenM2): + key = "%s-%d-%s" % (engine, ms, fenM2) + return self.db_cache_engines[key] + + def set_cache_engines(self, engine, ms, fenM2, move): + key = "%s-%d-%s" % (engine, ms, fenM2) + self.db_cache_engines[key] = move + + def init_database(self): + cursor = self._conexion.cursor() + cursor.execute("pragma table_info(LINES)") + if not cursor.fetchall(): + sql = "CREATE TABLE LINES( XPV TEXT PRIMARY KEY );" + cursor.execute(sql) + self._conexion.commit() + li_xpv = [] + else: + 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 setdbVisual_Tablero(self, tablero): self.tablero = tablero @@ -189,7 +255,6 @@ def removeAnalisis(self, tmpBP, mensaje): self.setfenvalue(fenM2, dic) self.packAlTerminar() - def getconfig(self, key, default=None): return self.db_config.get(key, default) @@ -200,7 +265,13 @@ def training(self): return self.getconfig("TRAINING") def setTraining(self, reg): - return self.setconfig("TRAINING", reg) + self.setconfig("TRAINING", reg) + + def trainingEngines(self): + return self.getconfig("TRAINING_ENGINES") + + def setTrainingEngines(self, reg): + self.setconfig("TRAINING_ENGINES", reg) def preparaTraining(self, reg, procesador): maxmoves = reg["MAXMOVES"] @@ -221,20 +292,22 @@ def preparaTraining(self, reg, procesador): lilipv[pos] = lipv[:-1] # Quitamos las repetidas - lilipvfinal = [] - nt = len(lilipv) - for x in range(nt-1): - pvmirar = "".join(lilipv[x]) - esta = False - for y in range(nt): - if y != x: - pvotro = "".join(lilipv[y]) - if pvotro.startswith(pvmirar): - esta = True - break - if not esta: - lilipvfinal.append(lilipv[x]) - lilipv = lilipvfinal + dicpv = {} + for lipv in lilipv: + pvmirar = "".join(lipv) + if pvmirar in dicpv: + continue + + siesta = False + for pvotro in dicpv: + if pvotro.startswith(pvmirar): + siesta = True + break + if not siesta: + dicpv[pvmirar] = lipv + li = dicpv.keys() + li.sort() + lilipv = [value for key, value in dicpv.iteritems()] ligamesST = [] ligamesSQ = [] @@ -315,7 +388,83 @@ def preparaTraining(self, reg, procesador): random.shuffle(liTrainPositions) reg["LITRAINPOSITIONS"] = liTrainPositions - def createTraining(self, reg, procesador): + def recalcFenM2(self): + lilipv = [LCEngine.xpv2pv(xpv).split(" ") for xpv in self.li_xpv] + + dicFENm2 = {} + for lipv in lilipv: + 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) + return dicFENm2 + + def preparaTrainingEngines(self, reg): + reg["DICFENM2"] = self.recalcFenM2() + reg["TIMES"] = [500, 1000, 2000, 4000, 8000] + reg["ENGINES"] = self.listaEngines()[reg["NUM_LISTA"]] + + def updateTrainingEngines(self): + reg = self.trainingEngines() + reg["DICFENM2"] = self.recalcFenM2() + self.setTrainingEngines(reg) + + def listaEngines(self): + lista = [ + ['irina', 'chispa', 'hamsters', 'zappa', 'demolito', 'wildcat', 'cheng', 'stockfish'], + ['irina', 'arminius', 'rodent', 'toga', 'rodentII', 'gaviota', 'texel', 'gull'], + ['tarrasch', 'cdrill', 'bikjump', 'garbochess', 'ufim', 'amyan', 'delfi', 'spike'], + ['rocinante', 'roce', 'cinnamon', 'gaia', 'greko', 'godel', 'rodent', 'mcbrain'], + ['zappa', 'demolito', 'rhetoric', 'critter', 'houdini', 'gull', 'andscacs', 'stockfish'], + ['clarabit', 'pawny', 'hamsters', 'cheng', 'spike', 'rybka', 'hannibal', 'texel'], + ['bikjump', 'clarabit', 'chispa', 'gaia', 'umko', 'greko', 'wildcat', 'critter'], + ['tarrasch', 'cdrill', 'lime', 'arminius', 'delfi', 'gaviota', 'andscacs', 'mcbrain'], + ['rocinante', 'cinnamon', 'pawny', 'amyan', 'alaric', 'daydreamer', 'godel', 'rodentII'], + ['irina', 'roce', 'demolito', 'rhetoric', 'toga', 'hannibal', 'komodo', 'stockfish'], + ['lime', 'zappa', 'wildcat', 'daydreamer', 'cheng', 'glaurung', 'critter', 'andscacs'], + ['bikjump', 'gaia', 'hamsters', 'umko', 'ufim', 'alaric', 'houdini', 'gull'], + ['cdrill', 'chispa', 'hamsters', 'amyan', 'spike', 'rybka', 'texel', 'komodo'], + ['tarrasch', 'clarabit', 'garbochess', 'ufim', 'delfi', 'fruit', 'rhetoric', 'mcbrain'], + ['rocinante', 'roce', 'cinnamon', 'pawny', 'alaric', 'cheng', 'fruit', 'rodent'], + ['irina', 'lime', 'garbochess', 'zappa', 'demolito', 'daydreamer', 'glaurung', 'spike'], + ['umko', 'greko', 'wildcat', 'glaurung', 'critter', 'gull', 'andscacs', 'stockfish'], + ['bikjump', 'chispa', 'gaia', 'wildcat', 'daydreamer', 'godel', 'fruit', 'toga'], + ['cdrill', 'clarabit', 'lime', 'umko', 'greko', 'amyan', 'delfi', 'texel'], + ['tarrasch', 'rocinante', 'roce', 'cinnamon', 'daydreamer', 'gaviota', 'houdini', 'mcbrain'], + ['irina', 'lime', 'umko', 'alaric', 'arminius', 'glaurung', 'fruit', 'stockfish'], + ['chispa', 'hamsters', 'zappa', 'demolito', 'cheng', 'rhetoric', 'houdini', 'andscacs'], + ['cdrill', 'bikjump', 'gaia', 'ufim', 'arminius', 'fruit', 'texel', 'gull'], + ['tarrasch', 'clarabit', 'simplex', 'amyan', 'delfi', 'godel', 'spike', 'hannibal'], + ['rocinante', 'roce', 'cinnamon', 'pawny', 'greko', 'glaurung', 'rhetoric', 'komodo'], + ['irina', 'lime', 'zappa', 'demolito', 'rodent', 'rodentII', 'gaviota', 'stockfish'], + ['bikjump', 'arminius', 'cheng', 'toga', 'critter', 'houdini', 'gull', 'mcbrain'], + ['chispa', 'gaia', 'umko', 'toga', 'hannibal', 'critter', 'texel', 'andscacs'], + ['cdrill', 'greko', 'godel', 'rodent', 'rhetoric', 'toga', 'rybka', 'hannibal'], + ['tarrasch', 'clarabit', 'arminius', 'delfi', 'rybka', 'gaviota', 'houdini', 'mcbrain'], + ['rocinante', 'roce', 'cinnamon', 'pawny', 'amyan', 'wildcat', 'godel', 'toga'], + ['irina', 'cdrill', 'zappa', 'demolito', 'daydreamer', 'fruit', 'andscacs', 'stockfish'], + ['lime', 'pawny', 'ufim', 'wildcat', 'alaric', 'glaurung', 'rhetoric', 'critter'], + ['chispa', 'gaia', 'amyan', 'arminius', 'rybka', 'hannibal', 'texel', 'gull'], + ['tarrasch', 'bikjump', 'alaric', 'delfi', 'cheng', 'spike', 'gaviota', 'mcbrain'], + ['cinnamon', 'simplex', 'umko', 'delfi', 'godel', 'spike', 'gaviota', 'komodo'], + ['irina', 'rocinante', 'roce', 'clarabit', 'zappa', 'daydreamer', 'houdini', 'stockfish'], + ['tarrasch', 'lime', 'umko', 'cheng', 'rodent', 'rybka', 'hannibal', 'gull'], + ['chispa', 'glaurung', 'spike', 'gaviota', 'critter', 'texel', 'andscacs', 'komodo'], + ['cdrill', 'bikjump', 'clarabit', 'hamsters', 'amyan', 'demolito', 'wildcat', 'mcbrain'], + ['cinnamon', 'godel', 'fruit', 'rhetoric', 'toga', 'hannibal', 'houdini', 'komodo'], + ['irina', 'rocinante', 'roce', 'hamsters', 'godel', 'glaurung', 'rodentII', 'stockfish'], + ['roce', 'umko', 'greko', 'garbochess', 'demolito', 'cheng', 'gull', 'andscacs'], + ['chispa', 'pawny', 'ufim', 'rodentII', 'spike', 'rybka', 'texel', 'komodo'], + ['bikjump', 'clarabit', 'lime', 'gaia', 'simplex', 'greko', 'rybka', 'hannibal'], + ['cdrill', 'rocinante', 'ufim', 'amyan', 'rhetoric', 'toga', 'rybka', 'komodo'], + ] + return lista + + def createTrainingSSP(self, reg, procesador): self.preparaTraining(reg, procesador) reg["DATECREATION"] = Util.hoy() @@ -325,6 +474,17 @@ def createTraining(self, reg, procesador): lo = ListaOpenings(procesador.configuracion) lo.add_training_file(os.path.basename(self.nomFichero)) + def createTrainingEngines(self, reg, procesador): + self.preparaTrainingEngines(reg) + reg["DATECREATION"] = Util.hoy() + self.setTrainingEngines(reg) + + self.setconfig("ENG_LEVEL", 0) + self.setconfig("ENG_ENGINE", 0) + + lo = ListaOpenings(procesador.configuracion) + lo.add_training_engines_file(os.path.basename(self.nomFichero)) + def withTrainings(self): return "TRAINING" in self.db_config @@ -446,29 +606,11 @@ def add_cache(self, xpv, partida): break self.cache[xpv] = partida - def init_database(self): - cursor = self._conexion.cursor() - cursor.execute("pragma table_info(LINES)") - if not cursor.fetchall(): - sql = "CREATE TABLE LINES( XPV TEXT PRIMARY KEY, GRUPO INTEGER, LINE BLOB );" - cursor.execute(sql) - sql = "CREATE INDEX IDX_GRUPO ON LINES( GRUPO );" - cursor.execute(sql) - self._conexion.commit() - li_xpv = [] - else: - 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): xpv = LCEngine.pv2xpv(partida.pv()) - line_blob = partida.save2blob() - sql = "INSERT INTO LINES( XPV, LINE ) VALUES( ?, ? )" + sql = "INSERT INTO LINES( XPV ) VALUES( ? )" cursor = self._conexion.cursor() - cursor.execute(sql, (xpv, line_blob)) + cursor.execute(sql, (xpv,)) cursor.close() self._conexion.commit() self.li_xpv.append(xpv) @@ -504,8 +646,8 @@ def __setitem__(self, num, partida_nue): self.li_xpv.sort() num = self.li_xpv.index(xpv_nue) cursor = self._conexion.cursor() - sql = "UPDATE LINES SET XPV=?, LINE=? WHERE XPV=?" - cursor.execute(sql, (xpv_nue, partida_nue.save2blob(), xpv_ant)) + sql = "UPDATE LINES SET XPV=? WHERE XPV=?" + cursor.execute(sql, (xpv_nue, xpv_ant)) self._conexion.commit() self.add_cache(xpv_nue, partida_nue) cursor.close() @@ -516,14 +658,10 @@ def __getitem__(self, num): if xpv in self.cache: return self.cache[xpv] - sql = "select LINE from LINES where XPV=?" - cursor = self._conexion.cursor() - cursor.execute(sql, (xpv,)) - blob = cursor.fetchone()[0] partida = Partida.Partida() - partida.blob2restore(blob) + pv = LCEngine.xpv2pv(xpv) + partida.leerPV(pv) self.add_cache(xpv, partida) - cursor.close() return partida def __delitem__(self, num): @@ -540,6 +678,54 @@ def __delitem__(self, num): def __len__(self): return len(self.li_xpv) + def removeLines(self, li, label): + self.saveHistory(_("Removing"), label) + li.sort(reverse=True) + cursor = self._conexion.cursor() + for num in li: + xpv = self.li_xpv[num] + sql = "DELETE FROM LINES where XPV=?" + cursor.execute(sql, (xpv,)) + if xpv in self.cache: + del self.cache[xpv] + del self.li_xpv[num] + self._conexion.commit() + cursor.close() + + def lihistory(self): + return self.db_history.keys(siOrdenados=True, siReverse=True) + + def saveHistory(self, *label): + d = datetime.datetime.now() + s = "%s-%s" % (d.strftime("%Y-%m-%d %H:%M:%S"), ",".join(label)) + self.db_history[s] = self.li_xpv[:] + + def rechistory(self, key): + self.saveHistory(_("Recovering"), key) + + stActivo = set(self.li_xpv) + li_xpv_rec = self.db_history[key] + stRecuperar = set(li_xpv_rec) + + cursor = self._conexion.cursor() + + # Borramos los que no estan en Recuperar + sql = "DELETE FROM LINES where XPV=?" + for xpv in stActivo: + if xpv not in stRecuperar: + cursor.execute(sql, (xpv,)) + self._conexion.commit() + + # Mas los que no estan en Activo + sql = "INSERT INTO LINES( XPV ) VALUES( ? )" + for xpv in stRecuperar: + if xpv not in stActivo: + cursor.execute(sql, (xpv, )) + self._conexion.commit() + + cursor.close() + self.li_xpv = li_xpv_rec + def close(self): if self._conexion: conexion = self._conexion @@ -553,16 +739,30 @@ def close(self): self.db_fenvalues.close() self.db_fenvalues = None + if self.db_cache_engines: + self.db_cache_engines.close() + self.db_cache_engines = None + if self.tablero: self.tablero.dbVisual_close() self.tablero = None if si_pack: + if len(self.db_history) > 70: + lik = self.db_history.keys(siOrdenados=True, siReverse=False) + liremove = lik[:len(self.db_history)-50] + for k in liremove: + del self.db_history[k] + self.db_history.close() + cursor = conexion.cursor() cursor.execute("VACUUM") cursor.close() conexion.commit() + else: + self.db_history.close() + conexion.close() def importarPGN(self, owner, partidabase, ficheroPGN, maxDepth): @@ -571,12 +771,14 @@ def importarPGN(self, owner, partidabase, ficheroPGN, maxDepth): dlTmp.hideDuplicados() dlTmp.show() + self.saveHistory(_("Import"), _("PGN with variants"), os.path.basename(ficheroPGN)) + cursor = self._conexion.cursor() base = partidabase.pv() if partidabase else self.getconfig("BASEPV") - sql_insert = "INSERT INTO LINES( XPV, LINE ) VALUES( ?, ? )" - sql_update = "UPDATE LINES SET XPV=?, LINE=? WHERE XPV=?" + sql_insert = "INSERT INTO LINES( XPV ) VALUES( ? )" + sql_update = "UPDATE LINES SET XPV=? WHERE XPV=?" for n, g in enumerate(PGNreader.readGames(ficheroPGN), 1): if not dlTmp.actualiza(n, erroneos, duplicados, importados): @@ -599,18 +801,17 @@ def haz_partida(liMoves): if base and not pv.startswith(base): return xpv = LCEngine.pv2xpv(pv) - line_blob = partida.save2blob() updated = False for npos, xpv_ant in enumerate(self.li_xpv): if xpv_ant.startswith(xpv): return if xpv.startswith(xpv_ant): - cursor.execute(sql_update, (xpv, line_blob, xpv_ant)) + cursor.execute(sql_update, (xpv, xpv_ant)) self.li_xpv[npos] = xpv updated = True break if not updated: - cursor.execute(sql_insert, (xpv, line_blob)) + cursor.execute(sql_insert, (xpv,)) self.li_xpv.append(xpv) for njug, move in enumerate(liMoves): @@ -633,6 +834,9 @@ def haz_partida(liMoves): dlTmp.ponContinuar() def importarPGO(self, partidabase, ficheroPGO, maxDepth): + + self.saveHistory(_("Personal Opening Guide"), os.path.basename(ficheroPGO)) + base = partidabase.pv() if partidabase else self.getconfig("BASEPV") baseXPV = LCEngine.pv2xpv(base) @@ -664,58 +868,75 @@ def importarPGO(self, partidabase, ficheroPGO, maxDepth): cursor = self._conexion.cursor() - sql_insert = "INSERT INTO LINES( XPV, LINE ) VALUES( ?, ? )" - sql_update = "UPDATE LINES SET XPV=?, LINE=? WHERE XPV=?" + sql_insert = "INSERT INTO LINES( XPV ) VALUES( ? )" + sql_update = "UPDATE LINES SET XPV=? WHERE XPV=?" for xpv in stPGO: - pv = LCEngine.xpv2pv(xpv) - partida = Partida.Partida() - partida.leerPV(pv) - line_blob = partida.save2blob() add = True for npos, xpv_ant in enumerate(self.li_xpv): if xpv_ant.startswith(xpv): add = False break if xpv.startswith(xpv_ant): - cursor.execute(sql_update, (xpv, line_blob, xpv_ant)) + cursor.execute(sql_update, (xpv, xpv_ant)) self.li_xpv[npos] = xpv add = False break if add: - cursor.execute(sql_insert, (xpv, line_blob)) + cursor.execute(sql_insert, (xpv, )) self.li_xpv.append(xpv) cursor.close() self.li_xpv.sort() self._conexion.commit() - def guardaPartidas(self, liPartidas, minMoves=0): + def guardaPartidas(self, label, liPartidas, minMoves=0): + self.saveHistory(_("Import"), label) partidabase = self.getpartidabase() - sql_insert = "INSERT INTO LINES( XPV, LINE ) VALUES( ?, ? )" - sql_update = "UPDATE LINES SET XPV=?, LINE=? WHERE XPV=?" + sql_insert = "INSERT INTO LINES( XPV) VALUES( ? )" + sql_update = "UPDATE LINES SET XPV=? WHERE XPV=?" cursor = self._conexion.cursor() for partida in liPartidas: if minMoves <= 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)) + cursor.execute(sql_update, (xpv, xpv_ant)) self.li_xpv[npos] = xpv updated = True break if not updated: - cursor.execute(sql_insert, (xpv, line_blob)) + cursor.execute(sql_insert, (xpv,)) self.li_xpv.append(xpv) cursor.close() self._conexion.commit() self.li_xpv.sort() - def importarPolyglot(self, ventana, partida, bookW, bookB, titulo, depth, siWhite, minMoves): + def guardaLiXPV(self, label, liXPV): + self.saveHistory(_("Import"), label) + sql_insert = "INSERT INTO LINES( XPV) VALUES( ? )" + sql_update = "UPDATE LINES SET XPV=? WHERE XPV=?" + cursor = self._conexion.cursor() + for xpv in liXPV: + if xpv not in self.li_xpv: + updated = False + for npos, xpv_ant in enumerate(self.li_xpv): + if xpv.startswith(xpv_ant): + cursor.execute(sql_update, (xpv, xpv_ant)) + self.li_xpv[npos] = xpv + updated = True + break + if not updated: + cursor.execute(sql_insert, (xpv,)) + self.li_xpv.append(xpv) + cursor.close() + self._conexion.commit() + self.li_xpv.sort() + + def importarPolyglot(self, ventana, partida, bookW, bookB, titulo, depth, siWhite, onlyone, minMoves): bp = QTUtil2.BarraProgreso1(ventana, titulo) bp.ponTotal(0) bp.ponRotulo(_X(_("Reading %1"), "...")) @@ -734,7 +955,7 @@ def hazFEN(fen, lipv_ant): return siWhite1 = " w " in fen book = bookW if siWhite1 else bookB - liPV = book.miraListaPV(fen, siWhite1 == siWhite) + liPV = book.miraListaPV(fen, siWhite1 == siWhite, onlyone=onlyone) if liPV and len(lipv_ant) < depth: for pv in liPV: setFen(fen) @@ -753,12 +974,13 @@ def hazFEN(fen, lipv_ant): hazFEN(cp.fen(), partida.lipv()) bp.ponRotulo(_("Writing...")) - self.guardaPartidas(liPartidas, minMoves) + + self.guardaPartidas("%s,%s,%s"%(_("Polyglot book"), bookW.nombre, bookB.nombre), liPartidas, minMoves) bp.cerrar() return True - def importarSummary(self, ventana, partidabase, ficheroSummary, depth, siWhite, minMoves): + def importarSummary(self, ventana, partidabase, ficheroSummary, depth, siWhite, onlyone, minMoves): titulo = _("Importing the summary of a database") bp = QTUtil2.BarraProgreso1(ventana, titulo) bp.ponTotal(0) @@ -778,9 +1000,10 @@ def importarSummary(self, ventana, partidabase, ficheroSummary, depth, siWhite, def hazPV(lipv_ant): if bp.siCancelado(): return - siWhite1 = len(lipv_ant) % 2 == 0 + n_ant = len(lipv_ant) + siWhite1 = n_ant % 2 == 0 - pv_ant = " ".join(lipv_ant) + pv_ant = " ".join(lipv_ant) if n_ant else "" liChildren = dbSTAT.children(pv_ant, False) if len(liChildren) == 0 or len(lipv_ant) > depth: @@ -793,24 +1016,26 @@ def hazPV(lipv_ant): return if siWhite1 == siWhite: - alm_max = None tt_max = 0 + limax = [] 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,] + limax = [alm,] + elif tt == tt_max and not onlyone: + limax.append(alm) + liChildren = limax for alm in liChildren: li = lipv_ant[:] li.append(alm.move) hazPV(li) - hazPV(pvBase.split(" ")) + hazPV(pvBase.split(" ") if pvBase else []) bp.ponRotulo(_("Writing...")) - self.guardaPartidas(liPartidas) + self.guardaPartidas("%s,%s" %(_("Database summary"), os.path.basename(ficheroSummary)), liPartidas) bp.cerrar() return True @@ -819,12 +1044,33 @@ def importarOtra(self, pathFichero, partida): xpvbase = LCEngine.pv2xpv(partida.pv()) tambase = len(xpvbase) otra = Opening(pathFichero) - liPartidas = [] + lista = [] for n, xpv in enumerate(otra.li_xpv): - if xpv.startswith(xpvbase) and tambase < len(xpv): - liPartidas.append(otra[n]) + if xpv.startswith(xpvbase) and len(xpv) > tambase: + if xpv not in self.li_xpv: + lista.append(xpv) otra.close() - self.guardaPartidas(liPartidas) + self.guardaLiXPV("%s,%s"% (_("Other opening lines"), otra.title), lista) + + def exportarPGN(self, ws, result): + liTags = [ + ("Event", self.title.replace('"', "")), + ("Site", ""), + ("Date", Util.hoy().strftime("%Y-%m-%d")) + ] + if result: + liTags.append(("Result", result)) + + for recno in range(len(self)): + partida = self[recno] + + liTags[1] = ("Site", "%s %d" % (_("Line"), recno+1)) + + if recno > 0 or not ws.is_new: + ws.write("\n\n") + tags = "".join(['[%s "%s"]\n' % (k, v) for k, v in liTags]) + ws.write(tags) + ws.write("\n%s" % partida.pgnBase()) def getAllFen(self): stFENm2 = set() @@ -905,4 +1151,3 @@ def listaPV(self): item = item.parent return li[::-1] - diff --git a/Code/PGNreader.py b/Code/PGNreader.py index 520a82a..4ed6ea7 100644 --- a/Code/PGNreader.py +++ b/Code/PGNreader.py @@ -35,7 +35,6 @@ def clona(self): return m - class Moves: def __init__(self): self.liMoves = [] @@ -260,7 +259,14 @@ def readLabels(self, liTxt): for linea in liTxt: li = linea[1:-1].replace('""', '"').split('"') if len(li) == 3: - clave = li[0].strip() + clave = li[0].strip().replace(" ", "") + ok = True + for c in clave: + if not( 33 < ord(c) < 127): + ok = False + break + if not ok: + continue valor = li[1].strip() if clave and valor: if clave.upper() == "FEN": diff --git a/Code/Partida.py b/Code/Partida.py index ac6b101..6055114 100644 --- a/Code/Partida.py +++ b/Code/Partida.py @@ -598,6 +598,7 @@ def pv_pgn(fen, pv): p.leerPV(pv) return p.pgnSP() + def lipv_lipgn(lipv): LCEngine.setFenInicial() li_pgn = [] @@ -606,6 +607,7 @@ def lipv_lipgn(lipv): li_pgn.append(info._san) return li_pgn + def pv_pgn_raw(fen, pv): p = Partida(fen=fen) p.leerPV(pv) @@ -678,7 +680,7 @@ def calc_formula_elo(jg): # , limit=200.0): # dataLG = [] # titLG = [] - # + # def LG(key, value): # titLG.append(key) # dataLG.append(str(value)) @@ -767,7 +769,6 @@ def calc_formula_elo(jg): # , limit=200.0): # LG("elo", int(min(3500, max(0, x)))) # LG("other elo", int(jg.elo)) - # with open("FormulaELO.csv", "ab") as q: # if firstLG[0]: # firstLG[0] = False diff --git a/Code/Procesador.py b/Code/Procesador.py index 74dbf6b..c2df7f2 100644 --- a/Code/Procesador.py +++ b/Code/Procesador.py @@ -65,7 +65,8 @@ from Code.QT import PantallaDatabaseFEN from Code.QT import WOpeningGuide from Code.QT import PantallaKibitzers -from Code.QT import POLines +from Code.QT import PantallaOpeningLines +from Code.QT import PantallaOpeningLine class Procesador: @@ -596,7 +597,6 @@ def usuarios(self): def setPassword(self): PantallaUsuarios.setPassword(self) - def trainingMap(self, mapa): resp = PantallaWorkMap.train_map(self, mapa) if resp: @@ -642,12 +642,12 @@ def menuTools_run(self, resp): self.openings() def openings(self): - dicline = POLines.openingLines(self) + dicline = PantallaOpeningLines.openingLines(self) if dicline: if "TRAIN" in dicline: resp = "tr_%s" % dicline["TRAIN"] else: - resp = POLines.study(self, dicline["file"]) + resp = PantallaOpeningLine.study(self, dicline["file"]) if resp is None: self.openings() else: @@ -658,14 +658,20 @@ def openings(self): self.openingsTrainingStatic(pathFichero) elif resp == "tr_positions": self.openingsTrainingPositions(pathFichero) + elif resp == "tr_engines": + self.openingsTrainingEngines(pathFichero) def openingsTrainingSequential(self, pathFichero): self.gestor = GestorOpeningLines.GestorOpeningLines(self) self.gestor.inicio(pathFichero, "sequential", 0) + def openingsTrainingEngines(self, pathFichero): + self.gestor = GestorOpeningLines.GestorOpeningEngines(self) + self.gestor.inicio(pathFichero) + def openingsTrainingStatic(self, pathFichero): dbop = OpeningLines.Opening(pathFichero) - num_linea = POLines.selectLine(self, dbop) + num_linea = PantallaOpeningLines.selectLine(self, dbop) dbop.close() if num_linea is not None: self.gestor = GestorOpeningLines.GestorOpeningLines(self) diff --git a/Code/QT/Iconos.py b/Code/QT/Iconos.py index afa9252..65cff82 100644 --- a/Code/QT/Iconos.py +++ b/Code/QT/Iconos.py @@ -2380,6 +2380,12 @@ def pmTrainPositions(): def TrainPositions(): return QtGui.QIcon(pmTrainPositions()) +def pmTrainEngines(): + return PM(915971,917405) + +def TrainEngines(): + return QtGui.QIcon(pmTrainEngines()) + def pmError(): return PM(50641,54641) @@ -2387,25 +2393,25 @@ def Error(): return QtGui.QIcon(pmError()) def pmAtajos(): - return PM(915971,917150) + return PM(917405,918584) def Atajos(): return QtGui.QIcon(pmAtajos()) def pmTOLline(): - return PM(917150,918254) + return PM(918584,919688) def TOLline(): return QtGui.QIcon(pmTOLline()) def pmTOLchange(): - return PM(918254,920476) + return PM(919688,921910) def TOLchange(): return QtGui.QIcon(pmTOLchange()) def pmPack(): - return PM(920476,921141) + return PM(921910,922575) def Pack(): return QtGui.QIcon(pmPack()) @@ -2416,3 +2422,39 @@ def pmHome(): def Home(): return QtGui.QIcon(pmHome()) +def pmImport8(): + return PM(922575,923785) + +def Import8(): + return QtGui.QIcon(pmImport8()) + +def pmExport8(): + return PM(923785,924410) + +def Export8(): + return QtGui.QIcon(pmExport8()) + +def pmTablas8(): + return PM(924410,925202) + +def Tablas8(): + return QtGui.QIcon(pmTablas8()) + +def pmBlancas8(): + return PM(925202,926232) + +def Blancas8(): + return QtGui.QIcon(pmBlancas8()) + +def pmNegras8(): + return PM(926232,927071) + +def Negras8(): + return QtGui.QIcon(pmNegras8()) + +def pmBook(): + return PM(927071,927645) + +def Book(): + return QtGui.QIcon(pmBook()) + diff --git a/Code/QT/InfoBase.py b/Code/QT/InfoBase.py index 40edea9..f4c6486 100644 --- a/Code/QT/InfoBase.py +++ b/Code/QT/InfoBase.py @@ -426,7 +426,7 @@ def Programming(self): (_("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/"), ("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"), + (_("Polyglot books"), _X(_("Based on work by %1"), "Michel Van den Bergh"), "https://hardy.uhasselt.be/personal/vdbergh/Members/michel_id.html"), ("Polyglot1.4w", _X(_("Created by %1"), "Fabien Letouzy") + ". " + _X(_("Modified by %1"), "Fonzy Bluemers"), "http://www.geenvis.net/"), ("STS", _X(_("Created by %1"), "Dan Corbit,Swaminathan"), "https://sites.google.com/site/strategictestsuite/about-1"), ("python-chess", _X(_("Created by %1"), "Niklas Fiekas"), "https://github.com/niklasf/python-chess"), diff --git a/Code/QT/POLAnalisis.py b/Code/QT/POLAnalisis.py index 4e49f4d..7b89acd 100644 --- a/Code/QT/POLAnalisis.py +++ b/Code/QT/POLAnalisis.py @@ -335,7 +335,6 @@ def stop(self): self.dbstat.close() - class TreeMoves(QtGui.QTreeWidget): def __init__(self, owner): QtGui.QTreeWidget.__init__(self, owner) @@ -415,7 +414,6 @@ def stop(self): def setData(self, data): pass - def menuContexto(self, position): item = self.tree.currentItem() if not item: diff --git a/Code/QT/POLBoard.py b/Code/QT/POLBoard.py index f4a2801..b1fcf69 100644 --- a/Code/QT/POLBoard.py +++ b/Code/QT/POLBoard.py @@ -37,6 +37,8 @@ def __init__(self, panelOpening, configuracion): self.tablero.dbVisual_setFichero(self.dbop.nomFichero) self.tablero.dbVisual_setShowAllways(True) + self.tablero.ponerPiezasAbajo(self.dbop.getconfig("WHITEBOTTOM", True)) + self.dbop.setdbVisual_Tablero(self.tablero) # To close self.intervalo = 1400 diff --git a/Code/QT/Pantalla.py b/Code/QT/Pantalla.py index 4439f19..8dd3ea7 100644 --- a/Code/QT/Pantalla.py +++ b/Code/QT/Pantalla.py @@ -225,9 +225,9 @@ def ajustaTamH(self): def ponTitulo(self): titulo = _("Lucas Chess") - conf = self.gestor.configuracion + # conf = self.gestor.configuracion - titulo += " - %s" % conf.jugador + # titulo += " - %s" % conf.jugador self.setWindowTitle(titulo) diff --git a/Code/QT/PantallaDirector.py b/Code/QT/PantallaDirector.py index a989326..218b5f4 100644 --- a/Code/QT/PantallaDirector.py +++ b/Code/QT/PantallaDirector.py @@ -1039,4 +1039,4 @@ def mouseReleaseEvent(self, event): def terminar(self): if self.w: self.w.terminar() - self.w = None \ No newline at end of file + self.w = None diff --git a/Code/QT/PantallaEntMaq.py b/Code/QT/PantallaEntMaq.py index 05b2525..0013629 100644 --- a/Code/QT/PantallaEntMaq.py +++ b/Code/QT/PantallaEntMaq.py @@ -185,7 +185,6 @@ def _label(lyG, txt, ly, rutinaCHB=None, siCheck=False): gbThoughtOp = Controles.GB(self, _("Thought of the opponent"), ly) gbThoughtOp.setStyleSheet(gbStyle) - ly = Colocacion.V().espacio(16).control(self.gbTutor).espacio(16).control(gbThoughtOp) ly.espacio(16).control(self.cbAtras).control(self.chbSummary) gb = Controles.GB(self, "", ly) diff --git a/Code/QT/PantallaGM.py b/Code/QT/PantallaGM.py index 533ca73..562edbf 100644 --- a/Code/QT/PantallaGM.py +++ b/Code/QT/PantallaGM.py @@ -691,6 +691,7 @@ def importarGM(ownerGM, siWoman): return False + class SelectGame(QTVarios.WDialogo): def __init__(self, wgm, ogm, siWoman): self.ogm = ogm diff --git a/Code/QT/PantallaKibitzers.py b/Code/QT/PantallaKibitzers.py index 2d9d4e1..3efa503 100644 --- a/Code/QT/PantallaKibitzers.py +++ b/Code/QT/PantallaKibitzers.py @@ -1,7 +1,10 @@ +import os + from PyQt4 import QtGui from Code import Kibitzers from Code import EngineThread +from Code import Books from Code.QT import Colocacion from Code.QT import Columnas from Code.QT import Controles @@ -35,6 +38,7 @@ def __init__(self, wParent, procesador): (_("Copy"), Iconos.Copiar(), self.copy), None, (_("Up"), Iconos.Arriba(), self.up), None, (_("Down"), Iconos.Abajo(), self.down), None, + (_("Polyglot book"), Iconos.Book(), self.polyglot), None, (_("External engines"), Iconos.Motores(), self.ext_engines), None ) tb = Controles.TBrutina(self, liAcciones) @@ -75,6 +79,32 @@ def __init__(self, wParent, procesador): self.gridKibitzers.gotop() + def polyglot(self): + listaLibros = Books.ListaLibros() + listaLibros.recuperaVar(self.configuracion.ficheroBooks) + listaLibros.comprueba() + menu = QTVarios.LCMenu(self) + rondo = QTVarios.rondoPuntos() + for book in listaLibros.lista: + menu.opcion(("book", book), book.nombre, rondo.otro()) + menu.separador() + menu.opcion(("install", None), _("Install new book"), Iconos.Nuevo()) + resp = menu.lanza() + if resp: + orden, book = resp + if orden == "book": + num = self.kibitzers.nuevoPolyglot(book) + self.goto(num) + elif orden == "install": + fbin = QTUtil2.leeFichero(self, listaLibros.path, "bin", titulo=_("Polyglot book")) + if fbin: + listaLibros.path = os.path.dirname(fbin) + nombre = os.path.basename(fbin)[:-4] + book = Books.Libro("P", nombre, fbin, True) + listaLibros.nuevo(book) + listaLibros.guardaVar(self.configuracion.ficheroBooks) + return self.polyglot() + def me_setEditor(self, parent): recno = self.gridValores.recno() key = self.liKibActual[recno][2] @@ -88,7 +118,7 @@ def me_setEditor(self, parent): valor = kibitzer.nombre elif key == "tipo": valor = kibitzer.tipo - if valor == "I": # Indices no se cambian + if valor in "IB": # Indices/books no se cambian return None control = "cb" lista = Kibitzers.Tipos().comboSinIndices() @@ -289,6 +319,7 @@ def actKibitzer(self): return me = self.kibitzers.kibitzer(fila) + tipo = me.tipo self.liKibActual.append((_("Name"), me.nombre, "nombre")) self.liKibActual.append((_("Type"), me.ctipo(), "tipo")) self.liKibActual.append((_("Priority"), me.cpriority(), "prioridad")) @@ -296,19 +327,21 @@ def actKibitzer(self): self.liKibActual.append((_("Analysis of the base position"), str(me.posicionBase), "posicionBase")) self.liKibActual.append((_("Visible in menu"), str(me.visible), "visible")) - self.liKibActual.append((_("Engine"), me.idName, None)) + if tipo != "B": + self.liKibActual.append((_("Engine"), me.idName, None)) - self.liKibActual.append((_("Author"), me.idAuthor, None)) + self.liKibActual.append((_("Author"), me.idAuthor, None)) self.liKibActual.append((_("File"), me.exe, None)) - self.liKibActual.append((_("Information"), me.idInfo, "info")) - - for num, opcion in enumerate(me.liOpciones): - default = opcion.label_default() - label_default = " (%s)" % default if default else "" - valor = str(opcion.valor) - if opcion.tipo in ("check", "button"): - valor = valor.lower() - self.liKibActual.append(("%s%s" % (opcion.nombre, label_default), valor, "opcion,%d" % num)) + if tipo != "B": + self.liKibActual.append((_("Information"), me.idInfo, "info")) + + for num, opcion in enumerate(me.liOpciones): + default = opcion.label_default() + label_default = " (%s)" % default if default else "" + valor = str(opcion.valor) + if opcion.tipo in ("check", "button"): + valor = valor.lower() + self.liKibActual.append(("%s%s" % (opcion.nombre, label_default), valor, "opcion,%d" % num)) class WKibitzerLive(QTVarios.WDialogo): diff --git a/Code/QT/POLines.py b/Code/QT/PantallaOpeningLine.py similarity index 65% rename from Code/QT/POLines.py rename to Code/QT/PantallaOpeningLine.py index cae993e..1506b5a 100644 --- a/Code/QT/POLines.py +++ b/Code/QT/PantallaOpeningLine.py @@ -2,10 +2,8 @@ import os.path import copy - from PyQt4 import QtCore, QtGui -from Code import VarGen from Code import Util from Code import Partida from Code import Analisis @@ -25,287 +23,15 @@ from Code.QT import POLAnalisis from Code.QT import Voyager from Code.QT import FormLayout - - -class WOpeningLines(QTVarios.WDialogo): - def __init__(self, procesador): - - self.procesador = procesador - self.configuracion = procesador.configuracion - self.resultado = None - self.listaOpenings = OpeningLines.ListaOpenings(self.configuracion) - - QTVarios.WDialogo.__init__(self, procesador.pantalla, self.getTitulo(), Iconos.OpeningLines(), "openingLines") - - - 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, siSeleccionMultiple=True) - - sp = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) - - liAcciones = ( - (_("Close"), Iconos.MainMenu(), self.terminar), None, - (_("Edit"), Iconos.Modificar(), self.modificar), None, - (_("New"), Iconos.Nuevo(), self.new), None, - (_("Rename"), Iconos.Modificar(), self.renombrar), None, - (_("Up"), Iconos.Arriba(), self.arriba), - (_("Down"), Iconos.Abajo(), self.abajo), None, - (_("Remove"), Iconos.Borrar(), self.borrar), None, - (_("Reinit"), Iconos.Reiniciar(), self.reiniciar), None, - (_("Folder"), Iconos.File(), self.changeFolder), None, - ) - tb = Controles.TBrutina(self, liAcciones) - - 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) - - lytb = Colocacion.H().control(tb).control(self.wtrain).margen(0) - wtb = QtGui.QWidget() - wtb.setFixedHeight(62) - wtb.setLayout(lytb) - - # Colocamos - - ly = Colocacion.V().control(wtb).control(self.glista).margen(4) - - self.setLayout(ly) - - self.registrarGrid(self.glista) - self.recuperarVideo(anchoDefecto=self.glista.anchoColumnas()+20) - - self.wtrain.setVisible(False) - self.glista.gotop() - - def getTitulo(self): - return "%s [%s]" % (_("Opening lines"), os.path.relpath(self.listaOpenings.folder)) - - - 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() - if len(self.listaOpenings) == 0: - self.wtrain.setVisible(False) - - def changeFolder(self): - nof = _("New opening folder") - base = self.configuracion.folderBaseOpenings - li = [x for x in os.listdir(base) if os.path.isdir(os.path.join(base, x))] - menu = QTVarios.LCMenu(self) - rondo = QTVarios.rondoPuntos() - menu.opcion("", _("Home folder"), Iconos.Home()) - menu.separador() - for x in li: - menu.opcion(x, x, rondo.otro()) - menu.separador() - menu.opcion(":n", nof, Iconos.Nuevo()) - if VarGen.isWindows: - menu.separador() - menu.opcion(":m", _("Direct maintenance"), Iconos.Configurar()) - - resp = menu.lanza() - if resp is not None: - if resp == ":m": - os.startfile(base) - return - - elif resp == ":n": - name = "" - error = "" - while True: - liGen = [FormLayout.separador] - liGen.append((nof + ":", name)) - if error: - liGen.append(FormLayout.separador) - liGen.append((None, error)) - - resultado = FormLayout.fedit(liGen, title=nof, parent=self, - icon=Iconos.OpeningLines(), anchoMinimo=460) - if resultado: - accion, liResp = resultado - name = liResp[0].strip() - if name: - path = os.path.join(base, name) - try: - os.mkdir(path) - except: - error = _("Unable to create this folder") - continue - if not os.path.isdir(path): - continue - break - else: - return - else: - path = os.path.join(base, resp) - - path = os.path.relpath(path) - self.configuracion.folderOpenings = path - self.configuracion.graba() - self.listaOpenings = OpeningLines.ListaOpenings(self.configuracion) - self.glista.refresh() - self.glista.gotop() - if len(self.listaOpenings) == 0: - self.wtrain.setVisible(False) - self.setWindowTitle(self.getTitulo()) - - def arriba(self): - fila = self.glista.recno() - if self.listaOpenings.arriba(fila): - self.glista.goto(fila - 1, 0) - self.glista.refresh() - - def abajo(self): - fila = self.glista.recno() - if self.listaOpenings.abajo(fila): - self.glista.goto(fila + 1, 0) - self.glista.refresh() - - def modificar(self): - recno = self.glista.recno() - if recno >= 0: - self.resultado = self.listaOpenings[recno] - else: - self.resultado = None - self.guardarVideo() - self.accept() - - def gridDobleClick(self, grid, fila, oColumna): - recno = self.glista.recno() - if recno >= 0: - self.modificar() - - def new(self): - si_expl = len(self.listaOpenings) < 4 - if si_expl: - QTUtil2.mensaje(self, _("First you must select the initial moves.")) - w = PantallaAperturas.WAperturas(self, self.configuracion, None) - if w.exec_(): - ap = w.resultado() - pv = ap.a1h8 if ap else "" - name = ap.nombre if ap else "" - else: - return - - if si_expl: - QTUtil2.mensaje(self, _("Secondly you have to choose a name for this opening studio.")) - - name = self.get_nombre(name) - if name: - file = self.listaOpenings.select_filename(name) - self.listaOpenings.new(file, pv, name) - self.resultado = self.listaOpenings[-1] - self.guardarVideo() - self.accept() - - def get_nombre(self, name): - 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].strip() - if name: - return name - return None - - def renombrar(self): - fila = self.glista.recno() - if fila >= 0: - op = self.listaOpenings[fila] - name = self.get_nombre(op["title"]) - if name: - self.listaOpenings.change_title(fila, name) - self.glista.refresh() - - def borrar(self): - li = self.glista.recnosSeleccionados() - if len(li) > 0: - 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]["title"]) - if QTUtil2.pregunta(self, mens): - li.sort(reverse=True) - for fila in li: - del self.listaOpenings[fila] - self.glista.refresh() - - def gridNumDatos(self, grid): - return len(self.listaOpenings) - - def gridDato(self, grid, fila, oColumna): - col = oColumna.clave - op = self.listaOpenings[fila] - if col == "TITLE": - return op["title"] - elif col == "FILE": - return op["file"] - elif col == "NUMLINES": - return op["lines"] - elif col == "BASEPV": - pv = op["pv"] - if pv: - p = Partida.Partida() - p.leerPV(pv) - return p.pgnBaseRAW() - else: - return "" - - 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() - - def terminar(self): - self.guardarVideo() - self.reject() +from Code.QT import PantallaSavePGN class WLines(QTVarios.WDialogo): def __init__(self, procesador, dbop): self.dbop = dbop - title = dbop.gettitle() + self.title = dbop.gettitle() - QTVarios.WDialogo.__init__(self, procesador.pantalla, title, Iconos.OpeningLines(), "studyOpening") + QTVarios.WDialogo.__init__(self, procesador.pantalla, self.title, Iconos.OpeningLines(), "studyOpening") self.procesador = procesador self.configuracion = procesador.configuracion @@ -320,7 +46,8 @@ def __init__(self, procesador, dbop): liAcciones = ( (_("Close"), Iconos.MainMenu(), self.terminar), None, (_("Remove"), Iconos.Borrar(), self.borrar), None, - (_("Import"), Iconos.Mezclar(), self.importar), None, + (_("Import"), Iconos.Import8(), self.importar), None, + (_("Export"), Iconos.Export8(), self.exportar), None, (_("Utilities"), Iconos.Utilidades(), self.utilidades), None, (_("Train"), Iconos.Study(), self.train), None, ) @@ -366,6 +93,34 @@ def __init__(self, procesador, dbop): self.recuperarVideo() + self.last_numlines = 0 + self.show_lines() + + def show_lines(self): + numlines = len(self.dbop) + if numlines != self.last_numlines: + self.setWindowTitle( "%s [%d]" %(self.title, numlines)) + self.last_numlines = numlines + + def exportar(self): + menu = QTVarios.LCMenu(self) + submenu = menu.submenu(_("PGN Format"), Iconos.PGN()) + r = "%s %%s" % _("Result") + submenu.opcion("1-0", r % "1-0", Iconos.Blancas8()) + submenu.opcion("0-1", r % "0-1", Iconos.Negras8()) + submenu.opcion("1/2-1/2", r % "1/2-1/2", Iconos.Tablas8()) + submenu.opcion("", _("Without Result"), Iconos.Gris()) + resp = menu.lanza() + if resp is not None: + w = PantallaSavePGN.WSaveVarios(self, self.configuracion) + if w.exec_(): + ws = PantallaSavePGN.FileSavePGN(self, w.dic_result) + if ws.open(): + ws.um() + self.dbop.exportarPGN(ws, resp) + ws.close() + ws.um_final() + def utilidades(self): menu = QTVarios.LCMenu(self) submenu = menu.submenu(_("Analysis"), Iconos.Analizar()) @@ -373,9 +128,29 @@ def utilidades(self): submenu.separador() submenu.opcion(self.ta_remove, _("Delete all previous analysis"), Iconos.Delete()) menu.separador() + lihistory = self.dbop.lihistory() + if lihistory: + submenu = menu.submenu(_("Backups"), Iconos.Copiar()) + rondo = QTVarios.rondoPuntos() + for history in lihistory[:30]: + h = history + if len(h) > 70: + h = h[:70] + "..." + submenu.opcion(history, h, rondo.otro()) + submenu.separador() + + # submenu = menu.submenu(_("History of this session"), Iconos.Copiar()) resp = menu.lanza() if resp: - resp() + if isinstance(resp, (str, unicode)): + if QTUtil2.pregunta(self, _("Are you sure you want to restore backup %s ?" % ("\n%s" % resp))): + um = QTUtil2.unMomento(self, _("Working...")) + self.dbop.rechistory(resp) + self.glines.refresh() + self.glines.gotop() + um.final() + else: + resp() def ta_massive(self): dicVar = self.configuracion.leeVariables("MASSIVE_OLINES") @@ -465,60 +240,69 @@ def ta_remove(self): tmpBP.cerrar() self.glines.refresh() - def train(self): - if self.train_test(): - menu = QTVarios.LCMenu(self) + menu = QTVarios.LCMenu(self) + trSSP, trEng = self.train_test() + if trSSP: 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()) + if trEng: + menu.opcion("tr_engines", _("With engines"), Iconos.TrainEngines()) + menu.separador() + submenu = menu.submenu(_("Configuration"), Iconos.Configurar()) + if trEng or trSSP: 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() + submenu1 = submenu.submenu(_("Re-create all trainings"), Iconos.Modificar()) + submenu1.opcion("new_ssp", "%s - %s - %s" %(_("Sequential"), _("Static"), _("Positions")), Iconos.TrainSequential()) + submenu1.opcion("new_eng", "With engines", Iconos.TrainEngines()) + + resp = menu.lanza() + if resp is None: + return + if resp.startswith("tr_"): + self.resultado = resp + self.accept() + elif resp == "new_ssp": + self.trainNewSSP() + elif resp == "new_eng": + self.trainNewEngines() + elif resp == "update": + self.trainUpdateAll() def train_test(self): if len(self.dbop) == 0: - return False + return False, False training = self.dbop.training() - if training is None: - return self.trainNew() - return True + trainingEng = self.dbop.trainingEngines() + return training is not None, trainingEng is not None - def trainNew(self): + def trainNewSSP(self): training = self.dbop.training() - if training is None: - color = "WHITE" - random_order = False - max_moves = 0 - else: + color = "WHITE" + random_order = False + max_moves = 0 + + if training is not None: color = training["COLOR"] random_order = training["RANDOM"] max_moves = training["MAXMOVES"] - liGen = [(None, None)] + separador = FormLayout.separador + liGen = [separador] liJ = [(_("White"), "WHITE"), (_("Black"), "BLACK")] config = FormLayout.Combobox(_("Play with"), liJ) liGen.append((config, color)) - liGen.append((None, None)) + liGen.append(separador) liGen.append((_("Random order"), random_order)) - liGen.append((None, None)) + liGen.append(separador) liGen.append((_("Maximum number of moves (0=all)"), max_moves)) resultado = FormLayout.fedit(liGen, title=_("New training"), parent=self, anchoMinimo=360, icon=Iconos.Study()) @@ -531,12 +315,70 @@ def trainNew(self): reg["COLOR"], reg["RANDOM"], reg["MAXMOVES"] = liResp - self.dbop.createTraining(reg, self.procesador) + self.dbop.createTrainingSSP(reg, self.procesador) QTUtil2.mensaje(self, _("The trainings of this opening has been created")) - def trainUpdate(self): + def trainNewEngines(self): + training = self.dbop.trainingEngines() + color = "WHITE" + mandatory = 5 + control = 10 + lost_points = 20 + engine_control = self.configuracion.tutor.clave + engine_time = 5.0 + num_lista = 0 + + if training is not None: + color = training["COLOR"] + mandatory = training.get("MANDATORY", mandatory) + control = training.get("CONTROL", control) + lost_points = training.get("LOST_POINTS", lost_points) + engine_control = training.get("ENGINE_CONTROL", engine_control) + engine_time = training.get("ENGINE_TIME", engine_time) + num_lista = training.get("NUM_LISTA", num_lista) + + separador = FormLayout.separador + liGen = [separador] + + liJ = [(_("White"), "WHITE"), (_("Black"), "BLACK")] + config = FormLayout.Combobox(_("Play with"), liJ) + liGen.append((config, color)) + + liGen.append((_("Mandatory moves") + ":", mandatory)) + liGen.append(separador) + liGen.append((_("Moves until the control") + ":", control)) + liGen.append(separador) + liGen.append((_("Maximum number of centipawns lost to pass control") + ":", lost_points)) + liGen.append(separador) + + licombo = [("%2d. %s" %(n+1, ",".join(x)), n) for n, x in enumerate(self.dbop.listaEngines())] + config = FormLayout.Combobox(_("Bunch of engines"), licombo) + liGen.append((config, num_lista)) + liGen.append(separador) + + config = FormLayout.Combobox(_("Engine that does the control"), self.configuracion.comboMotoresCompleto()) + liGen.append((config, engine_control)) + liGen.append((_("Duration of analysis (secs)") + ":", float(engine_time))) + + resultado = FormLayout.fedit(liGen, title=_("With engines"), parent=self, anchoMinimo=360, icon=Iconos.Study()) + if resultado is None: + return + + accion, liResp = resultado + + reg = {} + + (reg["COLOR"], reg["MANDATORY"], reg["CONTROL"], reg["LOST_POINTS"], reg["NUM_LISTA"], + reg["ENGINE_CONTROL"], reg["ENGINE_TIME"] ) = liResp + + self.dbop.createTrainingEngines(reg, self.procesador) + + QTUtil2.mensaje(self, _("Created")) + + def trainUpdateAll(self): self.dbop.updateTraining(self.procesador) + self.dbop.updateTrainingEngines() QTUtil2.mensaje(self, _("The trainings have been updated")) def addPartida(self, partida): @@ -550,6 +392,7 @@ def addPartida(self, partida): self.glines.refresh() else: QTUtil2.mensError(self, _X("New line must begin with %1", self.partidabase.pgnSP())) + self.show_lines() def partidaActual(self): partida = Partida.Partida() @@ -567,6 +410,7 @@ def voyager2(self, partida): partida = Partida.Partida() partida.recuperaDeTexto(ptxt) self.addPartida(partida) + self.show_lines() def importar(self): menu = QTVarios.LCMenu(self) @@ -604,7 +448,7 @@ def haz_menu(frommenu, part): if resp is None: return tipo, partida = resp - if tipo == "pgn" : + if tipo == "pgn": self.importarPGN(partida) elif tipo == "polyglot": self.importarPolyglot(partida) @@ -619,6 +463,7 @@ def haz_menu(frommenu, part): elif tipo == "ol": fichero, partida = partida self.importarOtra(fichero, partida) + self.show_lines() def importarOtra(self, fichero, partida): um = QTUtil2.unMomento(self) @@ -637,7 +482,10 @@ def importarApertura(self, partida): partida.leerPV(ap.a1h8) self.addPartida(partida) - def importarLeeParam(self, titulo, dicData): + def importarLeeParam(self, titulo): + dicData = self.dbop.getconfig("IMPORTAR_LEEPARAM") + if not dicData: + dicData = {} liGen = [FormLayout.separador] liGen.append((None, _("Select a maximum number of moves (plies)
to consider from each game"))) @@ -649,15 +497,22 @@ def importarLeeParam(self, titulo, dicData): liGen.append((config, dicData.get("SIWHITE", True))) liGen.append(FormLayout.separador) + li = [(_("Only one best move"), True), (_("All best moves"), False)] + config = FormLayout.Combobox(_("Best move"), li) + liGen.append((config, dicData.get("ONLYONE", True))) + liGen.append(FormLayout.separador) + liGen.append((FormLayout.Spinbox(_("Minimum moves must have each line"), 0, 99, 50), dicData.get("MINMOVES", 0))) resultado = FormLayout.fedit(liGen, title=titulo, parent=self, anchoMinimo=360, icon=Iconos.PuntoNaranja()) if resultado: accion, liResp = resultado - depth, siWhite, minMoves = liResp + depth, siWhite, onlyone, minMoves = liResp dicData["DEPTH"] = depth dicData["SIWHITE"] = siWhite + dicData["ONLYONE"] = onlyone dicData["MINMOVES"] = minMoves + self.dbop.setconfig("IMPORTAR_LEEPARAM", dicData) self.configuracion.escVariables("WBG_MOVES", dicData) return dicData return None @@ -665,12 +520,11 @@ def importarLeeParam(self, titulo, dicData): 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) + dicData = self.importarLeeParam(_("Database summary")) if dicData: ficheroSummary = nomfichgames + "_s1" - depth, siWhite, minMoves = dicData["DEPTH"], dicData["SIWHITE"], dicData["MINMOVES"] - self.dbop.importarSummary(self, partida, ficheroSummary, depth, siWhite, minMoves) + depth, siWhite, onlyone, minMoves = dicData["DEPTH"], dicData["SIWHITE"], dicData["ONLYONE"], dicData["MINMOVES"] + self.dbop.importarSummary(self, partida, ficheroSummary, depth, siWhite, onlyone, minMoves) self.glines.refresh() self.glines.gotop() @@ -679,20 +533,33 @@ def importarPolyglot(self, partida): listaLibros.recuperaVar(self.configuracion.ficheroBooks) listaLibros.comprueba() + dicData = self.dbop.getconfig("IMPORT_POLYGLOT") + bookW = listaLibros.lista[0] + bookB = listaLibros.lista[0] + if dicData: + book = listaLibros.buscaLibro(dicData["BOOKW"]) + if book: + bookW = book + book = listaLibros.buscaLibro(dicData["BOOKB"]) + if book: + bookB = book + liGen = [FormLayout.separador] - li = [(book.nombre, book) for book in listaLibros.lista] + li = [(bookx.nombre, bookx) for bookx in listaLibros.lista] config = FormLayout.Combobox(_("Book that plays white side"), li) - liGen.append((config, listaLibros.lista[0])) + liGen.append((config, bookW)) liGen.append(FormLayout.separador) config = FormLayout.Combobox(_("Book that plays black side"), li) - liGen.append((config, listaLibros.lista[0])) + liGen.append((config, bookB)) liGen.append(FormLayout.separador) resultado = FormLayout.fedit(liGen, title=_("Polyglot book"), parent=self, anchoMinimo=360, icon=Iconos.Libros()) if resultado: accion, liResp = resultado bookW, bookB = liResp + dicData = {"BOOKW":bookW.nombre, "BOOKB":bookB.nombre} + self.dbop.setconfig("IMPORT_POLYGLOT", dicData) else: return @@ -700,11 +567,10 @@ def importarPolyglot(self, partida): bookB.polyglot() titulo = bookW.nombre if bookW==bookB else "%s/%s" % (bookW.nombre, bookB.nombre) - dicData = self.configuracion.leeVariables("OPENINGLINES") - dicData = self.importarLeeParam(titulo, dicData) + dicData = self.importarLeeParam(titulo) if dicData: - depth, siWhite, minMoves = dicData["DEPTH"], dicData["SIWHITE"], dicData["MINMOVES"] - self.dbop.importarPolyglot(self, partida, bookW, bookB, titulo, depth, siWhite, minMoves) + depth, siWhite, onlyone, minMoves = dicData["DEPTH"], dicData["SIWHITE"], dicData["ONLYONE"], dicData["MINMOVES"] + self.dbop.importarPolyglot(self, partida, bookW, bookB, titulo, depth, siWhite, onlyone, minMoves) self.glines.refresh() self.glines.gotop() @@ -902,6 +768,7 @@ def borrar_move(self): self.dbop[linea] = partida self.goto_finlinea() + self.show_lines() def borrar(self): tam_dbop = len(self.dbop) @@ -922,10 +789,11 @@ def borrar(self): resp = menu.lanza() if resp == "current": + self.dbop.saveHistory(_("Remove line %d") % (current+1,)) del self.dbop[current] self.goto_inilinea() - else: + elif resp is not None: liGen = [FormLayout.separador] config = FormLayout.Editbox("
" + _("Lines") + "
" + _("By example:") + " -5,8-12,14,19-", @@ -952,13 +820,12 @@ def borrar(self): 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.dbop.removeLines([x-1 for x in li], cli) self.glines.refresh() self.goto_inilinea() um.final() + self.show_lines() def goto_inilinea(self): nlines = len(self.dbop) @@ -1028,11 +895,19 @@ def goto_next_lipv(self, lipv): self.glines.goto(fila, ncol) self.glines.refresh() - def terminar(self): + def procesosFinales(self): + self.dbop.setconfig("WHITEBOTTOM", self.pboard.tablero.siBlancasAbajo) self.tabsanalisis.saveConfig() + self.dbop.close() self.guardarVideo() + + def terminar(self): + self.procesosFinales() self.accept() + def closeEvent(self, event): + self.procesosFinales() + def mueveHumano(self, partida): # Estamos en la misma linea ? # recno = self.glines.recno() @@ -1057,91 +932,7 @@ def mueveHumano(self, partida): self.glines.refresh() self.glines.goto(fila, ncol) - - -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 - 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 + self.show_lines() def study(procesador, fichero): diff --git a/Code/QT/PantallaOpeningLines.py b/Code/QT/PantallaOpeningLines.py new file mode 100644 index 0000000..0c569d6 --- /dev/null +++ b/Code/QT/PantallaOpeningLines.py @@ -0,0 +1,396 @@ +import os +import os.path + +from PyQt4 import QtGui + +from Code import VarGen +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 Grid +from Code.QT import Iconos +from Code.QT import PantallaAperturas +from Code.QT import QTUtil2 +from Code.QT import QTVarios +from Code.QT import Delegados +from Code.QT import FormLayout + + +class WOpeningLines(QTVarios.WDialogo): + def __init__(self, procesador): + + self.procesador = procesador + self.configuracion = procesador.configuracion + self.resultado = None + self.listaOpenings = OpeningLines.ListaOpenings(self.configuracion) + + QTVarios.WDialogo.__init__(self, procesador.pantalla, self.getTitulo(), Iconos.OpeningLines(), "openingLines") + + 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, siSeleccionMultiple=True) + + sp = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + + liAcciones = ( + (_("Close"), Iconos.MainMenu(), self.terminar), None, + (_("Edit"), Iconos.Modificar(), self.modificar), None, + (_("New"), Iconos.Nuevo(), self.new), None, + (_("Copy"), Iconos.Copiar(), self.copy), None, + (_("Rename"), Iconos.Modificar(), self.renombrar), None, + (_("Up"), Iconos.Arriba(), self.arriba), + (_("Down"), Iconos.Abajo(), self.abajo), None, + (_("Remove"), Iconos.Borrar(), self.borrar), None, + (_("Reinit"), Iconos.Reiniciar(), self.reiniciar), None, + (_("Folder"), Iconos.File(), self.changeFolder), None, + ) + tb = Controles.TBrutina(self, liAcciones) + + tb.setSizePolicy(sp) + + liAcciones = ( + (_("Sequential"), Iconos.TrainSequential(), self.tr_sequential), None, + (_("Static"), Iconos.TrainStatic(), self.tr_static), None, + (_("Positions"), Iconos.TrainPositions(), self.tr_positions), None, + (_("With engines"), Iconos.TrainEngines(), self.tr_engines), + ) + self.tbtrain = 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) + + lytb = Colocacion.H().control(tb).control(self.wtrain).margen(0) + wtb = QtGui.QWidget() + wtb.setFixedHeight(62) + wtb.setLayout(lytb) + + # Colocamos + + ly = Colocacion.V().control(wtb).control(self.glista).margen(4) + + self.setLayout(ly) + + self.registrarGrid(self.glista) + self.recuperarVideo(anchoDefecto=self.glista.anchoColumnas()+20) + + self.wtrain.setVisible(False) + self.glista.gotop() + + def getTitulo(self): + return "%s [%s]" % (_("Opening lines"), os.path.relpath(self.listaOpenings.folder)) + + def tr_(self, tipo): + recno = self.glista.recno() + op = self.listaOpenings[recno] + op["TRAIN"] = tipo + self.resultado = op + self.terminar() + + def tr_sequential(self): + self.tr_("sequential") + + def tr_static(self): + self.tr_("static") + + def tr_positions(self): + self.tr_("positions") + + def tr_engines(self): + self.tr_("engines") + + def reiniciar(self): + self.listaOpenings.reiniciar() + self.glista.refresh() + self.glista.gotop() + if len(self.listaOpenings) == 0: + self.wtrain.setVisible(False) + + def changeFolder(self): + nof = _("New opening folder") + base = self.configuracion.folderBaseOpenings + li = [x for x in os.listdir(base) if os.path.isdir(os.path.join(base, x))] + menu = QTVarios.LCMenu(self) + rondo = QTVarios.rondoPuntos() + menu.opcion("", _("Home folder"), Iconos.Home()) + menu.separador() + for x in li: + menu.opcion(x, x, rondo.otro()) + menu.separador() + menu.opcion(":n", nof, Iconos.Nuevo()) + if VarGen.isWindows: + menu.separador() + menu.opcion(":m", _("Direct maintenance"), Iconos.Configurar()) + + resp = menu.lanza() + if resp is not None: + if resp == ":m": + os.startfile(base) + return + + elif resp == ":n": + name = "" + error = "" + while True: + liGen = [FormLayout.separador] + liGen.append((nof + ":", name)) + if error: + liGen.append(FormLayout.separador) + liGen.append((None, error)) + + resultado = FormLayout.fedit(liGen, title=nof, parent=self, + icon=Iconos.OpeningLines(), anchoMinimo=460) + if resultado: + accion, liResp = resultado + name = liResp[0].strip() + if name: + path = os.path.join(base, name) + try: + os.mkdir(path) + except: + error = _("Unable to create this folder") + continue + if not os.path.isdir(path): + continue + break + else: + return + else: + path = os.path.join(base, resp) + + path = os.path.relpath(path) + self.configuracion.folderOpenings = path + self.configuracion.graba() + self.listaOpenings = OpeningLines.ListaOpenings(self.configuracion) + self.glista.refresh() + self.glista.gotop() + if len(self.listaOpenings) == 0: + self.wtrain.setVisible(False) + self.setWindowTitle(self.getTitulo()) + + def arriba(self): + fila = self.glista.recno() + if self.listaOpenings.arriba(fila): + self.glista.goto(fila - 1, 0) + self.glista.refresh() + + def abajo(self): + fila = self.glista.recno() + if self.listaOpenings.abajo(fila): + self.glista.goto(fila + 1, 0) + self.glista.refresh() + + def modificar(self): + recno = self.glista.recno() + if recno >= 0: + self.resultado = self.listaOpenings[recno] + else: + self.resultado = None + self.guardarVideo() + self.accept() + + def gridDobleClick(self, grid, fila, oColumna): + recno = self.glista.recno() + if recno >= 0: + self.modificar() + + def new(self): + si_expl = len(self.listaOpenings) < 4 + if si_expl: + QTUtil2.mensaje(self, _("First you must select the initial moves.")) + w = PantallaAperturas.WAperturas(self, self.configuracion, None) + if w.exec_(): + ap = w.resultado() + pv = ap.a1h8 if ap else "" + name = ap.nombre if ap else "" + else: + return + + if si_expl: + QTUtil2.mensaje(self, _("Secondly you have to choose a name for this opening studio.")) + + name = self.get_nombre(name) + if name: + file = self.listaOpenings.select_filename(name) + self.listaOpenings.new(file, pv, name) + self.resultado = self.listaOpenings[-1] + self.guardarVideo() + self.accept() + + def copy(self): + recno = self.glista.recno() + if recno >= 0: + self.listaOpenings.copy(recno) + self.glista.refresh() + + def get_nombre(self, name): + 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].strip() + if name: + return name + return None + + def renombrar(self): + fila = self.glista.recno() + if fila >= 0: + op = self.listaOpenings[fila] + name = self.get_nombre(op["title"]) + if name: + self.listaOpenings.change_title(fila, name) + self.glista.refresh() + + def borrar(self): + li = self.glista.recnosSeleccionados() + if len(li) > 0: + 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]["title"]) + if QTUtil2.pregunta(self, mens): + li.sort(reverse=True) + for fila in li: + del self.listaOpenings[fila] + recno = self.glista.recno() + self.glista.refresh() + if recno >= len(self.listaOpenings): + self.glista.gobottom() + + def gridNumDatos(self, grid): + return len(self.listaOpenings) + + def gridDato(self, grid, fila, oColumna): + col = oColumna.clave + op = self.listaOpenings[fila] + if col == "TITLE": + return op["title"] + elif col == "FILE": + return op["file"] + elif col == "NUMLINES": + return op["lines"] + elif col == "BASEPV": + pv = op["pv"] + if pv: + p = Partida.Partida() + p.leerPV(pv) + return p.pgnBaseRAW() + else: + return "" + + def gridCambiadoRegistro(self, grid, fila, columna): + ok_ssp = False + ok_eng = False + if fila >= 0: + op = self.listaOpenings[fila] + ok_ssp = op.get("withtrainings", False) + ok_eng = op.get("withtrainings_engine", False) + + if ok_ssp or ok_eng: + self.wtrain.setVisible(True) + self.tbtrain.setAccionVisible(self.tr_sequential, ok_ssp) + self.tbtrain.setAccionVisible(self.tr_static, ok_ssp) + self.tbtrain.setAccionVisible(self.tr_positions, ok_ssp) + self.tbtrain.setAccionVisible(self.tr_engines, ok_eng) + else: + self.wtrain.setVisible(False) + def closeEvent(self, event): # Cierre con X + self.guardarVideo() + + def terminar(self): + self.guardarVideo() + self.accept() + + +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 + 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 + diff --git a/Code/QT/PantallaTorneos.py b/Code/QT/PantallaTorneos.py index f7b5e0f..217ce91 100644 --- a/Code/QT/PantallaTorneos.py +++ b/Code/QT/PantallaTorneos.py @@ -183,7 +183,6 @@ def __init__(self, wParent, torneo): lbBookDepth = Controles.LB(self, _("Max depth of book (0=Maximum)") + ": ") self.sbBookDepth = Controles.SB(self, torneo.bookDepth(), 0, 200) - # Posicion inicial lbFEN = Controles.LB(self, _("Initial position") + ": ") self.fen = torneo.fen() diff --git a/Code/QT/QTUtil.py b/Code/QT/QTUtil.py index d35de5d..f6cd498 100644 --- a/Code/QT/QTUtil.py +++ b/Code/QT/QTUtil.py @@ -119,6 +119,7 @@ def escondeWindow(window): window.move(screen.width()*2, 0) return pos + class EscondeWindow: def __init__(self, window): self.window = window @@ -133,6 +134,7 @@ def __exit__(self, type, value, traceback): self.window.move(self.pos) self.window.show() + def colorIcon(xcolor, ancho, alto): color = QtGui.QColor(xcolor) pm = QtGui.QPixmap(ancho, alto) diff --git a/Code/QT/QTUtil2.py b/Code/QT/QTUtil2.py index 9525e73..6ce54ce 100644 --- a/Code/QT/QTUtil2.py +++ b/Code/QT/QTUtil2.py @@ -508,6 +508,15 @@ def mensErrorSobreControl(owner, mens, control): msgBox.exec_() +def mensajeEnPunto(owner, mens, titulo, point, dif=5): + if titulo is None: + titulo = _("Information") + msgBox = QtGui.QMessageBox(QtGui.QMessageBox.Information, titulo, resalta(mens), parent=owner) + msgBox.addButton(_("Continue"), QtGui.QMessageBox.ActionRole) + msgBox.move(point.x()+dif, point.y()+dif) + msgBox.exec_() + + def pregunta(parent, mens, etiSi=None, etiNo=None, si_top=False): msgBox = QtGui.QMessageBox(QtGui.QMessageBox.Question, _("Question"), resalta(mens), parent=parent) if etiSi is None: diff --git a/Code/QT/Tablero.py b/Code/QT/Tablero.py index 5db4156..8cc7bb0 100644 --- a/Code/QT/Tablero.py +++ b/Code/QT/Tablero.py @@ -67,7 +67,6 @@ def __init__(self, parent, confTablero, siMenuVisual=True, siDirector=True): self.blindfold = None self.blindfoldModoPosicion = False - self.siInicializado = False self.ultPosicion = None @@ -636,7 +635,6 @@ def dropEvent(self, event): # self.dispatchDrop(a1h8, str(dato)) # event.setDropAction(QtCore.Qt.IgnoreAction) - def showKeys(self): liKeys = [ (_("ALT") + "-F", _("Flip the board")), @@ -1344,7 +1342,6 @@ def setDispatchMove(self, rutina): if siActiva: piezaSC.setDispatchMove(rutina) - def activaTodas(self): self.siActivasPiezas = True for num, una in enumerate(self.liPiezas): @@ -1469,7 +1466,6 @@ def creaFlechaTutor(self, desdeA1h8, hastaA1h8, factor): bf.forma = "1" bf.posicion.orden = kZvalue_pieza + 1 - flecha = self.creaFlecha(bf) self.liFlechas.append(flecha) flecha.show() diff --git a/Code/QT/Voyager.py b/Code/QT/Voyager.py index 4c981a8..7d11749 100644 --- a/Code/QT/Voyager.py +++ b/Code/QT/Voyager.py @@ -328,9 +328,9 @@ def setPosicion(self, posicion): # if self.posicion.siExistePieza("k") != 1: # QTUtil2.mensError(self, _("King") + "-" + _("Black") + "???") # return - # + # self.actPosicion() - # + # self.fen = self.posicion.fen() # Hace control de enroques y EnPassant # if self.fen == ControlPosicion.FEN_INICIAL: # self.fen = "" diff --git a/Code/QT/WBG_Players.py b/Code/QT/WBG_Players.py index 65fb7cb..d8797de 100644 --- a/Code/QT/WBG_Players.py +++ b/Code/QT/WBG_Players.py @@ -41,7 +41,6 @@ def __init__(self, side, rutina): ply4 = Controles.PB(self, _("%d ply") % 4, self.run_p4, plano=False).anchoFijo(ancho) ply5 = Controles.PB(self, _("%d ply") % 5, self.run_p5, plano=False).anchoFijo(ancho) - self.sbply = Controles.SB(self, 0, 0, 100) self.sbply.capturaCambiado(self.run_p) lbply = Controles.LB(self, _("Plies")) @@ -588,11 +587,9 @@ def ordena(empieza, nivel): um.final() - self.data = data self.gridOpeningWhite.refresh() self.gridOpeningBlack.refresh() self.gridMovesWhite.refresh() self.gridMovesBlack.refresh() - diff --git a/Code/QT/WBase.py b/Code/QT/WBase.py index 0727613..06b36b1 100644 --- a/Code/QT/WBase.py +++ b/Code/QT/WBase.py @@ -40,7 +40,6 @@ def __init__(self, parent, gestor): self.conAtajos = True - lyAI = Colocacion.H().relleno(1).control(self.capturas).otroi(lyT).otroi(lyBI).relleno(1).margen(0) ly = Colocacion.V().control(self.tb).relleno().otro(lyAI).relleno().margen(2) @@ -84,7 +83,6 @@ def lanzaAtajosALT(self, key): if self.conAtajos: self.gestor.lanzaAtajosALT(key) - def creaTablero(self): ae = QTUtil.altoEscritorio() mx = 64 if ae >= 750 else 48 @@ -112,7 +110,6 @@ def ponWhiteBlack(self, white, black): oColumnas.liColumnas[1].cabecera = white if white else _("White") oColumnas.liColumnas[2].cabecera = black if black else _("Black") - def creaBloqueInformacion(self): configuracion = self.gestor.configuracion nAnchoPgn = configuracion.anchoPGN @@ -450,7 +447,6 @@ def gridDato(self, grid, fila, oColumna): return pgn, color, info, indicadorInicial, stNAGS - def gridPonValor(self, grid, fila, oColumna, valor): pass diff --git a/Code/RunKibitzer.py b/Code/RunKibitzer.py index 25f24ad..8155d1b 100644 --- a/Code/RunKibitzer.py +++ b/Code/RunKibitzer.py @@ -14,6 +14,11 @@ from Code import Configuracion from Code import Partida from Code import EngineThread +from Code import Util +from Code import VarGen +from Code import XMotorRespuesta +from Code import Kibitzers +from Code import Books from Code.QT import Colocacion from Code.QT import Columnas from Code.QT import Controles @@ -24,11 +29,8 @@ from Code.QT import QTUtil2 from Code.QT import QTVarios from Code.QT import Tablero +from Code.QT import Delegados from Code.QT import PantallaKibitzers -from Code import Util -from Code import VarGen -from Code import XMotorRespuesta -from Code import Kibitzers CONFIGURACION = "C" FEN = "F" @@ -36,6 +38,294 @@ COPYCLIPBOARD = "P" +class VentanaPolyglot(QtGui.QDialog): + def __init__(self, cpu): + QtGui.QDialog.__init__(self) + + self.cpu = cpu + + dicVideo = self.cpu.dic_video + if not dicVideo: + dicVideo = {} + + self.siTop = dicVideo.get("SITOP", True) + self.siShowTablero = dicVideo.get("SHOW_TABLERO", True) + self.posicion = ControlPosicion.ControlPosicion() + + self.fen = "" + self.siPlay = True + + self.setWindowTitle(cpu.titulo) + self.setWindowIcon(Iconos.Book()) + + self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowMinimizeButtonHint) + + self.setBackgroundRole(QtGui.QPalette.Light) + + configuracion = VarGen.configuracion = cpu.configuracion + + VarGen.todasPiezas = Piezas.TodasPiezas() + confTablero = cpu.configuracion.confTablero("kib" + cpu.kibitzer.huella, 24) + self.tablero = Tablero.Tablero(self, confTablero) + self.tablero.crea() + Delegados.generaPM(self.tablero.piezas) + + book = Books.Libro("P", cpu.kibitzer.nombre, cpu.kibitzer.exe, True) + self.book = book + book.polyglot() + self.li_moves = [] + + self.siFigurines = configuracion.figurinesPGN + + oColumnas = Columnas.ListaColumnas() + 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) + self.grid_moves.tipoLetra(puntos=configuracion.puntosPGN) + self.grid_moves.ponAltoFila(configuracion.altoFilaPGN) + + liAcciones = ( + (_("Quit"), Iconos.Kibitzer_Terminar(), self.terminar), + (_("Continue"), Iconos.Kibitzer_Continuar(), self.play), + (_("Pause"), Iconos.Kibitzer_Pausa(), self.pause), + (_("Board"), Iconos.Tablero(), self.confTablero), + ("%s: %s" % (_("Enable"), _("window on top")), Iconos.Top(), self.windowTop), + ("%s: %s" % (_("Disable"), _("window on top")), Iconos.Bottom(), self.windowBottom), + ) + self.tb = Controles.TBrutina(self, liAcciones, siTexto=False, tamIcon=16) + self.tb.setAccionVisible(self.play, False) + + ly1 = Colocacion.H().control(self.tb) + ly2 = Colocacion.V().otro(ly1).control(self.grid_moves) + + layout = Colocacion.H().control(self.tablero).otro(ly2) + self.setLayout(layout) + + self.timer = QtCore.QTimer(self) + self.connect(self.timer, QtCore.SIGNAL("timeout()"), cpu.compruebaInput) + self.timer.start(200) + + if not self.siShowTablero: + self.tablero.hide() + self.recuperarVideo(dicVideo) + self.ponFlags() + + def ponFen(self, fen): + self.posicion = ControlPosicion.ControlPosicion() + self.posicion.leeFen(fen) + self.fen = fen + + if self.siPlay: + self.siW = self.posicion.siBlancas + self.centipawns = self.cpu.configuracion.centipawns + + self.tablero.ponPosicion(self.posicion) + self.li_moves = self.book.almListaJugadas(fen) + for alm in self.li_moves: + alm.nivel = 0 + alm.dato = [""] * 20 + alm.dato[0] = alm.pgn + alm.dato[1] = alm.porc + alm.dato[2] = "%d" % alm.weight + self.grid_moves.gotop() + self.grid_moves.refresh() + self.ponFlecha(0) + + def ponFlags(self): + if self.siTop: + flags = self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint + else: + flags = self.windowFlags() & ~QtCore.Qt.WindowStaysOnTopHint + self.setWindowFlags(flags) + self.tb.setAccionVisible(self.windowTop, not self.siTop) + self.tb.setAccionVisible(self.windowBottom, self.siTop) + self.show() + + def windowTop(self): + self.siTop = True + self.ponFlags() + + def windowBottom(self): + self.siTop = False + self.ponFlags() + + def terminar(self): + self.finalizar() + self.accept() + + def pause(self): + self.siPlay = False + self.tb.setPosVisible(1, True) + self.tb.setPosVisible(2, False) + + def play(self): + self.siPlay = True + self.tb.setPosVisible(1, False) + self.tb.setPosVisible(2, True) + self.ponFen(self.fen) + + def siAnalizar(self): + siW = " w " in self.fen + if not self.siPlay or \ + (siW and (not self.siBlancas)) or \ + ((not siW) and (not self.siNegras)): + return False + return True + + def color(self): + menu = QTVarios.LCMenu(self) + menu.opcion("blancas", _("White"), Iconos.PuntoNaranja()) + menu.opcion("negras", _("Black"), Iconos.PuntoNegro()) + menu.opcion("blancasnegras", "%s + %s" % (_("White"), _("Black")), Iconos.PuntoVerde()) + resp = menu.lanza() + if resp: + self.siNegras = True + self.siBlancas = True + if resp == "blancas": + self.siNegras = False + elif resp == "negras": + self.siBlancas = False + if self.siAnalizar(): + self.ponFen(self.fen) + + def closeEvent(self, event): + self.finalizar() + + def finalizar(self): + self.guardarVideo() + + def guardarVideo(self): + dic = {} + + pos = self.pos() + dic["_POSICION_"] = "%d,%d" % (pos.x(), pos.y()) + + tam = self.size() + dic["_SIZE_"] = "%d,%d" % (tam.width(), tam.height()) + + # dic["SHOW_TABLERO"] = self.siShowTablero + # dic["NARROWS"] = self.nArrows + + dic["SITOP"] = self.siTop + + self.cpu.save_video(dic) + + def recuperarVideo(self, dicVideo): + if dicVideo: + wE, hE = QTUtil.tamEscritorio() + x, y = dicVideo["_POSICION_"].split(",") + x = int(x) + y = int(y) + if not (0 <= x <= (wE - 50)): + x = 0 + if not (0 <= y <= (hE - 50)): + y = 0 + self.move(x, y) + if "_SIZE_" not in dicVideo: + w, h = self.width(), self.height() + for k in dicVideo: + if k.startswith("_TAMA"): + w, h = dicVideo[k].split(",") + else: + w, h = dicVideo["_SIZE_"].split(",") + w = int(w) + h = int(h) + if w > wE: + w = wE + elif w < 20: + w = 20 + if h > hE: + h = hE + elif h < 20: + h = 20 + self.resize(w, h) + + def gridNumDatos(self, grid): + return len(self.li_moves) + + def gridDato(self, grid, fila, oColumna): + mv = self.li_moves[fila] + li = mv.dato + key = int(oColumna.clave) + pgn = li[key] + 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) + self.grid_moves.refresh() + + def gridBotonDerecho(self, grid, fila, columna, modificadores): + self.borra_subnivel(fila) + self.grid_moves.refresh() + + def gridCambiadoRegistro(self, grid, fila, oColumna): + self.ponFlecha(fila) + + def ponFlecha(self, fila): + if fila < len(self.li_moves): + alm = self.li_moves[fila] + self.tablero.ponFlechaSC(alm.desde, alm.hasta) + + def borra_subnivel(self, fila): + alm = self.li_moves[fila] + nv = alm.nivel + if nv == 0: + return + li = [] + for x in range(fila, 0, -1): + alm1 = self.li_moves[x] + if alm1.nivel < nv: + break + li.append(x) + for x in range(fila+1, len(self.li_moves)): + alm1 = self.li_moves[x] + if alm1.nivel < nv: + break + li.append(x) + li.sort(reverse=True) + for x in li: + del self.li_moves[x] + + def lee_subnivel(self, fila): + alm_base = self.li_moves[fila] + if alm_base.nivel >= 17: + return + LCEngine.setFen(alm_base.fen) + if LCEngine.movePV(alm_base.desde, alm_base.hasta, alm_base.coronacion): + fen = LCEngine.getFen() + for alm in self.book.almListaJugadas(fen): + nv = alm.nivel = alm_base.nivel + 1 + alm.dato = [""] * 20 + alm.dato[nv] = alm.pgn + alm.dato[nv+1] = alm.porc + alm.dato[nv+2] = "%d" % alm.weight + fila += 1 + self.li_moves.insert(fila, alm) + + def confTablero(self): + self.pause() + menu = QTVarios.LCMenu(self) + if self.siShowTablero: + menu.opcion("hide", _("Hide"), Iconos.PuntoNaranja()) + else: + menu.opcion("show", _("Show"), Iconos.PuntoNaranja()) + resp = menu.lanza() + if resp: + if resp == "hide": + self.siShowTablero = False + self.tablero.hide() + elif resp == "show": + self.siShowTablero = True + self.tablero.show() + self.guardarVideo() + self.play() + + class VentanaMultiPV(QtGui.QDialog): def __init__(self, cpu): QtGui.QDialog.__init__(self) @@ -1667,7 +1957,8 @@ def procesa(self, orden): self.titulo = self.kibitzer.nombre - self.configMotor = self.kibitzer.configMotor() + if self.kibitzer.tipo != "B": + self.configMotor = self.kibitzer.configMotor() self.key_video = "KIB%s" % self.kibitzer.huella self.dic_video = self.configuracion.restore_video(self.key_video) @@ -1716,6 +2007,8 @@ def lanzaVentana(self): self.ventana = VentanaMultiPV(self) elif self.tipo == "E": self.ventana = VentanaStockfishEval(self) + elif self.tipo == "B": + self.ventana = VentanaPolyglot(self) self.ventana.show() VarGen.gc = QTUtil.GarbageCollector() diff --git a/Code/SQL/DBF.py b/Code/SQL/DBF.py index 98f5940..d489aee 100644 --- a/Code/SQL/DBF.py +++ b/Code/SQL/DBF.py @@ -442,6 +442,7 @@ def soloGrabar(self, dicNuevo, siCommit=False): values = values[:-1] cSQL = "insert into %s(%s) values(%s)" % (self.ctabla, campos, values) + self.cursor.execute(cSQL, liValues) if siCommit: diff --git a/Code/Tacticas.py b/Code/Tacticas.py index f3689d8..233b10d 100644 --- a/Code/Tacticas.py +++ b/Code/Tacticas.py @@ -8,16 +8,15 @@ class BaseTactica: def __init__(self): - self.PUZZLES = 999 # Max number of puzzles in each block - self.JUMPS = [] # Puzzle repetitions, each puzzle can be repeated, this field determine separations among replicates, more repetitions are separated by comma, eg 3,5,7 + self.PUZZLES = 100 # Max number of puzzles in each block + self.JUMPS = [3, 5, 9, 17] # Puzzle repetitions, each puzzle can be repeated, this field determine separations among replicates, more repetitions are separated by comma, eg 3,5,7 self.FILLEND = 0 # Si los flecos que quedan al final se rellenan con los puzzles mas antiguos,por orden - self.REPEAT = [ - 0, ] # Block repetitions, Repetitions of total of puzzles, comma separated, indicating order of repetition as 0=original, 1=random, 2=previous, eg 1,2,0=3 repetitions, + self.REPEAT = [0, 1] # Block repetitions, Repetitions of total of puzzles, comma separated, indicating order of repetition as 0=original, 1=random, 2=previous, eg 1,2,0=3 repetitions, # first is random, second repeat previous, and third original. Total field in blanck is the same as 0 # Penalties, divided in blocks, by example 1,3,5,7 means first 25% # (100%/4) of puzzles has one position of penalty when error, second 25% # three and so on. Blank means no penalties. - self.PENALIZATION = [] + self.PENALIZATION = [1, 2, 3, 4] self.SHOWTEXT = [1, ] # Text while training, in blocks like penalties, 1,0,0,0, 25% Yes, rest No self.POINTVIEW = 0 # El que corresponda, 1 = White 2 = Black self.REFERENCE = "" @@ -42,7 +41,7 @@ def leeREFERENCE(dic, default=""): def leeJUMPS(dic, default=None): - JUMPS = [] if default is None else default + JUMPS = [3, 5, 9, 17] if default is None else default c = dic.get("JUMPS", None) if c: JUMPS = [int(x) for x in c.replace(" ", "").split(",")] @@ -58,7 +57,7 @@ def leeFILLEND(dic, default=None): def leeREPEAT(dic, default=None): - REPEAT = [0, ] if default is None else default + REPEAT = [0, 1] if default is None else default c = dic.get("REPEAT", None) if c: REPEAT = [int(x) for x in c.replace(" ", "").split(",")] @@ -66,7 +65,7 @@ def leeREPEAT(dic, default=None): def leePENALIZATION(dic, default=None): - PENALIZATION = [] if default is None else default + PENALIZATION = [1, 2, 3, 4] if default is None else default c = dic.get("PENALIZATION", None) if c: PENALIZATION = [int(x) for x in c.replace(" ", "").split(",")] @@ -84,12 +83,12 @@ def leeSHOWTEXT(dic, default=None): def leePUZZLES(dic, default=None): - PUZZLES = 999 if default is None else default + PUZZLES = 100 if default is None else default c = dic.get("PUZZLES", None) if c is not None and c.isdigit(): PUZZLES = int(c) if not PUZZLES: - PUZZLES = 999 + PUZZLES = 100 return PUZZLES @@ -153,7 +152,6 @@ def eligeTactica(self, resp): return Tactica(self, resp) def leeCommon(self): - dic = self.dic["COMMON"] if "COMMON" in self.dic else {} self.PUZZLES = leePUZZLES(dic) @@ -225,6 +223,15 @@ def ponPosActual(self, pos): with self.dbdatos() as db: db["POSACTIVE"] = pos + def siSaltoAutomatico(self): + with self.dbdatos() as db: + siauto = db["AUTOJUMP"] + return False if siauto is None else siauto + + def setSaltoAutomatico(self, siSalto): + with self.dbdatos() as db: + db["AUTOJUMP"] = siSalto + def dbdatos(self): return Util.DicSQL(self.fichero, tabla=self.nombre) diff --git a/Code/Torneo.py b/Code/Torneo.py index 6aa733a..2f4f14a 100644 --- a/Code/Torneo.py +++ b/Code/Torneo.py @@ -371,7 +371,7 @@ def book(self, valor=None): def bookDepth(self, valor=None): if valor is not None: self._bookDepth = valor - return self._bookDepth + return self._bookDepth if self._bookDepth else 0 def fichero(self): if self._nombre: diff --git a/Code/XGestorMotor.py b/Code/XGestorMotor.py index c9df3f5..aaea40c 100644 --- a/Code/XGestorMotor.py +++ b/Code/XGestorMotor.py @@ -365,5 +365,3 @@ def miraListaPV(self, fen, siUna): # lipv = [rm.movimiento() for rm in mrm.liMultiPV] return lipv[0] if siUna else lipv - - diff --git a/GenIconos/Formatos.tema b/GenIconos/Formatos.tema index 70c7791..af81b40 100644 --- a/GenIconos/Formatos.tema +++ b/GenIconos/Formatos.tema @@ -535,6 +535,7 @@ Positions nuvola runMono.png TrainSequential windows8 Running_32px.png TrainStatic windows8 Gymnastics_32px.png TrainPositions windows8 Pullups_32px.png +TrainEngines windows8 Treadmill_32px.png Error gnome 64px-Gnome-process-stop.png @@ -547,3 +548,13 @@ TOLchange gnome edit-redo.png Pack qt4 icon_list-all_circ.png Home nuvola folder_home.png + +Import8 windows8 Add_List_32px.png +Export8 windows8 Download_32px.png + +Tablas8 windows8 Exposure_32px.png + +Blancas8 windows8 Knight_32px_1.png +Negras8 windows8 Knight_32px.png + +Book windows8 Book_32px.png diff --git a/GenIconos/windows8/Add_List_32px.png b/GenIconos/windows8/Add_List_32px.png new file mode 100644 index 0000000..c31370e Binary files /dev/null and b/GenIconos/windows8/Add_List_32px.png differ diff --git a/GenIconos/windows8/Book_32px.png b/GenIconos/windows8/Book_32px.png new file mode 100644 index 0000000..fad502d Binary files /dev/null and b/GenIconos/windows8/Book_32px.png differ diff --git a/GenIconos/windows8/Download_32px.png b/GenIconos/windows8/Download_32px.png new file mode 100644 index 0000000..df6f89e Binary files /dev/null and b/GenIconos/windows8/Download_32px.png differ diff --git a/GenIconos/windows8/Exposure_32px.png b/GenIconos/windows8/Exposure_32px.png new file mode 100644 index 0000000..e4246c5 Binary files /dev/null and b/GenIconos/windows8/Exposure_32px.png differ diff --git a/GenIconos/windows8/Knight_32px.png b/GenIconos/windows8/Knight_32px.png new file mode 100644 index 0000000..712ae63 Binary files /dev/null and b/GenIconos/windows8/Knight_32px.png differ diff --git a/GenIconos/windows8/Knight_32px_1.png b/GenIconos/windows8/Knight_32px_1.png new file mode 100644 index 0000000..9137371 Binary files /dev/null and b/GenIconos/windows8/Knight_32px_1.png differ diff --git a/GenIconos/windows8/Originals/Download_32px.png b/GenIconos/windows8/Originals/Download_32px.png new file mode 100644 index 0000000..3628fa1 Binary files /dev/null and b/GenIconos/windows8/Originals/Download_32px.png differ diff --git a/GenIconos/windows8/Treadmill_32px.png b/GenIconos/windows8/Treadmill_32px.png new file mode 100644 index 0000000..48e85c0 Binary files /dev/null and b/GenIconos/windows8/Treadmill_32px.png differ diff --git a/IntFiles/Figs/bb.png b/IntFiles/Figs/bb.png index 41159cc..4207e62 100644 Binary files a/IntFiles/Figs/bb.png and b/IntFiles/Figs/bb.png differ diff --git a/IntFiles/Figs/bk.png b/IntFiles/Figs/bk.png index 26ccd07..5cabf24 100644 Binary files a/IntFiles/Figs/bk.png and b/IntFiles/Figs/bk.png differ diff --git a/IntFiles/Figs/bn.png b/IntFiles/Figs/bn.png index 3acfacb..2825893 100644 Binary files a/IntFiles/Figs/bn.png and b/IntFiles/Figs/bn.png differ diff --git a/IntFiles/Figs/bp.png b/IntFiles/Figs/bp.png index b4bf21b..a6b22d8 100644 Binary files a/IntFiles/Figs/bp.png and b/IntFiles/Figs/bp.png differ diff --git a/IntFiles/Figs/bq.png b/IntFiles/Figs/bq.png index 47d6984..cfdfaab 100644 Binary files a/IntFiles/Figs/bq.png and b/IntFiles/Figs/bq.png differ diff --git a/IntFiles/Figs/br.png b/IntFiles/Figs/br.png index 7c2388a..5b87efd 100644 Binary files a/IntFiles/Figs/br.png and b/IntFiles/Figs/br.png differ diff --git a/IntFiles/Figs/wb.png b/IntFiles/Figs/wb.png index 4c7ba4c..5c5afd0 100644 Binary files a/IntFiles/Figs/wb.png and b/IntFiles/Figs/wb.png differ diff --git a/IntFiles/Figs/wk.png b/IntFiles/Figs/wk.png index c5c9a91..7431cf6 100644 Binary files a/IntFiles/Figs/wk.png and b/IntFiles/Figs/wk.png differ diff --git a/IntFiles/Figs/wn.png b/IntFiles/Figs/wn.png index 589246a..7b6b519 100644 Binary files a/IntFiles/Figs/wn.png and b/IntFiles/Figs/wn.png differ diff --git a/IntFiles/Figs/wp.png b/IntFiles/Figs/wp.png index ac4ceb7..cbdd9e5 100644 Binary files a/IntFiles/Figs/wp.png and b/IntFiles/Figs/wp.png differ diff --git a/IntFiles/Figs/wq.png b/IntFiles/Figs/wq.png index e24cdaf..87f4ac7 100644 Binary files a/IntFiles/Figs/wq.png and b/IntFiles/Figs/wq.png differ diff --git a/IntFiles/Figs/wr.png b/IntFiles/Figs/wr.png index e625567..5315f14 100644 Binary files a/IntFiles/Figs/wr.png and b/IntFiles/Figs/wr.png differ diff --git a/IntFiles/Iconos.bin b/IntFiles/Iconos.bin index eeb6ebf..713d82c 100644 Binary files a/IntFiles/Iconos.bin and b/IntFiles/Iconos.bin differ diff --git a/Locale/es/LC_MESSAGES/lucaschess.mo b/Locale/es/LC_MESSAGES/lucaschess.mo index 78e9d2d..e8e27c0 100644 Binary files a/Locale/es/LC_MESSAGES/lucaschess.mo and b/Locale/es/LC_MESSAGES/lucaschess.mo differ diff --git a/Locale/fr/LC_MESSAGES/lucaschess.mo b/Locale/fr/LC_MESSAGES/lucaschess.mo index b83749c..889b998 100644 Binary files a/Locale/fr/LC_MESSAGES/lucaschess.mo and b/Locale/fr/LC_MESSAGES/lucaschess.mo differ diff --git a/Lucas.py b/Lucas.py index f2d7274..4c6ab91 100644 --- a/Lucas.py +++ b/Lucas.py @@ -27,7 +27,6 @@ - import os diff --git a/bug.log b/bug.log index 9979181..b9f345f 100644 --- a/bug.log +++ b/bug.log @@ -1 +1 @@ -Version 11.09 +Version 11.10