import pygame
import random
import time

# ゲーム設定
WIDTH, HEIGHT = 8, 16
BLOCK_SIZE = 40
COLORS = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 0, 255)]
BACKGROUND_COLOR = (0, 0, 0)
GRID_LINE_COLOR = (0, 0, 0)
ANIMATION_DURATION = 15  # ブロックアニメーション間隔（秒）
GRAVITY = 1  # 落下速度
FAST_DROP_MULTIPLIER = 5  # 下矢印キー押下時の落下速度倍率
CHAIN_BONUS = 1.25  # 連鎖ボーナスの倍率
SCORE_INCREMENT = 100  # 消去ブロックごとのスコア増加
FONT_SIZE = 24

pygame.init()
pygame.font.init()
FONT = pygame.font.Font(None, FONT_SIZE)
screen = pygame.display.set_mode((WIDTH * BLOCK_SIZE, HEIGHT * BLOCK_SIZE))
pygame.display.set_caption("Renser")

# ブロッククラス
class Block:
    def __init__(self, color, x, y):
        self.color = color
        self.x = x
        self.y = y

# 落下ブロックペアクラス
class FallingBlockPair:
    def __init__(self, block1, block2):
        self.block1 = block1
        self.block2 = block2

# ブロックペアの生成
def generate_falling_block_pair():
    color1 = random.choice(COLORS)
    color2 = random.choice(COLORS)
    block1 = Block(color1, WIDTH // 2 - 1, 0)
    block2 = Block(color2, WIDTH // 2, 0)
    return FallingBlockPair(block1, block2)

# ブロックペアの移動
def move_falling_block_pair(pair, board, dx, dy):
    if is_valid_move(pair, board, dx, dy):
        pair.block1.x += dx
        pair.block1.y += dy
        pair.block2.x += dx
        pair.block2.y += dy

# ブロックペアの回転
def rotate_falling_block_pair(pair, board, direction):
    block1, block2 = pair.block1, pair.block2
    dx, dy = block1.x - block2.x, block1.y - block2.y
    new_dx, new_dy = -dy * direction, dx * direction

    new_x, new_y = block2.x + new_dx, block2.y + new_dy
    if is_valid_move(pair, board, new_x - block1.x, new_y - block1.y, block_idx=0, ignore_overlap=True):
        block1.x, block1.y = new_x, new_y

# ブロックペアのハードドロップ
def hard_drop_falling_block_pair(pair, board):
    while not place_falling_block_pair(pair, board):
        pair.block1.y += 1
        pair.block2.y += 1

# ブロックペアの配置
def place_falling_block_pair(pair, board):
    if not is_valid_move(pair, board, 0, 1):
        board[pair.block1.y][pair.block1.x] = pair.block1
        board[pair.block2.y][pair.block2.x] = pair.block2
        return True
    return False

# 有効な移動かどうかの判定
def is_valid_move(pair, board, dx, dy, block_idx=None, ignore_overlap=False):
    blocks = [pair.block1, pair.block2] if block_idx is None else [pair.block1] if block_idx == 0 else [pair.block2]
    for block in blocks:
        new_x, new_y = block.x + dx, block.y + dy
        if not (0 <= new_x < WIDTH and 0 <= new_y < HEIGHT) or (not ignore_overlap and board[new_y][new_x] is not None):
            return False
    return True

# ボードの描画
def draw_board(board):
    screen.fill(BACKGROUND_COLOR)
    for y, row in enumerate(board):
        for x, block in enumerate(row):
            if block is not None:
                draw_block(block)

# ブロックの描画
def draw_block(block):
    pygame.draw.circle(screen, block.color, (block.x * BLOCK_SIZE + BLOCK_SIZE // 2, block.y * BLOCK_SIZE + BLOCK_SIZE // 2), BLOCK_SIZE // 2)

# 消去判定
def detect_and_clear_matches(board, score):
    matched_blocks = find_matched_blocks(board)
    if matched_blocks:
        animate_block_flash(matched_blocks, board)
        clear_matched_blocks(matched_blocks, board)
        score += len(matched_blocks) * SCORE_INCREMENT
        score = detect_and_clear_matches(board, score)
    return score

# マッチしたブロックのフラッシュアニメーション
def animate_block_flash(matched_blocks, board):
    flash_duration = 750  # milliseconds
    flash_end_time = pygame.time.get_ticks() + flash_duration
    flash_interval = flash_duration // 12

    while pygame.time.get_ticks() < flash_end_time:
        for color_toggle in range(2):
            color = (255, 255, 255) if color_toggle == 0 else None
            for _ in range(2):
                draw_board(board)
                for x, y in matched_blocks:
                    if color is not None:
                        block = Block(color, x, y)
                        draw_block(block)
                    else:
                        block = board[y][x]
                        draw_block(block)
                pygame.display.flip()
                pygame.time.wait(flash_interval)

# マッチしたブロックの検出
def find_matched_blocks(board):
    matched_blocks = set()
    for y in range(HEIGHT):
        for x in range(WIDTH):
            if board[y][x] is not None and not (x, y) in matched_blocks:
                matched_group = find_matched_group(board[y][x], board)
                if len(matched_group) >= 4:
                    matched_blocks.update(matched_group)
    return matched_blocks

# マッチしたブロックグループの検出
def find_matched_group(block, board, visited=None):
    if visited is None:
        visited = set()
    visited.add((block.x, block.y))
    matched_group = {(block.x, block.y)}
    for dx, dy in ((0, 1), (1, 0), (0, -1), (-1, 0)):
        x, y = block.x + dx, block.y + dy
        if 0 <= x < WIDTH and 0 <= y < HEIGHT and not (x, y) in visited and board[y][x] is not None and board[y][x].color == block.color:
            matched_group.update(find_matched_group(board[y][x], board, visited))
    return matched_group

# マッチしたブロックの消去
def clear_matched_blocks(matched_blocks, board):
    for x, y in matched_blocks:
        board[y][x] = None

# 連鎖開始
def trigger_chain(board, score, chain_bonus):
    fall_and_lock_blocks(board)
    cleared_score = detect_and_clear_matches(board, 0)
    if cleared_score > 0:
        score += int(cleared_score * chain_bonus)
        chain_bonus += 0.25
        score, chain_bonus = trigger_chain(board, score, chain_bonus)
    return score, chain_bonus

# ブロックの落下と固定
def fall_and_lock_blocks(board):
    for x in range(WIDTH):
        stack = []
        for y in range(HEIGHT):
            if board[y][x] is not None:
                stack.append(board[y][x])
                board[y][x] = None
        for i, block in enumerate(reversed(stack)):
            block.y = HEIGHT - 1 - i
            board[HEIGHT - 1 - i][x] = block

# スコアの描画
def draw_score(score):
    score_text = FONT.render(f"SCORE: {score}", True, (255, 255, 255))
    screen.blit(score_text, (0, 0))

# ゲームオーバー判定
def is_game_over(board):
    return any(block is not None for block in board[0])

# ゲームループ
def game_loop():
    global GRAVITY
    board = [[None] * WIDTH for _ in range(HEIGHT)]
    score = 0
    chain_bonus = 1
    falling_block_pair = generate_falling_block_pair()
    fall_time = 0
    clock = pygame.time.Clock()

    while True:
        if is_game_over(board):
            return score

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                return
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    move_falling_block_pair(falling_block_pair, board, -1, 0)
                if event.key == pygame.K_RIGHT:
                    move_falling_block_pair(falling_block_pair, board, 1, 0)
                if event.key == pygame.K_z:
                    rotate_falling_block_pair(falling_block_pair, board, -1)
                if event.key == pygame.K_x:
                    rotate_falling_block_pair(falling_block_pair, board, 1)
                if event.key == pygame.K_SPACE:
                    hard_drop_falling_block_pair(falling_block_pair, board)
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    return

        keys = pygame.key.get_pressed()
        if keys[pygame.K_DOWN]:
            GRAVITY = FAST_DROP_MULTIPLIER
        else:
            GRAVITY = 1

        fall_time += clock.get_time()
        if fall_time >= 1000 // GRAVITY:
            fall_time = 0
            move_falling_block_pair(falling_block_pair, board, 0, 1)

        if place_falling_block_pair(falling_block_pair, board):
            score = detect_and_clear_matches(board, score)
            score, chain_bonus = trigger_chain(board, score, chain_bonus)
            falling_block_pair = generate_falling_block_pair()

        draw_board(board)
        draw_block(falling_block_pair.block1)
        draw_block(falling_block_pair.block2)
        draw_score(score)
        pygame.display.flip()
        clock.tick(60)

if __name__ == "__main__":
    final_score = game_loop()
    print("Game Over")

'''
上記コードを、streamlitを使用しスマートフォンのWebブラウザでプレイできるよう、コントロールにスマートフォン用のIFや操作も加えて改修し、修正されたコードをすべて表示してください