assignment 3 done?
parent
cf9131b760
commit
c9869979d3
|
|
@ -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 selected individual
|
||||||
# Add the 32 Bit individual in gray code to population
|
selected_pop.append(gray_pop_copy[i])
|
||||||
selected_pop.append(gray_pop[i])
|
|
||||||
|
# Remove selected individual and their fitness
|
||||||
# Calc new sum of 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]
|
parent_a = population_copy[i]
|
||||||
|
parent_b = population_copy[i + 1]
|
||||||
|
|
||||||
# Create two new offspring by swapping parts at XOVER_POINT
|
# 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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
" ####
|
||||||
|
######
|
||||||
|
## # #
|
||||||
|
######
|
||||||
|
######
|
||||||
|
# # # "
|
||||||
|
|
||||||
|
'''
|
||||||
Loading…
Reference in New Issue