## 
## PopBlocks
## Copyright (C) 2009,2010 Germano Fabio
## gefasio@gmail.com - gefa.altervista.org
## 
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
## 

import psp2d
from random import randint
from time import sleep

class Game(object):
    def __init__(self):
        self.intro = psp2d.Image('res\\intro.png')
        ## self.help = psp2d.Image('help.png')
        self.bg = psp2d.Image('res\\bg_suono.png')
        self.font = psp2d.Font('res\\font.png')
        self.font1 = psp2d.Font('res\\font1.png')
        self.daFare = psp2d.Image('res\\daFare.png')
        self.tile = []
        for i in range(1,13):
            self.tile.append(psp2d.Image('res\\tile\\%d.png'%i))
        self.mapTile = (psp2d.Image('res\\map_empty.png'), psp2d.Image('res\\map_full.png'))
        self.screen = psp2d.Screen()
        self.level = 1
        self.score = 0
        
        self.flScore = open('score','r')
        self.highscore = int(self.flScore.read())
        self.flScore.close()
        
        self.gameOver = False
        
        ## This variable determines the map type, that can be Empty or Full. If all slots are full, the
        ## level ends.
        ## Values:
        ## 0 -> Empty; 1 -> Full.
        self.mapType = [[0,0,0],\
                        [0,0,0],\
                        [0,0,0]]

        ## This variable determines if a map slot is occupied.
        ## Values:
        ## 0 -> Not; 1/12 -> The tyte of piece. -per controllare di eliminare i pezzi, controllo qui...
        self.mapOccupied = [[0,0,0],\
                            [0,0,0],\
                            [0,0,0]]
        self.oldMapOccupied = 0
        self.oldXY = [0,0]

        self.current = 0
        self.pieces = []
        for i in range(1,100):
            self.pieces.append(randint(1,3+self.level))
        self.timer = 0
        self.timerGo = False
        
        self.posCurs = [0,'LEFT'] # 0 -> The Y position (0, 1 or 2); 1 -> LEFT or RIGHT.        
        self.oldPad = psp2d.Controller()
        self.__update()
    def __showField(self):
        for i in range(0,3):
            self.screen.blit(self.mapTile[self.mapType[i][0]], 0, 0, 50, 50, 166, {0:98,1:150,2:202}[i], True)
            self.screen.blit(self.mapTile[self.mapType[i][1]], 0, 0, 50, 50, 219, {0:98,1:150,2:202}[i], True)
            self.screen.blit(self.mapTile[self.mapType[i][2]], 0, 0, 50, 50, 272, {0:98,1:150,2:202}[i], True)
    def __showPieces(self):
        for i in range(0,3):
            if self.mapOccupied[i][0] != 0: self.screen.blit(self.tile[self.mapOccupied[i][0]-1], 0, 0, 50, 50, 166, {0:98,1:150,2:202}[i], True)
            if self.mapOccupied[i][1] != 0: self.screen.blit(self.tile[self.mapOccupied[i][1]-1], 0, 0, 50, 50, 219, {0:98,1:150,2:202}[i], True)
            if self.mapOccupied[i][2] != 0: self.screen.blit(self.tile[self.mapOccupied[i][2]-1], 0, 0, 50, 50, 272, {0:98,1:150,2:202}[i], True)
    def __showCursor(self):
        if not self.gameOver:
            if self.posCurs[1] == 'LEFT':
                self.screen.blit(self.tile[self.pieces[self.current]], 0, 0, 50, 50, 110, {0:98,1:150,2:202}[self.posCurs[0]], True)
            elif self.posCurs[1] == 'RIGHT':
                self.screen.blit(self.tile[self.pieces[self.current]], 0, 0, 50, 50, 328, {0:98,1:150,2:202}[self.posCurs[0]], True)
    def __controlPad(self, pad, oldPad):
        if not self.gameOver:
            if pad.down and not oldPad.down and self.posCurs[0] != 2:
                self.posCurs[0] += 1
            elif pad.up and not oldPad.up and self.posCurs[0] != 0:
                self.posCurs[0] -= 1
            if pad.left:
                self.posCurs[1] = 'LEFT'
            elif pad.right:
                self.posCurs[1] = 'RIGHT'
            ## if pad.select: # Shows help
            ##     self.screen.blit(self.help)
            if pad.cross and not oldPad.cross:
                for i in range(0,3):
                    if self.posCurs[1] == 'LEFT' and self.posCurs[0] == i:
                        if self.mapOccupied[i][0] == 0 and self.mapOccupied[i][1] == 0 and self.mapOccupied[i][2] == 0:
                            self.mapOccupied[i][2] = self.pieces[self.current]+1
                            self.current += 1
                        elif self.mapOccupied[i][0] != 0 and self.mapOccupied[i][1] == 0 and self.mapOccupied[i][2] != 0: 
                            self.mapOccupied[i][1] = self.mapOccupied[i][0]
                            self.mapOccupied[i][0] = self.pieces[self.current]+1
                            self.current += 1
                        elif self.mapOccupied[i][0] == 0 and self.mapOccupied[i][1] != 0 and self.mapOccupied[i][2] == 0: #
                            self.mapOccupied[i][2] = self.mapOccupied[i][1]
                            self.mapOccupied[i][1] = self.pieces[self.current]+1
                            self.current += 1
                        elif self.mapOccupied[i][0] == 0 and self.mapOccupied[i][1] != 0 and self.mapOccupied[i][2] != 0:
                            self.mapOccupied[i][0] = self.pieces[self.current]+1
                            self.current += 1
                        elif self.mapOccupied[i][0] != 0 and self.mapOccupied[i][1] != 0 and self.mapOccupied[i][2] == 0:
                            self.mapOccupied[i][2] = self.mapOccupied[i][1]
                            self.mapOccupied[i][1] = self.mapOccupied[i][0]
                            self.mapOccupied[i][0] = self.pieces[self.current]+1
                            self.current += 1
                        elif self.mapOccupied[i][0] == 0 and self.mapOccupied[i][1] == 0 and self.mapOccupied[i][2] != 0:
                            self.mapOccupied[i][1] = self.pieces[self.current]+1
                            self.current += 1
                        elif self.mapOccupied[i][0] != 0 and self.mapOccupied[i][1] == 0 and self.mapOccupied[i][2] == 0:
                            self.mapOccupied[i][2] = self.mapOccupied[i][0]
                            self.mapOccupied[i][0] = 0
                            self.mapOccupied[i][1] = self.pieces[self.current]+1
                            self.current += 1
                    elif self.posCurs[1] == 'RIGHT' and self.posCurs[0] == i:
                        if self.mapOccupied[i][0] == 0 and self.mapOccupied[i][1] == 0 and self.mapOccupied[i][2] == 0:
                            self.mapOccupied[i][0] = self.pieces[self.current]+1
                            self.current += 1
                        elif self.mapOccupied[i][0] != 0 and self.mapOccupied[i][1] == 0 and self.mapOccupied[i][2] != 0: 
                            self.mapOccupied[i][1] = self.mapOccupied[i][2]
                            self.mapOccupied[i][2] = self.pieces[self.current]+1
                            self.current += 1
                        elif self.mapOccupied[i][0] == 0 and self.mapOccupied[i][1] != 0 and self.mapOccupied[i][2] == 0:
                            self.mapOccupied[i][0] = self.mapOccupied[i][1]
                            self.mapOccupied[i][1] = self.pieces[self.current]+1
                            self.current += 1
                        elif self.mapOccupied[i][0] == 0 and self.mapOccupied[i][1] != 0 and self.mapOccupied[i][2] != 0:
                            self.mapOccupied[i][0] = self.mapOccupied[i][1]
                            self.mapOccupied[i][1] = self.mapOccupied[i][2]
                            self.mapOccupied[i][2] = self.pieces[self.current]+1
                            self.current += 1
                        elif self.mapOccupied[i][0] != 0 and self.mapOccupied[i][1] != 0 and self.mapOccupied[i][2] == 0:
                            self.mapOccupied[i][2] = self.pieces[self.current]+1
                            self.current += 1
                        elif self.mapOccupied[i][0] == 0 and self.mapOccupied[i][1] == 0 and self.mapOccupied[i][2] != 0:
                            self.mapOccupied[i][0] = self.mapOccupied[i][2]
                            self.mapOccupied[i][1] = self.pieces[self.current]+1
                            self.mapOccupied[i][2] = 0
                            self.current += 1
                        elif self.mapOccupied[i][0] != 0 and self.mapOccupied[i][1] == 0 and self.mapOccupied[i][2] == 0:
                            self.mapOccupied[i][1] = self.pieces[self.current]+1
                            self.current += 1
        else:
            if pad.start and not oldPad.start:
                self.mapType = [[0,0,0],[0,0,0],[0,0,0]]
                self.mapOccupied = [[0,0,0],[0,0,0],[0,0,0]]
                self.current = 0
                self.level = 1
                self.score = 0
                self.pieces = []
                for i in range(1,100):
                    self.pieces.append(randint(1,3+self.level))
                self.gameOver = False
                sleep(0.3)
    def __controlForWinOrLose(self):
        for i in range(0,3):
            if (self.mapOccupied[0][i] + self.mapOccupied[1][i] != 0) and self.mapOccupied[0][i] == self.mapOccupied[1][i]:
                self.oldMapOccupied = self.mapOccupied[0][i] - 1
                self.oldXY[0] = i
                self.oldXY[1] = 0
                self.mapOccupied[0][i] = 0
                self.mapOccupied[1][i] = 0
                self.mapType[0][i] = 1
                self.mapType[1][i] = 1
                self.score += 6+(self.level*2)
                self.timerGo = True
            if (self.mapOccupied[1][i] + self.mapOccupied[2][i] != 0) and self.mapOccupied[1][i] == self.mapOccupied[2][i]:
                self.oldMapOccupied = self.mapOccupied[1][i] - 1
                self.oldXY[0] = i
                self.oldXY[1] = 1
                self.mapOccupied[1][i] = 0
                self.mapOccupied[2][i] = 0
                self.mapType[1][i] = 1
                self.mapType[2][i] = 1
                self.score += 6+(self.level*2)
                self.timerGo = True
        if not 0 in self.mapType[0] and not 0 in self.mapType[1] and not 0 in self.mapType[2]:
            ## You Won the current level.
            ## Level up.
            self.mapType = [[0,0,0],[0,0,0],[0,0,0]]
            self.mapOccupied = [[0,0,0],[0,0,0],[0,0,0]]
            self.current = 0
            self.pieces = []
            for i in range(1,100):
                self.pieces.append(randint(1,3+self.level))
            self.level += 1
        if not 0 in self.mapOccupied[0] and not 0 in self.mapOccupied[1] and not 0 in self.mapOccupied[2] and not self.gameOver:
            ## You lose.
            self.gameOver = True
            ## Memorizzo, se c'e', il puntaggio massimo.
            if self.score > self.highscore:
                self.flScore = open('score','w')
                self.flScore.write(str(self.score))
                self.flScore.close()
                self.score = self.highscore
            i = 0
            while i < 100:
                self.screen.blit(self.bg)
                self.__showField()
                self.__showPieces()
                self.__showHud(False)
                self.font.drawText(self.screen, i,150,"game".upper())
                self.font.drawText(self.screen, 450-i,150,"over".upper())
                sleep(0.01)
                i += 1
                self.screen.swap()
            
    def __controlTimer(self):
        if self.timerGo == True:
            self.timer += 1 
            if (self.timer > 0 and self.timer < 20) or (self.timer < 50 and self.timer > 30) or (self.timer < 80 and self.timer > 60):
                self.screen.blit(self.tile[self.oldMapOccupied], 0, 0, 50, 50, {0:166,1:219,2:272}[self.oldXY[0]], {0:98,1:150,2:202}[self.oldXY[1]], True)
                self.screen.blit(self.tile[self.oldMapOccupied], 0, 0, 50, 50, {0:166,1:219,2:272}[self.oldXY[0]], {0:98,1:150,2:202}[self.oldXY[1]+1], True)
            elif self.timer > 80:
                self.timer = 0
                self.timerGo = False
    def __showHud(self, mostraGameOver = True):
        ## Shows the next piece...
        self.screen.blit(self.tile[self.pieces[self.current+1]], 0, 0, 50, 50, 11, 27, True)
        self.font.drawText(self.screen, 273, 26, str(self.score))
        self.font.drawText(self.screen, 204, 64, str(self.level))
        self.screen.drawText(423, 72, str(self.highscore), psp2d.Color(255,255,255))
        for i in range(0,3):
            if self.mapType[i][0] == 0:
                self.screen.blit(self.daFare, 0, 0, 4, 4, 237, {0:45,1:50,2:55}[i], True)
            if self.mapType[i][1] == 0:
                self.screen.blit(self.daFare, 0, 0, 4, 4, 242, {0:45,1:50,2:55}[i], True)
            if self.mapType[i][2] == 0:
                self.screen.blit(self.daFare, 0, 0, 4, 4, 247, {0:45,1:50,2:55}[i], True)
        if self.gameOver and mostraGameOver:
            self.font.drawText(self.screen, 100,150,"game".upper())
            self.font.drawText(self.screen, 350,150,"over".upper())
    def __update(self):
        self.tIntro = 0
        ## Shows Intro
        while True:
            self.tIntro += 1
            self.pad = psp2d.Controller()
            self.screen.blit(self.intro)
            if (self.tIntro > 0 and self.tIntro < 60):
                self.font1.drawText(self.screen, 70, 240, 'Press START to begin')
            if self.tIntro > 110:
                self.tIntro = 0
            if self.pad.start:
                ## Begins the game =)
                sleep(1)
                break
            self.screen.swap()
            
        while True:
            ## Debug Mode.
            ## -----------
            ## print self.mapType[0], self.mapOccupied[0]
            ## print self.mapType[1], self.mapOccupied[1]
            ## print self.mapType[2], self.mapOccupied[2]
            ## print self.level,': ',self.score
            ## print "-----------------------------------"
            self.pad = psp2d.Controller()
            self.screen.blit(self.bg)
                    
            self.__showField()
            self.__showCursor()
            self.__showPieces()
            if self.timer == 0:
                self.__controlPad(self.pad, self.oldPad)
            self.__controlForWinOrLose()
            self.__controlTimer()
            self.__showHud()

            self.oldPad = self.pad
            self.screen.swap()

Game()
