import pygame
import random
import math

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

# Define colors
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)

# Define grid size
GRID_WIDTH = 21
GRID_HEIGHT = 17

# Initialize the invisible variable
invisible = False

# 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)

available_buttons = [‘v’, ‘b’, ‘n’, ‘x’, ‘y’, ‘z’] # Add more buttons if needed
selected_tools = random.sample(tools_text, 3)

# Assign buttons to the selected tools
button_assignments = available_buttons[:3] # Take the first three buttons
button_assigned_functions = [tool_functions[tools_text.index(tool)] for tool in selected_tools]

# Wrap the tool descriptions and display them with their assigned buttons
wrapped_tools = []
for i, tool_desc in enumerate(selected_tools):
tool_lines = []
current_line = f"{button_assignments[i]}: {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()

return button_assignments, button_assigned_functions

# Define the logic for each tool as a function
def invisibility_cloak(player_rect):
# 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)

# Create a Rect for the invisibility cloak sprite
cloak_rect = player_rect.copy()
cloak_rect.inflate_ip(50, 50)

# Load the invisibility cloak image
try:
cloak_surf = pygame.image.load(‘invisibility_cloak.png’)
except pygame.error as e:
print(f"Cannot load invisibility cloak image: {e}”)
return

while invisible:
# Draw the invisibility cloak sprite over the player
screen.blit(cloak_surf, cloak_rect)

# Update the cloak position based on the player’s position
cloak_rect.center = player_rect.center

# Check for events
for event in pygame.event.get():
if event.type == pygame.USEREVENT:
# Stop the invisibility cloak effect
invisible = False

# Update the display
pygame.display.flip()

# Limit the frame rate
pygame.time.Clock().tick(60)

# Reset the invisible state
invisible = False

def grappling_hook(player_rect):
# 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(player_rect):
# Get the mouse position and the player position
mouse_x, mouse_y = pygame.mouse.get_pos()
player_x, player_y = player_rect.center

# Randomly choose between the two attacks
attack_type = random.randint(1, 2)

# Load the katana image
try:
katana_surf = pygame.image.load(‘katana.png’)
except pygame.error as e:
print(f"Cannot load katana image: {e}“)
return

# Create a temporary sprite for the katana
katana_sprite = pygame.sprite.Sprite()
katana_sprite.image = katana_surf
katana_sprite.rect = katana_sprite.image.get_rect()
katana_sprite.rect.center = player_rect.center

if attack_type == 1:
# Attack 1: Player moves/slashes in a random direction
angle = random.uniform(0, 2 * math.pi) # Random angle
slash_distance = 198 # Distance to move/slash
new_x = player_x + math.cos(angle) * slash_distance
new_y = player_y + math.sin(angle) * slash_distance
player_rect.center = (new_x, new_y)

# Draw the katana image on the player
katana_sprite.rect.center = player_rect.center
screen.blit(katana_sprite.image, katana_sprite.rect)

else:
# Attack 2: Throw the katana towards the mouse position
angle = math.atan2(mouse_y - player_y, mouse_x - player_x)
katana_sprite.image = pygame.transform.rotate(katana_sprite.image, math.degrees(angle))
katana_sprite.rect = katana_sprite.image.get_rect()
katana_sprite.rect.center = (player_x, player_y)
screen.blit(katana_sprite.image, katana_sprite.rect)

# Move the katana towards the mouse position
dx = mouse_x - player_x
dy = mouse_y - player_y
distance = (dx ** 2 + dy ** 2) ** 0.5
katana_speed = 10
katana_sprite.rect.x += dx / distance * katana_speed
katana_sprite.rect.y += dy / distance * katana_speed

# Check if the katana has reached the mouse position
if katana_sprite.rect.collidepoint(mouse_x, mouse_y):
# Reset the katana position
katana_sprite.rect.center = player_rect.center

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

def key(player_rect):
# 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(player_rect):
# 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_image = pygame.image.load(‘go_kart.jpeg’)
# Draw the go kart over the player
screen.blit(go_kart_image, player_rect)
# Check if the player collides with an enemy or a barrier
collided_enemies = pygame.sprite.spritecollide(player_sprite, enemies, True)
collided_barriers = pygame.sprite.spritecollide(player_sprite, barriers, True)


def freeze_ray(player_rect):
# 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)

# Create a line surface from the player to the mouse
line_length = math.hypot(mouse_x - player_x, mouse_y - player_y)
line = pygame.Surface((line_length, 5), pygame.SRCALPHA)
line.fill(BLUE)
line_rect = line.get_rect()
line_rect.center = player_rect.center

# Rotate the line surface
rotated_line = pygame.transform.rotate(line, math.degrees(angle))

# Draw the rotated line on the screen
screen.blit(rotated_line, (player_x, player_y))

# Create a temporary sprite for the line
line_sprite = pygame.sprite.Sprite()
line_sprite.image = rotated_line
line_sprite.rect = rotated_line.get_rect(center=line_rect.center)

# Check if the line intersects with an enemy or a platform
enemies_hit = pygame.sprite.spritecollide(line_sprite, enemies, False)
platforms_hit = pygame.sprite.spritecollide(line_sprite, platforms, False)

# Freeze the enemies and platforms that were hit
for enemy in enemies_hit:
freeze(enemy)
for platform in platforms_hit:
freeze(platform)

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(player_rect):
global tsunami
tsunami = True
wave_surf = pygame.image.load(‘tsunami_maker.png’)
# Resize the wave_surf to make it taller
wave_surf = pygame.transform.scale(wave_surf, (wave_surf.get_width(), wave_surf.get_height() * 3))
wave_sprite = pygame.sprite.Sprite()
wave_sprite.image = wave_surf
wave_sprite.rect = wave_sprite.image.get_rect()
wave_sprite.rect.bottomleft = (0, screen.get_height())
wave_speed = 10

while tsunami:
screen.blit(wave_sprite.image, wave_sprite.rect)
wave_sprite.rect.x += wave_speed

if wave_sprite.rect.right >= screen.get_width():
tsunami = False

pygame.display.flip()


def laser_beam(player_rect):
# 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(player_rect):
# 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(player_rect):
# Set a global variable to indicate that the player has a revival kit
global revival
revival = True
global player_health
# 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

tool_functions = [invisibility_cloak, grappling_hook, katana, freeze_ray, bouncy_shoes, key,
go_kart, tsunami_maker, laser_beam, speed_pill, revival_kit]

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()

# Call show_intro() and get the button_assigned_functions list
button_assignments, button_assigned_functions = show_intro()


# Initialize player jumping state
player_is_jumping = False

# Create a rect for the player sprite
player_rect = player_sprite.rect

# In the main game loop
while running:
# …
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

# Process KEYDOWN events individually
if 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

if event.key == ord(‘v’): # Pressed V
try:
button_assigned_functions0 # Pass player_sprite.rect
except Exception as e:
print(f"Error calling tool function 1: {e}”)
elif event.key == ord(‘b’): # Pressed B
try:
button_assigned_functions1 # Pass player_sprite.rect
except Exception as e:
print(f"Error calling tool function 2: {e}“)
elif event.key == ord(‘n’): # Pressed N
try:
button_assigned_functions2 # Pass player_sprite.rect
except Exception as e:
print(f"Error calling tool function 3: {e}”)
# 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

# Check if the player is invisible
if invisible:
# Get the updated player position
player_x, player_y = player_sprite.rect.topleft
# Draw the invisibility cloak image over the player
screen.blit(invisibility_cloak_image, (player_x, player_y))

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

# 4. Cap the frame rate
clock.tick(60)

if name == “main”:
main() now code to beat the level the player has to reach enter either door, to enter door 1 player just has to reach it because its open but for door 2 its locked so player needs to have the key. this activates you beat level 1 and sends the player to level 2. just send them there will make level 2 just now.