import pygame
import random
import math

# Initialize pygame and create a screen object
pygame.init()
screen = pygame.display.set_mode((1000, 800))

# Define grid size
GRID_WIDTH = 21
GRID_HEIGHT = 17

# Define initial floor position
FLOOR_START_ROW = GRID_HEIGHT - 2
FLOOR_END_ROW = GRID_HEIGHT - 1

pygame.display.set_caption(‘100% no luck’)

# Load the images for the background, the player, and the boss
# Ensure that these images are present in your project directory
try:
background = pygame.image.load(‘level_1_background.jpeg’)
player_image = pygame.image.load(‘player1_back.png’)
invisibility_cloak_image = pygame.image.load(‘invisibility_cloak.png’)
grappling_hook_image = pygame.image.load(‘grappling_hook.png’)
katana_image = pygame.image.load(‘katana.png’)
freezing_ray_image = pygame.image.load(‘freezing_ray.png’)
speed_pill_image = pygame.image.load(‘speed_pill.jpeg’)
bouncy_shoes_image = pygame.image.load(‘bouncy_shoes.png’)
key_image = pygame.image.load(‘key.png’)
tsunami_maker_image = pygame.image.load(‘tsunami_maker.png’)
laser_beam_image = pygame.image.load(‘laser_beam.png’)
go_kart_image = pygame.image.load(‘go_kart.jpeg’)
revival_kit_image = pygame.image.load(‘revival_kit.jpeg’)
except pygame.error as e:
print(“Cannot load images:”, e)
raise SystemExit

# Define the colors for the text
WHITE = (255, 255, 255)

# Define the font for the text
font = pygame.font.SysFont(‘Arial’, 32)

# Define the text for the intro and the tools
intro_text = “Welcome to 100% no luck, a game where you have to use smart logic and some luck to beat the dungeon. You will spawn with 3 tools out of a possible 15 tools randomized. Each tool has a different effect and can help you or hinder you depending on the situation. You have to think carefully about how to use your tools and when to use them. The dungeon has many obstacles and enemies that you have to overcome. The goal is to reach the end of the dungeon and defeat the boss. Good luck!”

tools_text = [“Invisibility cloak: Makes you invisible for 10 seconds. Useful for sneaking past enemies or traps.”,
“Grappling hook: Allows you to swing across gaps or pull objects towards you.”,
“Katana: A sharp sword that can cut through anything. Useful for fighting enemies or breaking barriers.”,
“Freeze ray: A device that can freeze anything in its path. Useful for stopping enemies or creating platforms.”,
“Bouncy shoes: Shoes that make you jump higher and farther. Useful for reaching high places or avoiding obstacles.”,
“Key: A key that can unlock any door or chest. Useful for accessing hidden areas or treasures.”,
“Go kart: A vehicle that can move fast and run over anything. Useful for escaping enemies or crossing large distances.”,
“Tsunami maker: A device that can create a huge wave of water. Useful for washing away enemies or filling gaps.”,
“Laser beam: A device that can shoot a powerful laser. Useful for destroying enemies or barriers.”,
“Speed pill: A pill that can make you move faster for 10 seconds. Useful for dodging enemies or traps.”,
“Revival kit: A kit that can revive you once if you die. Useful for surviving fatal situations.”]

def show_intro():
intro_text = “Welcome to 100% no luck, a game where you have to use smart logic and some luck to beat the dungeon. You will spawn with 3 tools out of a possible 15 tools randomized. Each tool has a different effect and can help you or hinder you depending on the situation. You have to think carefully about how to use your tools and when to use them. The dungeon has many obstacles and enemies that you have to overcome. The goal is to reach the end of the dungeon and defeat the boss. Good luck!”

# Wrap the intro text
intro_lines = []
max_width = 950 # Adjust as needed
words = intro_text.split()
current_line = words[0]
for word in words[1:]:
if font.size(current_line + ’ ’ + word)[0] < max_width:
current_line += ’ ’ + word
else:
intro_lines.append(current_line)
current_line = word
intro_lines.append(current_line)

current_line = 0
intro_complete = False
start_time = pygame.time.get_ticks()

while not intro_complete:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()

