import sys
from math import floor
from random import randint
import pygame
from pygame.locals import QUIT, MOUSEBUTTONDOWN
#-------------------------------------------
YOKO = 20
TATE = 16
SIZE = 40
NUM_OF_BOMBS = 20
EMPTY = 0
BOMB = 1
OPENED = 2
OPEN_COUNT = 0
CHECKED = [[0 for _ in range(YOKO)] for _ in range(TATE)]
#Copyright 2016 Kenichiro Tanaka
#-------------------------------------------
pygame.init()
SURFACE = pygame.display.set_mode([YOKO*SIZE, TATE*SIZE])
EPSCLOCK = pygame.time.Clock()
#-------------------------------------------
def num_of_bombs(field, x_pos, y_pos):
    count = 0
    for yoffset in range(-1, 2):
        for xoffset in range(-1, 2):
            xp, yp = (x_pos+xoffset, y_pos+yoffset)
            if 0 <= xp < YOKO and 0 <= yp < TATE and field[yp][xp] == BOMB:
                count += 1
    return count
#-------------------------------------------
def open_tile(field, x_pos, y_pos):
    global OPEN_COUNT
    if CHECKED[y_pos][x_pos]:
        return
    #---
    CHECKED[y_pos][x_pos] = True
    #---
    for yoffset in range(-1, 2):
        for xoffset in range(-1, 2):
            xp, yp = (x_pos+xoffset, y_pos+yoffset)
            if 0 <= xp < YOKO and 0 <= yp < TATE and field[yp][xp] == EMPTY:
                field[yp][xp] = OPENED
                OPEN_COUNT += 1
                count = num_of_bombs(field,xp,yp)
                if count == 0 and not (xp == x_pos and yp == y_pos):
                    open_tile(field,xp,yp)
#-------------------------------------------
def main():
    smallfont = pygame.font.SysFont(None, 32)
    largefont = pygame.font.SysFont(None, 80)
    message_clear = largefont.render("CLEAR !!", True, (255, 255, 0))
    message_over = largefont.render("GAME OVER !!", True, (255, 0, 255))
    message_rect = message_clear.get_rect()
    message_rect.center = (YOKO*SIZE/2, TATE*SIZE/2)
    game_over = False
    field = [[EMPTY for xp in range(YOKO)] for yp in range(TATE)]
    count = 0
    #-------------------------------------------
    while count < NUM_OF_BOMBS:
        xp, yp = randint(0, YOKO-1), randint(0, TATE-1)
        if field[yp][xp] == EMPTY:
            field[yp][xp] = BOMB
            count += 1
    #-------------------------------------------
    while True:
        #-------------------------------------------
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            #-------------------------------------------
            if event.type == MOUSEBUTTONDOWN and event.button == 1:
                xp, yp = floor(event.pos[0]/SIZE), floor(event.pos[1]/SIZE)
                if field[yp][xp] == BOMB:
                    game_over = True
                else:
                    open_tile(field,xp,yp)
        #-------------------------------------------
        #--- Graphic part.
        SURFACE.fill((112,192,192))
        for yp in range(TATE):
            for xp in range(YOKO):
                tile = field[yp][xp]
                rect = (xp*SIZE, yp*SIZE, SIZE, SIZE)
                if tile == EMPTY or tile == BOMB:
                    pygame.draw.rect(SURFACE, (222,222,222), rect)
                    if game_over and tile == BOMB:
                        pygame.draw.rect(SURFACE, (200,100,0), rect)
                elif tile == OPENED:
                    count = num_of_bombs(field,xp,yp)
                    if count > 0:
                        num_image = smallfont.render("{}".format(count), True, (255,0,0))
                        SURFACE.blit(num_image, (xp*SIZE+10, yp*SIZE+10))
        #-------------------------------------------
        #--- Lines.
        for index in range(0, YOKO*SIZE, SIZE):
            pygame.draw.line(SURFACE, (96,96,96), (index, 0), (index, TATE*SIZE))
        for index in range(0, TATE*SIZE, SIZE):
            pygame.draw.line(SURFACE, (96,96,96), (0, index), (YOKO*SIZE, index))
        #-------------------------------------------
        if OPEN_COUNT == YOKO*TATE - NUM_OF_BOMBS:
            SURFACE.blit(message_clear, message_rect.topleft)
        elif game_over:
            SURFACE.blit(message_over, message_rect.topleft)
        #-------------------------------------------
        pygame.display.update()
        EPSCLOCK.tick(15)
        #-------------------------------------------
    #-------------------------------------------
#-------------------------------------------
if __name__ == "__main__":
    main()
