# Arup Guha
# 6/12/2024
# This version of the Fruit Game uses inheritance,
# draws the score on the screen, and has introduced bombs.

# Edited to make more fun and interesting in class on 6/11/2026

import random
import math
import time
import pygame, sys
from pygame.locals import *
from PicTokenFile import pictoken
from TokenFile import token

# Useful Constants
SCREEN_W = 1000
SCREEN_H = 600

# Helps to make different behavior by level.
SCORE_BY_LEVEL = [0, 1000, 3000, 8000, 100000]
DROP_BY_LEVEL = [0, 5, 10, 15, 20]

# Store images here.
pics = []
pics.append(pygame.transform.scale(pygame.image.load("apple.png"),(75, 75)))
pics.append(pygame.transform.scale(pygame.image.load("strawberry.png"),(75, 75)))
pics.append(pygame.transform.scale(pygame.image.load("kiwi.png"),(75, 75)))
pics.append(pygame.transform.scale(pygame.image.load("cherry.png"),(75, 75)))
bomb = pygame.image.load("bomb.jpg")
bomb = pygame.transform.scale(bomb, (80, 80))

# How much each fruit is worth!
pts = [50, 75, 100, 150]

# This function handles moving each item listed in items.
def move(items):
    for item in items:
        item.move()

# This function removes all items that will never be visible again,
# and returns how many were removed.
def removeUseless(items):
    total = 0
    for item in items:
        if item.rec.y > SCREEN_H:
            items.remove(item)
            total += 1
    return total

# Function to put text onto the screen.
def draw(text, font, color, surface, x, y):
    # Draw text on a new Surface. Title, antialias and color are used.
    text = font.render(text, 1, color)

    # Returns a new rectangle covering the entire surface.
    # This rectangle will always start at (0, 0) with a width and height the same size as the image.
    textrect = text.get_rect()

    # Sets location of text.
    textrect.topleft = (x, y)

    # Go ahead and draw it to the surface.
    surface.blit(text, textrect)

def addobjects(step,fruit,bombs,level):

    # As level increases more objects appear.
    if step%(11-level) != 0:
        return

    # Stuff common to both bombs and fruit.
    x = random.randint(1, SCREEN_W)
    mydx = random.randint(-2, 2)
    mydy = random.randint(3, 8+2*level)

    # Choose - fruit or bomb, as the level increases, bomb chance increases.
    which = random.randint(0,3+level)
    
    # Fruit
    if which < 4:
        temp = pictoken(x, 0, mydx, mydy, "white", pics[which], pts[which])
        fruit.append(temp)

    # Bomb
    else:
        temp = pictoken(x, 0, mydx,mydy, "white", bomb, -1000)
        bombs.append(temp)
        
def main():

    # Basic Set Up
    pygame.init()
    font = pygame.font.SysFont("Arial", 36)
    DISPLAYSURF = pygame.display.set_mode((SCREEN_W, SCREEN_H))
    pygame.display.set_caption("Catch the fruit!")
    WHITE = pygame.Color(255,255,255)
    BLUE = pygame.Color(0,0,255)
    clock = pygame.time.Clock()

    # Store fruit and bombs.
    fruit = []
    bombs = []

    # Initialize stuff.
    loseT = 0
    score = 0
    dropped = 0
    step = 0
    lose = False
    lives = 3
    level = 1
    wonLevel = False

    # Main game loop starts here.
    while True:
        
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

            # Looking to see if you tried to get a fruit!
            if event.type == MOUSEBUTTONDOWN:

                # Just look at left mouse button.
                if pygame.mouse.get_pressed()[0]:

                    # Now see which fruit we hit! (I've implemented it so you
                    # could hit more than one in a single click!)
                    for f in fruit:
                        if f.hit(event.pos):
                            score += f.pts
                            fruit.remove(f)

                    # Now see if we hit a bomb.
                    for b in bombs:
                        if b.hit(event.pos):

                            # Messes up your score, lose a life.
                            score +=b.pts
                            bombs.remove(b)
                            lives -= 1

                            # You lose!
                            if lives == 0:
                                draw("YOU LOSE!!!",font,"red",DISPLAYSURF,250,250)
                                lose = True
                                loseT = time.time()
                            
                            

        # These images are big, so I only add a drop once every 10 time steps.
        addobjects(step, fruit, bombs, level)
         
        DISPLAYSURF.fill("white")

        # Only draw this stuff if you haven't lost yet.
        if not lose:
            # blit allows us to draw a surface onto another surface.
            for item in fruit:
                item.draw(DISPLAYSURF)

            for item in bombs:
                item.draw(DISPLAYSURF)

        # Always draw this.
        draw("Score: "+str(score), font, "blue", DISPLAYSURF, 800,50)
        draw("Dropped: "+str(dropped), font, "green", DISPLAYSURF, 800,100)
        draw("Lives: "+str(lives), font, "red", DISPLAYSURF, 800, 150)
        draw("Level: "+str(level), font, "cyan", DISPLAYSURF, 800, 200)

        # Reset to the next level.
        if score >= SCORE_BY_LEVEL[level]:

            # So I can freeze the screen for a bit.
            wonLevel = True

            # Draw my message and reset.
            draw("Congrats, you completed level "+str(level)+"!", font, "purple", DISPLAYSURF, 200, 400)
            level += 1
            dropped = 0
            fruit = []
            bombs = []
            
        # Message for losing.
        if lose:

            # Always draw this.
            draw("GAME OVER", font, "red", DISPLAYSURF, 400, 250)

            # Dropped message.
            if dropped >= DROP_BY_LEVEL[level]:
                draw("YOU DROPPED "+str(DROP_BY_LEVEL[level])+" FRUITS", font, "red", DISPLAYSURF, 300, 300)

            # Bomb message.
            else:
                draw("YOU RAN OUT OF LIVES", font, "red", DISPLAYSURF, 375, 300)
        
        pygame.display.update()

        # Wait for 5 seconds.
        if wonLevel:
            pygame.time.wait(5000)
            wonLevel = False
                
        # Move the drops for the next iteration and remove useless ones.
        if not lose:
            move(fruit)
            move(bombs)
            dropped += removeUseless(fruit)

        # We've lost!
        if not lose and dropped >= DROP_BY_LEVEL[level]:
            lose = True
            loseT = time.time()

        # Game ends!
        if lose and time.time()-loseT > 5:
            print("Sorry, you have dropped more than 50 fruits.")
            print("The game is over.")
            print("Your score is",score)
            pygame.quit()
            sys.exit()
            
        clock.tick(30)
        step += 1

# Run it!
main()