screen.fill((0, 0, 0))
intro_surface = font.render(intro_lines[current_line], True, WHITE)
intro_rect = intro_surface.get_rect(center=(screen.get_width() // 2, screen.get_height() // 2))
screen.blit(intro_surface, intro_rect)

if pygame.time.get_ticks() - start_time > 2980:
current_line += 1
start_time = pygame.time.get_ticks()

if current_line == len(intro_lines):
intro_complete = True

pygame.display.flip()
pygame.time.Clock().tick(60)

screen.fill((0, 0, 0))
pygame.display.flip()

tools_title_surface = font.render(“Selected Tools:”, True, WHITE)
tools_title_rect = tools_title_surface.get_rect(center=(screen.get_width() // 2, 100))
screen.blit(tools_title_surface, tools_title_rect)
pygame.display.flip()

pygame.time.delay(1000)

selected_tools = random.sample(tools_text, 3)

# Wrap the tool descriptions
wrapped_tools = []
for tool_desc in selected_tools:
tool_lines = []
current_line = tool_desc.split()[0]
for word in tool_desc.split()[1:]:
if font.size(current_line + ’ ’ + word)[0] < max_width:
current_line += ’ ’ + word
else:
tool_lines.append(current_line)
current_line = word
tool_lines.append(current_line)
wrapped_tools.append(tool_lines)

selected_tools_surface = [font.render(line, True, WHITE) for tool_lines in wrapped_tools for line in tool_lines]

for i, tool_surface in enumerate(selected_tools_surface):
tool_rect = tool_surface.get_rect(center=(screen.get_width() // 2, 200 + i * 50))
screen.blit(tool_surface, tool_rect)
pygame.display.flip()

start_time = pygame.time.get_ticks()
while pygame.time.get_ticks() - start_time < 2000:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()

screen.fill((0, 0, 0))
pygame.display.flip()

# Define the logic for each tool as a function
def invisibility_cloak():
# Set a global variable to indicate that the player is invisible
global invisible
invisible = True
# Set a timer to make the player visible again after 10 seconds
pygame.time.set_timer(pygame.USEREVENT, 10000)

def grappling_hook():
# Get the mouse position and the player position
mouse_x, mouse_y = pygame.mouse.get_pos()
player_x, player_y = player_rect.center
# Calculate the distance and the angle between the mouse and the player
distance = ((mouse_x - player_x) ** 2 + (mouse_y - player_y) ** 2) ** 0.5
angle = math.atan2(mouse_y - player_y, mouse_x - player_x)
# Draw a line from the player to the mouse
pygame.draw.line(screen, BLACK, (player_x, player_y), (mouse_x, mouse_y), 5)
# Check if the mouse is over a gap or an object
if mouse_x > 600 and mouse_x < 700 and mouse_y > 300 and mouse_y < 400:
# If the mouse is over a gap, move the player towards the mouse
player_rect.centerx += math.cos(angle) * 10
player_rect.centery += math.sin(angle) * 10
elif mouse_x > 700 and mouse_x < 800 and mouse_y > 200 and mouse_y < 300:
# If the mouse is over an object, move the object towards the player
object_rect.centerx -= math.cos(angle) * 10
object_rect.centery -= math.sin(angle) * 10

def katana():
# Get the mouse position and the player position
mouse_x, mouse_y = pygame.mouse.get_pos()
player_x, player_y = player_rect.center
# Calculate the angle between the mouse and the player
angle = math.atan2(mouse_y - player_y, mouse_x - player_x)
# Draw a line from the player to the mouse
pygame.draw.line(screen, RED, (player_x, player_y), (mouse_x, mouse_y), 5)
# Check if the line intersects with an enemy or a barrier
if pygame.sprite.spritecollideany(line, enemies) or pygame.sprite.spritecollideany(line, barriers):
# If the line intersects with an enemy or a barrier, destroy it
pygame.sprite.spritecollide(line, enemies, True)
pygame.sprite.spritecollide(line, barriers, True)

def bouncy_shoes():
# Set a global variable to indicate that the player has bouncy shoes
global bouncy
bouncy = True
# Increase the player’s jump velocity
player_jump_vel = 20

def key():
# Get the mouse position and the player position
mouse_x, mouse_y = pygame.mouse.get_pos()
player_x, player_y = player_rect.center
# Calculate the distance between the mouse and the player
distance = ((mouse_x - player_x) ** 2 + (mouse_y - player_y) ** 2) ** 0.5
# Check if the mouse is over a door or a chest
if pygame.sprite.spritecollideany(mouse, doors) or pygame.sprite.spritecollideany(mouse, chests):
# If the mouse is over a door or a chest, unlock it and open it
pygame.sprite.spritecollide(mouse, doors, True)
pygame.sprite.spritecollide(mouse, chests, True)
# If the chest contains a tool, add it to the player’s inventory
if chest.tool:
inventory.append(chest.tool)

def go_kart():
# Set a global variable to indicate that the player is in a go kart
global go_kart
go_kart = True
# Increase the player’s speed and size
player_speed = 15
player_rect.inflate_ip(50, 50)
# Load the image for the go kart
go_kart = pygame.image.load(‘go_kart.png’)
# Draw the go kart over the player
screen.blit(go_kart, player_rect)
# Check if the player collides with an enemy or a barrier
if pygame.sprite.spritecollideany(player, enemies) or pygame.sprite.spritecollideany(player, barriers):
# If the player collides with an enemy or a barrier, run over it and destroy it
pygame.sprite.spritecollide(player, enemies, True)
pygame.sprite.spritecollide(player, barriers, True)

def freeze_ray():
# Get the mouse position and the player position
mouse_x, mouse_y = pygame.mouse.get_pos()
player_x, player_y = player_rect.center
# Calculate the angle between the mouse and the player
angle = math.atan2(mouse_y - player_y, mouse_x - player_x)
# Draw a line from the player to the mouse
pygame.draw.line(screen, BLUE, (player_x, player_y), (mouse_x, mouse_y), 5)
# Check if the line intersects with an enemy or a platform
if pygame.sprite.spritecollideany(line, enemies) or pygame.sprite.spritecollideany(line, platforms):
# If the line intersects with an enemy or a platform, freeze it
pygame.sprite.spritecollide(line, enemies, False, freeze)
pygame.sprite.spritecollide(line, platforms, False, freeze)

def freeze(sprite):
# Change the sprite’s image to a frozen version
sprite.image = pygame.image.load(sprite.name + ‘_frozen.png’)
# Set the sprite’s frozen attribute to True
sprite.frozen = True

def tsunami_maker():
# Set a global variable to indicate that the player has used the tsunami maker
global tsunami
tsunami = True
# Load the image for the wave
wave = pygame.image.load(‘wave.png’)
# Create a rect for the wave
wave_rect = wave.get_rect()
# Set the wave’s initial position at the left edge of the screen
wave_rect.left = 0
# Set the wave’s speed
wave_speed = 10
# Draw the wave on the screen
screen.blit(wave, wave_rect)
# Move the wave to the right
wave_rect.x += wave_speed
# Check if the wave collides with an enemy or a gap
if pygame.sprite.spritecollideany(wave, enemies) or pygame.sprite.spritecollideany(wave, gaps):
# If the wave collides with an enemy or a gap, wash it away
pygame.sprite.spritecollide(wave, enemies, True)
pygame.sprite.spritecollide(wave, gaps, True, fill)

def fill(sprite):
# Change the sprite’s image to a water version
sprite.image = pygame.image.load(sprite.name + ‘_water.png’)
# Set the sprite’s filled attribute to True
sprite.filled = True

def laser_beam():
# Get the mouse position and the player position
mouse_x, mouse_y = pygame.mouse.get_pos()
player_x, player_y = player_rect.center
# Calculate the angle between the mouse and the player
angle = math.atan2(mouse_y - player_y, mouse_x - player_x)
# Draw a line from the player to the mouse
pygame.draw.line(screen, YELLOW, (player_x, player_y), (mouse_x, mouse_y), 5)
# Check if the line intersects with an enemy or a barrier
if pygame.sprite.spritecollideany(line, enemies) or pygame.sprite.spritecollideany(line, barriers):
# If the line intersects with an enemy or a barrier, destroy it
pygame.sprite.spritecollide(line, enemies, True)
pygame.sprite.spritecollide(line, barriers, True)

def speed_pill():
# Set a global variable to indicate that the player has used the speed pill
global speed
speed = True
# Set a timer to make the player normal again after 10 seconds
pygame.time.set_timer(pygame.USEREVENT + 1, 10000)
# Increase the player’s speed
player_speed = 10

def revival_kit():
# Set a global variable to indicate that the player has a revival kit
global revival
revival = True
# Check if the player’s health is zero
if player_health == 0:
# If the player’s health is zero, revive the player
player_health = 100
# Set the revival variable to False
revival = False

def is_on_floor_or_stairs(player_rect):
“”“
Check if the player is standing on a floor or stairs cell.
Returns True if standing on floor or stairs, False otherwise.
“””
cell_width = screen.get_width() // GRID_WIDTH
cell_height = screen.get_height() // GRID_HEIGHT

# Check if the player is on the initial floor rows
if FLOOR_START_ROW <= player_rect.bottom // cell_height <= FLOOR_END_ROW:
for x in range(player_rect.left // cell_width, (player_rect.right + cell_width - 1) // cell_width):
if 0 <= x < GRID_WIDTH:
return True



return False

def draw_doors():
# Define the door’s color
DOOR_COLOR = (139, 69, 19) # Saddle brown color

# Calculate the cell size based on the screen dimensions
cell_width = screen.get_width() // GRID_WIDTH
cell_height = screen.get_height() // GRID_HEIGHT

# Draw door 1
door1_start_row = GRID_HEIGHT - 10
door1_end_row = GRID_HEIGHT - 13
door1_start_col = 10
door1_end_col = 11

for row in range(door1_start_row, door1_end_row - 1, -1):
for col in range(door1_start_col, door1_end_col + 1):
rect = pygame.Rect(col * cell_width, row * cell_height, cell_width, cell_height)
pygame.draw.rect(screen, DOOR_COLOR, rect)

# Draw door 2
door2_start_row = GRID_HEIGHT - 3
door2_end_row = GRID_HEIGHT - 4
door2_start_col = 16
door2_end_col = 17

for row in range(door2_start_row, door2_end_row - 1, -1):
for col in range(door2_start_col, door2_end_col + 1):
rect = pygame.Rect(col * cell_width, row * cell_height, cell_width, cell_height)
pygame.draw.rect(screen, DOOR_COLOR, rect)

def draw_floor():
# Define the floor’s color
FLOOR_COLOR = (128, 64, 0) # Brown color
STAIRS_COLOR = (128, 128, 128) # Gray color

# Calculate the cell size based on the screen dimensions
cell_width = screen.get_width() // GRID_WIDTH
cell_height = screen.get_height() // GRID_HEIGHT

# Draw the floor cells
for col in range(GRID_WIDTH):
for row in range(FLOOR_START_ROW, FLOOR_END_ROW + 1):
rect = pygame.Rect(col * cell_width, row * cell_height, cell_width, cell_height)
pygame.draw.rect(screen, FLOOR_COLOR, rect)



enemies = pygame.sprite.Group()
barriers = pygame.sprite.Group()
platforms = pygame.sprite.Group()
doors = pygame.sprite.Group()
chests = pygame.sprite.Group()
gaps = pygame.sprite.Group()
tools = pygame.sprite.Group()

# Create some sprites and groups for the player
player_sprite = pygame.sprite.Sprite()
player_sprite.image = player_image
player_sprite.rect = player_sprite.image.get_rect()
player_sprite.rect.center = (100, 300)

# Create sprite groups
enemies = pygame.sprite.Group()
tools = pygame.sprite.Group() # Assuming tools are also Sprites

# Gravity constant
GRAVITY = 0.5

# Player properties
player_x = 100
player_y = 300
player_speed = 5
player_jump_vel = 10
player_vert_vel = 0 # Initial vertical velocity
player_health = 100
inventory = []

# Main game loop control
running = True
clock = pygame.time.Clock()

show_intro()

# Initialize player jumping state
player_is_jumping = False

while running:
# 1. Handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and not player_is_jumping:
# Start jumping
player_is_jumping = True
player_vert_vel = -player_jump_vel

# 2. Update game state
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player_sprite.rect.x -= player_speed
if keys[pygame.K_RIGHT]:
player_sprite.rect.x += player_speed
if keys[pygame.K_UP]:
player_sprite.rect.y -= player_speed
if keys[pygame.K_DOWN]:
player_sprite.rect.y += player_speed

# Update player’s vertical velocity and position if jumping
if player_is_jumping:
player_vert_vel += GRAVITY
player_sprite.rect.y += player_vert_vel

# Check if the player has landed on floor or stairs
if is_on_floor_or_stairs(player_sprite.rect):
player_is_jumping = False
player_vert_vel = 0
else:
# Apply gravity only if not on floor or stairs
if not is_on_floor_or_stairs(player_sprite.rect):
player_vert_vel += GRAVITY
player_sprite.rect.y += player_vert_vel

# Reset vertical velocity if on floor or stairs
if is_on_floor_or_stairs(player_sprite.rect):
player_vert_vel = 0

# Prevent the player from moving off screen
player_sprite.rect.clamp_ip(screen.get_rect())

# 3. Draw everything
screen.blit(background, (0, 0))
draw_floor()
draw_doors()
tools.draw(screen)
enemies.draw(screen)
screen.blit(player_sprite.image, player_sprite.rect) # Draw player

# After drawing everything, update/flip the display
pygame.display.flip()

# 4. Cap the frame rate
clock.tick(60) simplify and shorten code