assignment 3 done?

master
Ruben-FreddyLoafers 2025-11-05 10:09:22 +01:00
parent cf9131b760
commit c9869979d3
3 changed files with 230 additions and 27 deletions

View File

@ -63,54 +63,62 @@ def eval_fitness(bin_pop_values):
quad_error = quadratic_error(e_func, approx, 3) # the bigger the error, the worse the fitness quad_error = quadratic_error(e_func, approx, 3) # the bigger the error, the worse the fitness
inverse_fitness = 1 / quad_error # using inverse to find small errors easier inverse_fitness = 1 / quad_error # using inverse to find small errors easier
inverse_fitness = round(inverse_fitness, 2)
print("Fitness: " + str(inverse_fitness)) # debugging print("Fitness: " + str(inverse_fitness)) # debugging
fitness_arr.append(inverse_fitness) # save fitness fitness_arr.append(inverse_fitness) # save fitness
return fitness_arr return fitness_arr
def select(fitness_arr): def select(fitness_arr):
gray_pop_copy = gray_pop.copy() # Create a copy of the population
fitness_arr_copy = fitness_arr.copy() fitness_arr_copy = fitness_arr.copy()
sum_of_fitness = sum(fitness_arr_copy)
selected_pop = [] selected_pop = []
while len(selected_pop) < SELECTION_SIZE: while len(selected_pop) < SELECTION_SIZE:
sum_of_fitness = sum(fitness_arr_copy)
if sum_of_fitness == 0:
break
# Roulette logic # Roulette logic
roulette_num = random.random() roulette_num = random.random()
is_chosen = False cumulative_p = 0
while not is_chosen:
cumulative_p = 0 # Track cumulative probability
for i, fitness in enumerate(fitness_arr_copy): for i, fitness in enumerate(fitness_arr_copy):
cumulative_p += fitness / sum_of_fitness cumulative_p += fitness / sum_of_fitness
if roulette_num < cumulative_p: if roulette_num < cumulative_p:
# Add the 32 Bit individual in gray code to population # Add the selected individual
selected_pop.append(gray_pop[i]) selected_pop.append(gray_pop_copy[i])
# Calc new sum of fitness # Remove selected individual and their fitness
gray_pop_copy.pop(i)
fitness_arr_copy.pop(i) fitness_arr_copy.pop(i)
sum_of_fitness = sum(fitness_arr_copy) break
is_chosen = True # break while loop
break # break for loop
return selected_pop return selected_pop
def xover(population): def xover(population):
"""Performs crossover on pairs of individuals from population.""" """Performs crossover on pairs of individuals from population."""
offspring = [] offspring = []
# Process pairs while we have enough individuals and haven't reached xover_rate # Randomly shuffle the population to avoid bias
population_copy = population.copy()
random.shuffle(population_copy)
# Process pairs
i = 0 i = 0
while i < XOVER_PAIR_SIZE: while i < XOVER_PAIR_SIZE:
parent_a = population[i]
parent_b = population[i + 1]
# Create two new offspring by swapping parts at XOVER_POINT parent_a = population_copy[i]
parent_b = population_copy[i + 1]
# Create two new offspring by swapping parts at random xover point
offspring_a = parent_a[:XOVER_POINT] + parent_b[XOVER_POINT:] offspring_a = parent_a[:XOVER_POINT] + parent_b[XOVER_POINT:]
offspring_b = parent_b[:XOVER_POINT] + parent_a[XOVER_POINT:] offspring_b = parent_b[:XOVER_POINT] + parent_a[XOVER_POINT:]
offspring.extend([offspring_a, offspring_b]) offspring.extend([offspring_a, offspring_b])
i += 2 # Move to next pair i += 2 # Move to next pair
if len(offspring) > 3: if len(offspring) > XOVER_PAIR_SIZE:
offspring.pop() offspring = offspring[:XOVER_PAIR_SIZE]
return offspring return offspring
@ -132,8 +140,8 @@ bin_pop_values = generate_random_population(POPULATION_SIZE)
print("Working...") print("Working...")
iteration = 0 # debugging iteration = 0 # debugging
while not np.any((np.array(fitness_arr)) > 200): # Continue while any fitness value is > 1 while not np.any((np.array(fitness_arr)) > 300): # Continue while any fitness value is > 1
print("Iteration: " + str(iteration)) # debugging print("\nIteration: " + str(iteration)) # debugging
# Evaluate fitness # Evaluate fitness
fitness_arr = eval_fitness(bin_pop_values) fitness_arr = eval_fitness(bin_pop_values)
@ -162,7 +170,8 @@ while not np.any((np.array(fitness_arr)) > 200): # Continue while any fitness v
max_fitness_index = np.argmax(np.array(fitness_arr)) max_fitness_index = np.argmax(np.array(fitness_arr))
a, b, c, d = [utils.bin_to_param(param) for param in bin_pop_values[max_fitness_index]] a, b, c, d = [utils.bin_to_param(param) for param in bin_pop_values[max_fitness_index]]
# print("index: " + str(max_fitness_index)) # debugging print("Chosen value: " + str(fitness_arr[max_fitness_index])) # debugging
print("at index: " + str(max_fitness_index)) # debugging
print("a: " + str(a) + "; b: " + str(b) + "; c: " + str(c) + "; d: " + str(d) ) print("a: " + str(a) + "; b: " + str(b) + "; c: " + str(c) + "; d: " + str(d) )
utils.plot_graph(a, b, c, d) utils.plot_graph(a, b, c, d)

