#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
Tetris con QDesigner y PyQt4 (pyqt4 preserva el programa libre
mientras que con pyside puede volverse privativo, no use pyside)
sudo apt-get install python-qt4 python-qt4-phonon
Creas la interfaz con QDesigner y la transformas a código con pyuic4
$ pyuic4 interfaz.ui -o interfaz.py

autor: Guillermo Molleda based in work of Jan Bodnar (zetcode.com)
website: guillermo.molleda.com
Modificado: Agosto de 2016 -> 3 jugadores y pyQt4
Falta: tabla records por quincenas
versión android, 1 pantalla móvil y 2 ó 3 pantallas tablet
usar pantalla jugador que no juega para records

"""

#import gi
#gi.require_version('Gst', '1.0')
#from gi.repository import GObject, Gst

#GObject.threads_init()
#Gst.init(None)
from PyQt4.phonon import Phonon

import sys, os, random
#from playsound import playsound
#from wave import open as waveOpen, AFMT_S16_LE, AFMT_S16_BE
from PyQt4 import QtCore, QtGui
from interfaz import *
from agordo import *

class Agordo(QtGui.QDialog): # Agordo: Agordaĵoj Configuración
    def __init__(self, Speed, reiniciarpuntuacion, quieroMusica, sumarPuntos, parent = None):
        QtGui.QDialog.__init__(self, parent) # o super(Agordo, self).__init__(parent)
        self.ventana = QtGui.QDialog(parent) # la ventana se cierra al cerrar el programa principal
        self.ui = Ui_Agordo()    
        self.ui.setupUi(self.ventana)
        
        self.reinPunt = reiniciarpuntuacion[:]
        self.velocidad = Speed[:]
        self.cuantoSumar = sumarPuntos[:]
        self.ui.muziko.setChecked(quieroMusica)

        self.ui.spinBox.setValue(1)
        self.antesSpinBox = 1
        self.ui.checkBox.setChecked(self.reinPunt[0])
        self.ui.horizontalScrollBar.setValue(self.ui.horizontalScrollBar.maximum() - self.velocidad[0]/10)
        self.ponerPuntaje(0)
        self.ui.label.setText(str(self.ui.horizontalScrollBar.maximum() - self.velocidad[0]/10))
        #self.ventana.setWindowTitle(str(Speed[2]))
        self.padre = parent
        #self.ventana.setWindowTitle(u"Agordo - Configuración")
        self.ui.buttonBox.button(QtGui.QDialogButtonBox.Ok).clicked.connect(self.aceptarCambios)
        self.ui.buttonBox.button(QtGui.QDialogButtonBox.Cancel).clicked.connect(self.rechazarCambios)
        #self.ui.pushButton.clicked.connect(self.PulsaPushButton)
        self.ui.spinBox.valueChanged.connect(self.cambioJugador)
        self.ui.horizontalScrollBar.valueChanged.connect(self.cambioVelocidad)
        self.ui.checkBox.stateChanged.connect(self.cambioCheckReiniciar)
        self.ventana.setModal(True) # solamente esta ventana activa.
        self.ventana.exec_() # en realidad esto hace que solo esta ventana sea la activa, show() no desactiva las demás
    
    def ponerPuntaje(self, cual): # Selecciona el radioButton correspondiente
        if self.cuantoSumar[cual] == 0:
            self.ui.radioButton_1.setChecked(True)
        elif self.cuantoSumar[cual] == 1:
            self.ui.radioButton_2.setChecked(True)
        elif self.cuantoSumar[cual] == 2:
            self.ui.radioButton_3.setChecked(True)
        else:
            self.ui.radioButton_4.setChecked(True)
        
    def dimePuntaje(self): # Lee cual es el radioButton chequeado
        if self.ui.radioButton_2.isChecked() == True:
            return 1
        elif self.ui.radioButton_3.isChecked() == True:
            return 2
        elif self.ui.radioButton_4.isChecked() == True:
            return 3
        else:
            return 0
        
    def cambioCheckReiniciar(self, state):
        self.reinPunt[self.antesSpinBox-1] = self.ui.checkBox.isChecked()
        
    def cambioJugador(self, nuevo):
        self.reinPunt[self.antesSpinBox-1] = self.ui.checkBox.isChecked()
        self.velocidad[self.antesSpinBox-1] = (self.ui.horizontalScrollBar.maximum() - self.ui.horizontalScrollBar.value())*10
        self.cuantoSumar[self.antesSpinBox-1] = self.dimePuntaje()
        self.antesSpinBox = nuevo
        
        self.ui.checkBox.setChecked(self.reinPunt[nuevo-1])
        self.ponerPuntaje(nuevo-1)
        self.ui.horizontalScrollBar.setValue(self.ui.horizontalScrollBar.maximum() - self.velocidad[nuevo-1]/10)
        self.ui.label.setText(str(self.ui.horizontalScrollBar.maximum() - self.velocidad[nuevo-1]/10))
        
    def cambioVelocidad(self):
        self.velocidad[self.ui.spinBox.value()-1] = (self.ui.horizontalScrollBar.maximum() - self.ui.horizontalScrollBar.value())*10
        self.ui.label.setText(str(self.ui.horizontalScrollBar.value()))
        
    def aceptarCambios(self):
        self.cuantoSumar[self.antesSpinBox-1] = self.dimePuntaje()
        for i in range(3):
            self.padre.Speed[i] = self.velocidad[i]
            self.padre.reiniciarpuntuacion[i] = self.reinPunt[i]
            self.padre.sumarPuntos[i] = self.cuantoSumar[i]
            self.padre.quieroMusica = self.ui.muziko.isChecked()
        
    def rechazarCambios(self):
        pass

class Tetrominoe(object): # Las figuras por sus nombres
    
    NoShape = 0
    ZShape = 1
    SShape = 2
    LineShape = 3
    TShape = 4
    SquareShape = 5
    LShape = 6
    MirroredLShape = 7


class Shape(object): # Dibujo de las figuras (horizontal, vertical)
    
    coordsTable = (
        ((0, 0),     (0, 0),     (0, 0),     (0, 0)),
        ((0, -1),    (0, 0),     (-1, 0),    (-1, 1)), # ZShape el rojo
        ((0, -1),    (0, 0),     (1, 0),     (1, 1)), # SShape el verde
        ((0, -1),    (0, 0),     (0, 1),     (0, 2)), # LineShape palo largo azul
        ((-1, 0),    (0, 0),     (1, 0),     (0, 1)), # TShape la T corta amarilla
        ((0, 0),     (1, 0),     (0, 1),     (1, 1)), # SquareShape cuadrado morado
        ((-1, -1),   (0, -1),    (0, 0),     (0, 1)), # LShape L celeste
        ((1, -1),    (0, -1),    (0, 0),     (0, 1)) # MirroredLShape L invertida naranja
    )

    def __init__(self):
        
        self.coords = [[0,0] for i in range(4)]
        self.pieceShape = Tetrominoe.NoShape

        self.setShape(Tetrominoe.NoShape)
        

    def shape(self):
        return self.pieceShape
        

    def setShape(self, shape):
        
        table = Shape.coordsTable[shape]
        
        for i in range(4):
            for j in range(2):
                self.coords[i][j] = table[i][j]

        self.pieceShape = shape
        

    def setRandomShape(self): # elige una forma al azar
        self.setShape(random.randint(1, 7))

        
    def x(self, index):
        return self.coords[index][0]

        
    def y(self, index):
        return self.coords[index][1]

        
    def setX(self, index, x):
        self.coords[index][0] = x

        
    def setY(self, index, y):
        self.coords[index][1] = y

        
    def minX(self):
        
        m = self.coords[0][0]
        for i in range(4):
            m = min(m, self.coords[i][0])

        return m

        
    def maxX(self):
        
        m = self.coords[0][0]
        for i in range(4):
            m = max(m, self.coords[i][0])

        return m

        
    def minY(self):
        
        m = self.coords[0][1]
        for i in range(4):
            m = min(m, self.coords[i][1])

        return m

        
    def maxY(self):
        
        m = self.coords[0][1]
        for i in range(4):
            m = max(m, self.coords[i][1])

        return m

        
    def rotateLeft(self):
        
        if self.pieceShape == Tetrominoe.SquareShape: # Si es el cuadrado se deja tal cual es
            return self

        result = Shape() # result será una variable de clase o tipo Shape (forma con 4 cuadraditos)
        result.pieceShape = self.pieceShape # Se le asigna la forma actual
        
        for i in range(4): # Son cuatro cuadritos cada pieza
            
            result.setX(i, self.y(i)) # cuadradito i, cambio su X (setX) por su Y (y(i))
            result.setY(i, -self.x(i)) # cuadradito i, cambio su Y (setY) por su -X (-x(i))

        return result

        
    def rotateRight(self):
        
        if self.pieceShape == Tetrominoe.SquareShape:
            return self

        result = Shape()
        result.pieceShape = self.pieceShape
        
        for i in range(4):
            
            result.setX(i, -self.y(i)) # casi lo mismo, ahora X = -Y
            result.setY(i, self.x(i)) # e Y = -X

        return result
    # Hasta aquí la clase Shape que se encarga de las figuritas en sí mismas.

ADerecho = 230

class Juego(QtGui.QMainWindow):
    def __init__(self, parent=None):
        #QtGui.QMainWindow.__init__(self, parent) # constructor clase padre
        super(Juego,self).__init__() # constructor clase padre
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.actionSalir.triggered.connect(self.salir)
        self.BoardWidth = 10 # El ancho de la ventana se divide en esos cuadritos iguales
        self.BoardHeight = 22 # El alto se divide en esos cuadritos iguales
        self.Speed = [550,300,550] # 50 es muy rápido y 500 muy lento, 300 antes
        self.reiniciarpuntuacion = [False, True, False]
        self.lasTeclas = [ # Pausa, Izq, Der, Abj, Arr, al suelo, baj 1 línea, recomenzar
        [QtCore.Qt.Key_I, QtCore.Qt.Key_A, QtCore.Qt.Key_D, QtCore.Qt.Key_S, QtCore.Qt.Key_W, QtCore.Qt.Key_Q, QtCore.Qt.Key_Z, QtCore.Qt.Key_R],
        [QtCore.Qt.Key_O, QtCore.Qt.Key_H, QtCore.Qt.Key_K, QtCore.Qt.Key_J, QtCore.Qt.Key_U, QtCore.Qt.Key_M, QtCore.Qt.Key_B, QtCore.Qt.Key_Y],
        [QtCore.Qt.Key_P, QtCore.Qt.Key_Left, QtCore.Qt.Key_Right, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up, QtCore.Qt.Key_Enter, QtCore.Qt.Key_Plus, QtCore.Qt.Key_Minus]
        ]
        self.proximaPieza = [Shape(), Shape(), Shape()]
        self.curPiece = [Shape(), Shape(), Shape()]
        self.autor=""
        self.quieroMusica = True
        self.musicaIniciada = False
        self.tboard = [self.ui.frame_2, self.ui.frame_3, self.ui.frame_5]
        self.ui.label_3.setText("")
        self.ui.label_2.setText("")
        self.ui.label.setText("")
        #self.sennalEstadoTetris[str].connect(self.ui.label.setText)
        #self.resize(180, 380)
        self.centrar()
        #self.statusbar = self.statusBar()
        #self.tboard.msg2Statusbar[str].connect(self.statusbar.showMessage)
        #self.msg2Statusbar.emit("paused")
        #self.statusbar.showMessage("AAA") # con b minúscula statusbar
        #self.statusBar().showMessage("AAA") # atento a la B mayúscula.
        self.media_obj = Phonon.MediaObject(self)
        self.musica = 0
        self.media_obj.finished.connect(self.musicaTerminada)
        #playsound('/home/guillermo/Documentos/trabajo/python/pythonaprendo/pyside/Tetris7/aaa.ogg')
        self.setWindowTitle(u'TrioblaTetriso')
        self.ui.groupBox.setTitle(u'Ludanto 1')
        self.ui.groupBox_2.setTitle(u'Ludanto 2')
        self.ui.groupBox_3.setTitle(u'Ludanto 3')
        self.ui.actionNova_ludo_Nuevo_juego.triggered.connect(self.starttres)
        self.ui.action_Agordoj_Ajustes.triggered.connect(self.ajustes)
        self.initBoard()
        #self.show()
        
    def musicaTerminada(self):
        self.ponerMusica(3)
        
    def salir(self):
        self.ponerMusica(-1)
        self.close() # cierra la ventana sys.exit() sirve también
        
    def centrar(self):
        pantalla = QtGui.QDesktopWidget().screenGeometry()
        tamanno = self.geometry()
        self.move((pantalla.width()-tamanno.width())/2, 
            (pantalla.height()-tamanno.height())/2)
    
    def initBoard(self):     
        
        self.timer = [QtCore.QBasicTimer(), QtCore.QBasicTimer(), QtCore.QBasicTimer()] # cronómetro
        self.isWaitingAfterLine = [False, False, False]
        
        self.curX = [0, 0, 0]
        self.curY = [0, 0, 0]
        self.numLinesRemoved = [0, 0, 0] # Número de líneas completadas y borradas
        self.sumarPuntos = [ 1, 1, 1 ] # 0 No suma puntos, 1 suma líneas, 2 suma piezas, 3 suma cuadraditos
        self.losPuntos = [0, 0, 0] # Esta es la puntuación, antes eran las líneas eliminadas
        self.board = [[], [], []] # Matriz del tablero
        
        #self.tboard.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.pintar = False
        self.isStarted = [False, False, False] # Partida ya empezada
        self.isPaused = [False, False, False] # Partida empezada en pausa
        self.clearBoard(0)
        self.clearBoard(1)
        self.clearBoard(2)
        #self.start()
    
    def shapeAt(self, x, y, cual):
        return self.board[cual][(y * self.BoardWidth) + x]
        
    def setShapeAt(self, x, y, shape, cual):
        self.board[cual][(y * self.BoardWidth) + x] = shape
    
    def squareWidth(self): # calcula el ancho de cada cuadrito
        #return self.tboard.contentsRect().width() / (self.BoardWidth)
        return (self.tboard[0].frameRect().width()-10) / (self.BoardWidth)
        
    def squareHeight(self): # calcula el alto de cada cuadrito
        #return self.tboard.contentsRect().height() / (self.BoardHeight)
        return (self.tboard[0].frameRect().height()) / (self.BoardHeight)

    def ajustes(self): # Agordaĵoj
        #self.Speed = [850,250,850] # 50 es muy rápido y 500 muy lento, 300 por defecto
        #self.reiniciarpuntuacion
        #self.lasTeclas = [ # Pausa, Izq, Der, Abj, Arr, al suelo, baj 1 línea, recomenzar 
        #[QtCore.Qt.Key_I, QtCore.Qt.Key_A, QtCore.Qt.Key_D, QtCore.Qt.Key_S, QtCore.Qt.Key_W, QtCore.Qt.Key_X, QtCore.Qt.Key_Z, QtCore.Qt.Key_R],
        #[QtCore.Qt.Key_O, QtCore.Qt.Key_H, QtCore.Qt.Key_K, QtCore.Qt.Key_J, QtCore.Qt.Key_U, QtCore.Qt.Key_M, QtCore.Qt.Key_B, QtCore.Qt.Key_Y],
        #[QtCore.Qt.Key_P, QtCore.Qt.Key_Left, QtCore.Qt.Key_Right, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up, QtCore.Qt.Key_Enter, QtCore.Qt.Key_Plus, QtCore.Qt.Key_Minus]
        #]
        
        #if self.isStarted[0] == False and self.isStarted[1] == False and self.isStarted[2] == False:
        #    Agordo(self.Speed, self.reiniciarpuntuacion, self)
        
        inicialmentepausado = [self.isPaused[0], self.isPaused[1], self.isPaused[2]]
        for cual in range(3):
            if inicialmentepausado[cual] == False:
                self.pause(cual)
        if self.pintar == True:
            self.ponerMusica(0)
        habiaMusica = self.quieroMusica
        Agordo(self.Speed, self.reiniciarpuntuacion, self.quieroMusica, self.sumarPuntos, self)
        if habiaMusica == True and self.quieroMusica == False:
            self.ponerMusica(-1)
        if habiaMusica == False and self.quieroMusica == True:
            if self.pintar == True:
                if self.musicaIniciada == True:
                    self.ponerMusica(3)
                else:
                    self.ponerMusica(2)
        if self.pintar == True:
            self.ponerMusica(1)
        for cual in range(3):
            if inicialmentepausado[cual] == False:
                self.pause(cual)
        
    def pause(self, cual):
        
        if not self.isStarted[cual]:
            return
        
        self.isPaused[cual] = not self.isPaused[cual]
        
        if self.isPaused[cual]:
            self.timer[cual].stop()
            if cual == 2:
                self.ui.label_3.setText(u"Paŭzo")
            elif cual == 1:
                self.ui.label_2.setText(u"Paŭzo")
            else:
                self.ui.label.setText(u"Paŭzo")
            #self.msg2Statusbar.emit("paused") # Lanza la señal con el texto "Pausado"
            
        else:
            self.timer[cual].start(self.Speed[cual], self)
            #self.msg2Statusbar.emit(str(self.numLinesRemoved)) # Lanza la señal con el número de líneas eliminadas hasta ahora.
            self.ponerLcdNumero(cual)
            
        self.tboard[cual].update()
        
    def clearBoard(self, cual):
        
        for i in range(self.BoardHeight * self.BoardWidth):
            self.board[cual].append(Tetrominoe.NoShape)
    
    def starttres(self):
        empezado = self.pintar
        if self.pintar == False:
            self.ponerMusica(2)
        for cual in range(3):
            if self.isStarted[cual] == False:
                if empezado == True:
                    self.curX[cual] = 0
                    self.curY[cual] = 0
                    self.numLinesRemoved[cual] = 0 # Número de líneas completadas y borradas
                    if self.reiniciarpuntuacion[cual] == True:
                        self.losPuntos[cual] = 0  # Esta es la puntuación
                    for m in range(self.BoardHeight):
                        for k in range(self.BoardHeight):
                            for l in range(self.BoardWidth):
                                self.setShapeAt(l, k, self.shapeAt(l, k + 1,cual), cual)
                    
                    self.pintar = True
                    self.isStarted[cual] == True
                    self.isPaused[cual] = False
                self.start(cual) # Inicia una nueva partida
        
    def start(self, cual): # Inicia una nueva partida
        
        if self.isPaused[cual]: # En realidad esto es imposible, porque sin empezar no puede estar pausado
            return

        self.isStarted[cual] = True
        self.pintar = True
        self.isWaitingAfterLine[cual] = False
        self.proximaPieza[cual] = Shape()
        self.proximaPieza[cual].setRandomShape()
        self.clearBoard(cual)
        
        #self.msg2Statusbar.emit(str(self.numLinesRemoved)) # Lanza la señal con el número de líneas eliminadas hasta ahora.
        self.ponerLcdNumero(cual)
        
        self.newPiece(cual)
        self.timer[cual].start(self.Speed[cual], self) # Se pone en marcha el cronómetro para bajar de línea
        
    def newPiece(self, cual):
        
        self.curPiece[cual] = self.proximaPieza[cual]
        self.proximaPieza[cual] = Shape()
        self.proximaPieza[cual].setRandomShape()
        self.curX[cual] = self.BoardWidth / 2 + 1
        self.curY[cual] = self.BoardHeight - 1 + self.curPiece[cual].minY()
        
        if not self.tryMove(self.curPiece[cual], self.curX[cual], self.curY[cual], cual):
            
            self.curPiece[cual].setShape(Tetrominoe.NoShape)
            self.timer[cual].stop()
            self.isStarted[cual] = False
            if cual == 2:
                self.ui.label_3.setText(" F I N I T A")
            elif cual == 1:
                self.ui.label_2.setText(" F I N I T A")
            else:
                self.ui.label.setText(" F I N I T A")
            #self.msg2Statusbar.emit("Game over") # Lanza la señal con el texto de FIN del juego.
        else:
            if self.sumarPuntos[cual] == 2:
                self.losPuntos[cual] = self.losPuntos[cual] + 1
                self.ponerLcdNumero(cual)
            if self.sumarPuntos[cual] == 3:
                self.losPuntos[cual] = self.losPuntos[cual] + 4
                self.ponerLcdNumero(cual)
        
    def tryMove(self, newPiece, newX, newY, cual):
        
        for i in range(4):
            
            x = newX + newPiece.x(i)
            y = newY - newPiece.y(i)
            
            if x < 0 or x >= self.BoardWidth or y < 0 or y >= self.BoardHeight:
                return False
                
            if self.shapeAt(x, y, cual) != Tetrominoe.NoShape:
                return False

        self.curPiece[cual] = newPiece
        self.curX[cual] = newX
        self.curY[cual] = newY
        self.update()
        
        return True
        
    def dibujaProximaPieza(self, painterframe, cual):
        #pass
        if cual == 2:
            rect = self.ui.frame_6.contentsRect() # rect es el recuadro de QFrame.
            frameX = self.ui.frame_6.x()
            frameY = self.ui.frame_6.y()
        elif cual == 1:
            rect = self.ui.frame_4.contentsRect() # rect es el recuadro de QFrame.
            frameX = self.ui.frame_4.x()
            frameY = self.ui.frame_4.y()
        else:
            rect = self.ui.frame.contentsRect() # rect es el recuadro de QFrame.
            frameX = self.ui.frame.x()
            frameY = self.ui.frame.y()
        if self.proximaPieza[cual].shape() != Tetrominoe.NoShape:
            # Dibuja la pieza actual en su sitio
            for i in range(4):
                
                x = self.proximaPieza[cual].x(i)
                y = self.proximaPieza[cual].y(i)
                self.drawSquare(painterframe, 40+cual*ADerecho + x * self.squareWidth(),
                    70 + y * self.squareHeight(),
                    self.proximaPieza[cual].shape())
        
    def paintEvent(self, event):
                
        painter = QtGui.QPainter(self)
        for cual in range(3):
            if self.pintar == True: #isStarted[cual] == True: # Partida ya empezada
                self.dibujaProximaPieza(painter, cual)
                #rect = self.ui.frame_2.contentsRect()
                rect = self.tboard[cual].contentsRect() # rect es el recuadro de esta clase QFrame donde dibujamos todo de tipo QPainter.
                
                # Tenemos dos objetos QPainter, uno de esta función llamado painter y otro del cuadro (QFrame) de nuestro juego Tetris.
                # primero 170 , 150
                #print (self.tboard.y()) # 140, 120
                #print (self.ui.frame.y()) # 20, 20
                #print (self.ui.frame.contentsRect().bottom()) # 109, 89
                #print (self.squareHeight()) # 16, 17
                #print (self.tboard.contentsRect().bottom()) # 359, 379
                #print (self.tboard.contentsRect().top()) # 1, 1
                #print (self.tboard.contentsRect().height()) # 359, 379
                boardTop = self.tboard[cual].y() #rect.bottom() - self.BoardHeight * self.squareHeight() # Calcula la posición Y de arriba del todo.
        
                for i in range(self.BoardHeight): # Vamos a rastrear el tablero desde arriba
                    for j in range(self.BoardWidth): # coordenadas j,i -> (X,Y)
                        shape = self.shapeAt(j, self.BoardHeight - i - 1, cual) # ¿Qué figura hay en ese cuadrito?
                        
                        if shape != Tetrominoe.NoShape: # Si hay una figura (es distinto de NoFigura)
                            self.drawSquare(painter, # Llama a la función que dibuja ese cuadradito en la superficie de esta función llamada painter, la X e Y donde dibujarlo y la forma que toque dibujar.
                                5+cual*ADerecho + j * self.squareWidth(),
                                144 + i * self.squareHeight(), shape)
        
                if self.curPiece[cual].shape() != Tetrominoe.NoShape:
                    # Dibuja la pieza actual en su sitio
                    for i in range(4):
                        
                        x = self.curX[cual] + self.curPiece[cual].x(i)
                        y = self.curY[cual] - self.curPiece[cual].y(i)
                        self.drawSquare(painter, 5+cual*ADerecho + x * self.squareWidth(),
                            144 + (self.BoardHeight - y - 1) * self.squareHeight(),
                            self.curPiece[cual].shape())
        
    def drawSquare(self, painter, x, y, shape):
        
        colorTable = [0x000000, 0xCC6666, 0x66CC66, 0x6666CC,
                      0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00]

        color = QtGui.QColor(colorTable[shape])
        painter.fillRect(x + 1, y + 1, self.squareWidth() - 2, 
            self.squareHeight() - 2, color)

        painter.setPen(color.lighter())
        painter.drawLine(x, y + self.squareHeight() - 1, x, y)
        painter.drawLine(x, y, x + self.squareWidth() - 1, y)

        painter.setPen(color.darker())
        painter.drawLine(x + 1, y + self.squareHeight() - 1,
            x + self.squareWidth() - 1, y + self.squareHeight() - 1)
        painter.drawLine(x + self.squareWidth() - 1, 
            y + self.squareHeight() - 1, x + self.squareWidth() - 1, y + 1)
        
    def timerEvent(self, event):
        pasaalgo = 0
        
        if self.statusBar().currentMessage() == "": # repone autor en la statusbar porque al señalar con el ratón el menú se borraba.
            self.statusBar().showMessage(self.autor)
        
        for cual in range(3):
            if event.timerId() == self.timer[cual].timerId():
                
                if self.isWaitingAfterLine[cual]: # Mira si la pieza NO puede bajar una fila más
                    self.isWaitingAfterLine[cual] = False
                    self.newPiece(cual)
                    
                else: # sí puede bajar
                    self.oneLineDown(cual)
                pasaalgo = 1
                    
        #if not pasaalgo:
        #    super(Board, self).timerEvent(event) # llama al evento de timer de la clase padre de Board en el objeto actual (self). Por si la clase superior hiciera algo con el timer ya que esta clase no lo va a hacer.
        
    def oneLineDown(self, cual):
        
        if not self.tryMove(self.curPiece[cual], self.curX[cual], self.curY[cual] - 1, cual):
            self.pieceDropped(cual)
        
    def pieceDropped(self, cual):
        
        for i in range(4):
            
            x = self.curX[cual] + self.curPiece[cual].x(i)
            y = self.curY[cual] - self.curPiece[cual].y(i)
            self.setShapeAt(x, y, self.curPiece[cual].shape(), cual)

        self.removeFullLines(cual)

        if not self.isWaitingAfterLine[cual]:
            self.newPiece(cual)
        
    def removeFullLines(self, cual):
        
        numFullLines = 0
        rowsToRemove = []

        for i in range(self.BoardHeight):
            
            n = 0
            for j in range(self.BoardWidth):
                if not self.shapeAt(j, i, cual) == Tetrominoe.NoShape:
                    n = n + 1

            if n == 10:
                rowsToRemove.append(i)

        rowsToRemove.reverse()
        

        for m in rowsToRemove:
            
            for k in range(m, self.BoardHeight):
                for l in range(self.BoardWidth):
                        self.setShapeAt(l, k, self.shapeAt(l, k + 1,cual), cual)
        numFullLines = numFullLines + len(rowsToRemove)

        if numFullLines > 0:
            
            self.numLinesRemoved[cual] = self.numLinesRemoved[cual] + numFullLines
            #self.msg2Statusbar.emit(str(self.numLinesRemoved)) # Lanza la señal con el número de líneas eliminadas hasta ahora.
            if self.sumarPuntos[cual] == 1:
                self.losPuntos[cual] = self.losPuntos[cual] + numFullLines
                self.ponerLcdNumero(cual)
            
            self.isWaitingAfterLine[cual] = True
            self.curPiece[cual].setShape(Tetrominoe.NoShape)
            self.update()
            
    def ponerLcdNumero(self, cual):
        if cual == 2:
            self.ui.lcdNumber_3.display(self.losPuntos[cual])
            self.ui.label_3.setText("")
        elif cual == 1:
            self.ui.lcdNumber_2.display(self.losPuntos[cual])
            self.ui.label_2.setText("")
        else:
            self.ui.lcdNumber.display(self.losPuntos[cual])
            self.ui.label.setText("")
        
        
    def dropDown(self, cual):
        
        newY = self.curY[cual]
        
        while newY > 0:
            
            if not self.tryMove(self.curPiece[cual], self.curX[cual], newY - 1, cual):
                break
                
            newY -= 1

        self.pieceDropped(cual)
        
    def keyPressEvent(self, event):
        
        #if not self.isStarted or self.curPiece.shape() == Tetrominoe.NoShape:
        #    super(Juego, self).keyPressEvent(event) # llama al evento de keyPress de la clase padre de Board en el objeto actual (self). Por si la clase superior hiciera algo con la tecla pulsada ya que esta clase no lo va a hacer.
        #    return
        key = event.key()
        evitarPadre = 0
        for cual in range(3):
            if key == self.lasTeclas[cual][0]: # Pausa
                self.pause(cual)
                return
            if not self.isPaused[cual]:
                evitarPadre = evitarPadre + 1
                if key == self.lasTeclas[cual][1]: # Izquierda
                    self.tryMove(self.curPiece[cual], self.curX[cual] - 1, self.curY[cual],cual)
                    
                elif key == self.lasTeclas[cual][2]: # Derecha
                    self.tryMove(self.curPiece[cual], self.curX[cual] + 1, self.curY[cual],cual)
                    
                elif key == self.lasTeclas[cual][3]: # Abajo
                    self.tryMove(self.curPiece[cual].rotateRight(), self.curX[cual], self.curY[cual],cual)
                    
                elif key == self.lasTeclas[cual][4]: # Arriba
                    self.tryMove(self.curPiece[cual].rotateLeft(), self.curX[cual], self.curY[cual],cual)
                    
                elif key == self.lasTeclas[cual][5]: # Al suelo
                    if self.isStarted[cual] == True:
                        self.dropDown(cual)
                    
                elif key == self.lasTeclas[cual][6]: # Bajar una línea
                    if self.isStarted[cual] == True:
                        self.oneLineDown(cual)
                    
                elif key == self.lasTeclas[cual][7]: # Recomenzar
                    if self.isStarted[cual] == False:
                        self.curX[cual] = 0
                        self.curY[cual] = 0
                        if self.reiniciarpuntuacion[cual] == True or self.sumarPuntos[cual] == 2:
                            self.losPuntos[cual] = 0
                        if self.losPuntos[cual] > 1000:
                            self.losPuntos[cual] = 100
                        self.numLinesRemoved[cual] = 0
                        self.ponerLcdNumero(cual)
                        
                        for m in range(self.BoardHeight):
                            for k in range(self.BoardHeight):
                                for l in range(self.BoardWidth):
                                    self.setShapeAt(l, k, self.shapeAt(l, k + 1,cual), cual)
                        
                        self.pintar = True
                        self.isStarted[cual] == True
                        self.isPaused[cual] = False
                        self.start(cual) # Inicia una nueva partida
                    
                else:
                    evitarPadre = evitarPadre - 1
            
        if key == QtCore.Qt.Key_0: # Derecha
            self.tryMove(self.curPiece[2], self.curX[2] + 1, self.curY[2],2)
        
        #if evitarPadre == 0:
        #    super(Juego, self).keyPressEvent(event) # llama al evento de keyPress de la clase padre de Board en el objeto actual (self). Por si la clase superior hiciera algo con la tecla pulsada ya que esta clase no lo va a hacer.
        
    def resizeEvent(self, Event):
        pass
        """
        tam_central = self.ui.centralwidget.frameGeometry() # PySide.QtCore.QRect(0, 27, 582, 503)
        if tam_central.width()/tam_central.height() > 0.58:
            tam_central = QtCore.QRect(0,27,0.58*tam_central.height(),tam_central.height())
        #print (u'frameGeometry')
        #print (tamanno) #       
        #tam_central = self.ui.centralwidget.frameSize()
        #print (u'frameSize')
        #print (tamanno) # PySide.QtCore.QSize(582, 503)
        tamanno = QtCore.QRect(0,0,tam_central.width()-10, tam_central.height()-122) # PySide.QtCore.QSize(0,0,221,381)      
        self.ui.frame_2.setFrameRect(tamanno) # ancho/alto = bien 0,58, mal 1,5
        #self.ui.frame_2.setFrameShape(QtGui.QFrame.Shape.Box)
        """
    
    def ponerMusica(self, hacer): # hacer=0 pausar, 1 tocar
        if self.quieroMusica == False:
            return
        directorioactual = os.path.dirname(os.path.abspath(sys.argv[0]))
        libreriamusical = { u"Robert Schumann – El campesino Alegre":u"08ElCampesinoAlegre.ogg",
            u"Manuel de Falla – La danza del fuego":u"03LaDanzaDelFuego.ogg",
            u"Wolfgang Amadeus Mozart – Fantasía en Re Menor":u"11FantasiaEnReMenor.ogg",
            u"Johann Sebastian Bach – Concierto de Brandenburgo No. 2: Movimiento 1":u"Bach_Brandenburg2.mp3",
            u"Ludwig van Beethoven – Sinfonía No. 5: Primer Movimiento":u"Beethoven_Symphony5.mp3",
            u"Georges Bizet – L'Arlésienne Suite: Farandole":u"Bizet_Larlesienne.mp3",
            u"Johannes Brahms – Danza húngara No. 5":u"Brahms_Hungarian5.mp3",
            u"George Frideric Handel – Música acuática: Hornpipe":u"Handel_HornpipeWM.mp3",
            u"Gustav Holst – Los planetas: Jupiter":u"Holst_Jupiter.mp3",
            u"Felix Mendelssohn – El sueño de una noche de verano: Scherzo":u"Mendelssohn_Midsummer.mp3",
            u"Wolfgang Amadeus Mozart – Piano Sonata No. 11 en La Mayor: Rondo Alla Turca. Marcha Turca":u"Mozart_Turkish.mp3",
            u"Modest Mussorgsky – Cuadros de una exposición: Promenade":u"Mussorgsky_Promenade.mp3",
            u"Jacques Offenbach – Orfeo en los infiernos (Orphée aux enfers): Can-Can":u"Offenbach_CanCan.mp3",
            u"Nikolai Rimsky-Korsakov – El vuelo del moscardón":u"RimskyKorsakov_Bumblebee.mp3",
            u"Franz Schubert – Marche Militaire":u"Schubert_Militaire.mp3",
            u"John Philip Sousa – Barras y estrellas para siempre":u"Sousa_StarsStripes.mp3"
            }
        if hacer == 0: # de play a pausa, 2 porque falla con pyQt4, pero State funciona en pySide
            if self.media_obj.state() == 2: #Phonon.State.PlayingState: # http://pyqt.sourceforge.net/Docs/PyQt4/phonon.html#State-enum
                self.media_obj.pause()
        if hacer == 1: # de pausa a play, 4 porque falla con pyQt4, pero State funciona en pySide
            if self.media_obj.state() == 4: #Phonon.State.PausedState: # http://pyqt.sourceforge.net/Docs/PyQt4/phonon.html#State-enum
                self.media_obj.play()
        if hacer == 2: # iniciar el dispositivo
            self.audio_output = Phonon.AudioOutput(Phonon.MusicCategory, self)
            Phonon.createPath(self.media_obj, self.audio_output)
            self.musicaIniciada = True
            hacer = 3
        if hacer == 3: # empezar una música
            #fichero = u"/home/guillermo/Documentos/trabajo/python/pythonaprendo/pyside/Tetris7/aaa.ogg"
            toca = random.randint(0, len(libreriamusical)-1)
            fichero = os.path.join(directorioactual,libreriamusical.values()[toca])
            self.autor = libreriamusical.keys()[toca]
            self.statusBar().showMessage(self.autor)
            self.media_obj.setCurrentSource(Phonon.MediaSource(fichero))
            #self.media_obj.tick.connect(self.time_change)
            #self.media_obj.totalTimeChanged.connect(self.total_time_change)
            self.media_obj.play()
        if hacer == -1: # parar
            self.media_obj.stop()
    
    """ falta dar velocidad y acompasar el tipo de música al rápido, cada nivel multiplica velocidad * 0,9 cada X piezas
        falta guardar la configuración en un fichero.
    http://www.classicsforkids.com/music/hear.asp
    https://archive.org/details/PianoMusicVol.1ignatiusHenderson
    https://faisalpp.wordpress.com/2015/02/13/pyqtpyside-music-player-in-10-minute/
    fallan https://commons.wikimedia.org/wiki/Category:Ogg_files_of_classical_music_by_composer #fallan
    self.media_obj = Phonon.MediaObject(self)
    self.current_time = 0
        value = self.horizontalSlider.value()
        print value
        self.media_obj.seek(value)
        self.audio_output = Phonon.AudioOutput(Phonon.MusicCategory, self)
        Phonon.createPath(self.media_obj, self.audio_output)
        self.media_obj.setCurrentSource(Phonon.MediaSource(filename))
        self.media_obj.tick.connect(self.time_change)
        self.media_obj.totalTimeChanged.connect(self.total_time_change)
        self.media_obj.play()
    """

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = Juego(None)
    myapp.show()
    sys.exit(app.exec_())