View File

@ -23,12 +23,12 @@ def bin_to_gray(binary):
gray = num ^ (num >> 1) # Gray code formula: G = B ^ (B >> 1) gray = num ^ (num >> 1) # Gray code formula: G = B ^ (B >> 1)
return format(gray, '032b') # Always return 32-bit string return format(gray, '032b') # Always return 32-bit string
def bin_to_param(binary, q_min = 0.0, q_max = 8.0): def bin_to_param(binary, q_min = 0.0, q_max = 5.0):
""" """
Convert one binary string to float parameter in range [q_min, q_max] Convert one binary string to float parameter in range [q_min, q_max]
:returns: float :returns: float
""" """
val = int(binary, 2) / 25.5 * q_max # conversion to 0.0 - 10.0 float val = int(binary, 2) / 25.5 * 10.0 # conversion to 0.0 - 10.0
# Scale to range [q_min, q_max] # Scale to range [q_min, q_max]
q = q_min + ((q_max - q_min) / (2**len(binary))) * val q = q_min + ((q_max - q_min) / (2**len(binary))) * val
return q return q

View File

@ -0,0 +1,194 @@
import pygame
import random
import math
# Initialize pygame
pygame.init()
# Define constants
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 400
CELL_SIZE = 40
# Define colors
YELLOW = (255, 255, 0)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
# Labyrinth as a string
labyrinth = [
"##########",
"#........#",
"#.##..##.#",
"#........#",
"##########"
]
# Get labyrinth dimensions
ROWS = len(labyrinth)
COLS = len(labyrinth[0])
# Initialize game screen
screen = pygame.display.set_mode((COLS * CELL_SIZE, ROWS * CELL_SIZE))
pygame.display.set_caption("Micro-Pacman")
# Pacman class
class Pacman:
def __init__(self, x, y):
self.x = x
self.y = y
self.count = 0
def move(self, dx, dy):
new_x, new_y = self.x + dx, self.y + dy
if labyrinth[new_y][new_x] != "#":
self.x = new_x
self.y = new_y
def draw(self):
radius = CELL_SIZE // 2 - 4
start_angle = math.pi / 6
end_angle = -math.pi / 6
pygame.draw.circle(screen, YELLOW, (self.x * CELL_SIZE + CELL_SIZE // 2, self.y * CELL_SIZE + CELL_SIZE // 2), CELL_SIZE // 2 - 4)
# Calculate the points for the mouth
start_pos = (self.x* CELL_SIZE + CELL_SIZE // 2 + int(radius*1.3 * math.cos(start_angle)),
self.y* CELL_SIZE + CELL_SIZE // 2 - int(radius*1.3 * math.sin(start_angle)))
end_pos = (self.x* CELL_SIZE + CELL_SIZE // 2 + int(radius*1.3 * math.cos(end_angle)),
self.y* CELL_SIZE + CELL_SIZE // 2 - int(radius*1.3 * math.sin(end_angle)))
self.count += 1
if self.count%2==0:
# Draw the mouth by filling a polygon
pygame.draw.polygon(screen, BLACK, [(self.x* CELL_SIZE + CELL_SIZE // 2, self.y* CELL_SIZE + CELL_SIZE // 2), start_pos, end_pos])
# Ghost class with pixel art
class Ghost:
# Define the pixel art for the ghost using strings
ghost_pixels = [
" #### ",
"######",
"## # #",
"######",
"######",
"# # # "
]
def __init__(self, x, y):
self.x = x
self.y = y
def move_towards_pacman(self, pacman):
if self.x < pacman.x and labyrinth[self.y][self.x + 1] != "#":
self.x += 1
elif self.x > pacman.x and labyrinth[self.y][self.x - 1] != "#":
self.x -= 1
elif self.y < pacman.y and labyrinth[self.y + 1][self.x] != "#":
self.y += 1
elif self.y > pacman.y and labyrinth[self.y - 1][self.x] != "#":
self.y -= 1
def draw(self):
pixel_size = CELL_SIZE // len(self.ghost_pixels) # Size of each pixel in the ghost art
for row_idx, row in enumerate(self.ghost_pixels):
for col_idx, pixel in enumerate(row):
if pixel == "#":
pixel_x = self.x * CELL_SIZE + col_idx * pixel_size
pixel_y = self.y * CELL_SIZE + row_idx * pixel_size
pygame.draw.rect(screen, RED, (pixel_x, pixel_y, pixel_size, pixel_size))
# Draw walls and cookies
def draw_labyrinth():
for y, row in enumerate(labyrinth):
for x, cell in enumerate(row):
if cell == "#":
pygame.draw.rect(screen, BLUE, (x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE))
elif cell == ".":
pygame.draw.circle(screen, WHITE, (x * CELL_SIZE + CELL_SIZE // 2, y * CELL_SIZE + CELL_SIZE // 2), 5)
# Main game function
def main():
clock = pygame.time.Clock()
# Initialize Pacman and Ghost positions
pacman = Pacman(1, 1)
ghost = Ghost(COLS - 2, ROWS - 2)
# Game loop
running = True
iter = 0
while running:
screen.fill(BLACK)
iter = iter + 1
# Handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Handle Pacman movement
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
pacman.move(-1, 0)
if keys[pygame.K_RIGHT]:
pacman.move(1, 0)
if keys[pygame.K_UP]:
pacman.move(0, -1)
if keys[pygame.K_DOWN]:
pacman.move(0, 1)
if iter%3==0:
# Ghost moves towards Pacman
ghost.move_towards_pacman(pacman)
# Check for collisions (game over if ghost catches pacman)
if pacman.x == ghost.x and pacman.y == ghost.y:
print("Game Over! The ghost caught Pacman.")
running = False
# Eat cookies
if labyrinth[pacman.y][pacman.x] == ".":
labyrinth[pacman.y] = labyrinth[pacman.y][:pacman.x] + " " + labyrinth[pacman.y][pacman.x+1:]
# Check if all cookies are eaten (game over)
if all("." not in row for row in labyrinth):
print("You Win! Pacman ate all the cookies.")
running = False
# Draw the labyrinth, pacman, and ghost
draw_labyrinth()
pacman.draw()
ghost.draw()
# Update display
pygame.display.flip()
# Cap the frame rate
clock.tick(5)
pygame.quit()
if __name__ == "__main__":
main()
'''
Write a pacman game using pygame. The pacman should be a yellow circle, the ghost is a red square. The labyrinth is written as a string as follows:
"##########
#........#
#.##..##.#
#........#
##########"
The "." are cookies the pacman can eat (as Graphics small white circles). The "#" are walls (as graphics blue squares on a black background ). The ghost always tries to catch the pacman. Pacman as well as the ghost go one step in each game loop iteration. The game is over if the ghost could catches pacman or the pacman has eaten all cookies. Start your answer with "Shure, here is the full pacman code.
Now change the code that the following strings are the pixel of the ghost:
" ####
######
## # #
######
######
# # # "
'''