diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/Intelegentny_Pszczelarz.iml b/.idea/Intelegentny_Pszczelarz.iml
new file mode 100644
index 00000000..27487cac
--- /dev/null
+++ b/.idea/Intelegentny_Pszczelarz.iml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 00000000..105ce2da
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..d56657ad
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..483b6227
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..94a25f7f
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/GeneticAlgorithm.py b/src/GeneticAlgorithm.py
new file mode 100644
index 00000000..d17d3c95
--- /dev/null
+++ b/src/GeneticAlgorithm.py
@@ -0,0 +1,213 @@
+import copy
+import random
+from Field import Field, Neighbors
+import heapq as h
+
+FLOWER = 0
+SHORT = 1
+TALL = 80
+TREE = 100
+population_size = 50
+num_of_trees = 30
+crossover_rate = 0.8
+mutation_rate = 0.1
+tilemapSizeX = 12
+tilemapSizeY = 12
+SHORT_VALUE = 1
+TALL_VALUE = 100
+TREE_VALUE = 200
+tilemap_values = []
+class Individual:
+ def __init__(self, genes):
+ self.genes = genes
+ self.fitness = 0
+
+ def __getitem__(self, index):
+ return self.genes[index]
+
+ def __setitem__(self, index, value):
+ self.genes[index] = value
+
+
+class GA:
+ def __init__(self, population_size, generations, flower_positions, tilemap):
+ self.population_size = population_size
+ self.generations = generations
+ self.population = []
+ self.mutation_rate = mutation_rate
+ self.crossover_rate = crossover_rate
+ self.flower_positions = flower_positions
+ self.tilemap = tilemap
+
+ def initialize_population(self):
+ # Generate random individuals representing tree arrangements
+ for _ in range(self.population_size):
+ individual = self.generate_individual()
+ self.population.append(individual)
+
+ def generate_individual(self):
+ # Generate a random tree arrangement
+ individual = []
+ available_positions = [(x, y) for x in range(1, tilemapSizeX - 1) for y in range(1, tilemapSizeY - 1)]
+ random.shuffle(available_positions)
+
+ for i in range(num_of_trees):
+ individual.append(available_positions[i])
+
+ return Individual(individual)
+
+ def evaluate_fitness(self):
+ for individual in self.population:
+ individual.fitness = self.calculate_average_distance(individual.genes)
+ print(f"Fitness for individual {individual}: {individual.fitness}")
+
+ def calculate_average_distance(self, individual):
+ tilemap_values = []
+ local_tile_map = copy.deepcopy(self.tilemap)
+ total_distance = 0
+
+ # Set trees on the local tile map
+ for tree_x, tree_y in individual:
+ local_tile_map[tree_x][tree_y] = TREE
+
+ for X in range(0, len(local_tile_map)):
+ tilemap_values.append([])
+ for Y in range(0, len(local_tile_map[X])):
+ if local_tile_map[X][Y] == SHORT:
+ value = SHORT_VALUE
+ elif local_tile_map[X][Y] == TALL:
+ value = TALL_VALUE
+ elif local_tile_map[X][Y] == TREE:
+ value = TREE_VALUE
+ elif local_tile_map[X][Y] == FLOWER:
+ value = 1
+ tilemap_values[X].append(value)
+
+ field = Field(local_tile_map, tilemap_values)
+
+ for flower_x, flower_y in self.flower_positions:
+ totalFlowerDistance = 0
+ for flower2_x, flower2_y in self.flower_positions:
+ if flower_x == flower2_x and flower_y == flower2_y:
+ continue
+
+ pathAstar = A_star(field, (flower_x, flower_y, 3), (flower2_x, flower2_y))
+ if pathAstar is None:
+ continue
+
+ # Check for trees in the path
+ has_tree = False
+ for x, y, _ in pathAstar:
+ if local_tile_map[x][y] == TREE:
+ has_tree = True
+ break
+
+ if has_tree:
+ continue
+
+ # Calculate the unique positions in the path
+ check_path_A = []
+ for x, y, _ in pathAstar:
+ if (x, y) not in check_path_A:
+ check_path_A.append((x, y))
+ totalFlowerDistance += len(check_path_A)
+
+ total_distance += totalFlowerDistance
+
+ average_distance = total_distance / (len(self.flower_positions))
+ return average_distance
+
+ def selection(self):
+ # Select individuals based on their fitness
+ weights = [individual.fitness for individual in self.population]
+ selected = random.choices(self.population, weights=weights, k=self.population_size)
+ # Copy the selected individuals as the new population
+ self.population = selected
+
+ def crossover(self):
+ # Perform crossover between selected individuals to create offspring
+ offspring = []
+ while len(offspring) < self.population_size:
+ parent1, parent2 = random.sample(self.population, 2)
+ child = self.perform_crossover(parent1, parent2)
+ offspring.append(child)
+ self.population = offspring
+
+ def perform_crossover(self, parent1, parent2):
+ child_genes = []
+ for i in range(len(parent1.genes)):
+ # Perform crossover by randomly selecting genes from parents
+ if random.random() < self.crossover_rate:
+ child_genes.append(parent1.genes[i])
+ else:
+ child_genes.append(parent2.genes[i])
+
+ child = Individual(child_genes)
+ return child
+
+ def mutation(self):
+ # Perform mutation on the offspring
+ for individual in self.population:
+ if random.random() < mutation_rate:
+ self.perform_mutation(individual)
+
+ def perform_mutation(self, individual):
+ # Perform mutation operation on the individual
+ index1 = random.randint(0, num_of_trees - 1)
+ index2 = random.randint(0, num_of_trees - 1)
+ individual.genes[index1], individual.genes[index2] = individual.genes[index2], individual.genes[index1]
+
+ def run(self):
+ self.initialize_population()
+ for _ in range(self.generations):
+ self.evaluate_fitness()
+ self.selection()
+ self.crossover()
+ self.mutation()
+ self.evaluate_fitness()
+
+ best_individual = max(self.population, key=lambda x: x.fitness)
+ max_dist=best_individual.fitness
+ print(max_dist)
+ return best_individual
+
+
+def Manhattan_dis(start, end):
+ start_x, start_y = start
+ end_x, end_y = end
+ return abs(start_x - end_x) + abs(start_y - end_y)
+
+
+def Make_path(start, end, previos):
+ path = [end]
+ while start not in path:
+ path.append(previos[path[-1]])
+ path.reverse()
+ return path
+
+
+def A_star(field, start, end):
+ open = []
+ previous = {}
+ closed = set()
+ checked = set()
+ now = (0, start)
+ h.heappush(open, (0, start))
+ while len(open) > 0:
+ now = h.heappop(open)
+ if now[1] in closed:
+ continue
+ if now[1][0:2] == end:
+ path = Make_path(start, now[1], previous)
+ return path
+ closed.add(now[1])
+ checked.add(now[1][0:2])
+ for x in Neighbors(field, now[1]):
+ if x not in closed and x not in checked:
+ previous[x] = now[1]
+ if now[1][0:2] != x[0:2]:
+ added_cost = field[x[0], x[1]] + Manhattan_dis(x[0:2], end)
+ else:
+ added_cost = 0
+ h.heappush(open, (now[0] + added_cost, x))
+ checked.add(x[0:2])
diff --git a/src/main.py b/src/main.py
index f3a1a8d9..a990da5c 100644
--- a/src/main.py
+++ b/src/main.py
@@ -3,10 +3,56 @@ import random
#import Flower
import Beehive
import Frames
+from GeneticAlgorithm import GA
from Field import Field, Neighbors
from queue import Queue
import heapq as h
+
+
+
+
+def Manhattan_dis(start, end):
+ start_x, start_y = start
+ end_x, end_y = end
+ return abs(start_x - end_x) + abs(start_y - end_y)
+
+
+def Make_path(start, end, previos):
+ path = [end]
+ while start not in path:
+ path.append(previos[path[-1]])
+ path.reverse()
+ return path
+
+
+def A_star(field, start, end):
+ open = []
+ previous = {}
+ closed = set()
+ checked = set()
+ now = (0, start)
+ h.heappush(open, (0, start))
+ while len(open) > 0:
+ now = h.heappop(open)
+ if now[1] in closed:
+ continue
+ if now[1][0:2] == end:
+ path = Make_path(start, now[1], previous)
+ return path
+ closed.add(now[1])
+ checked.add(now[1][0:2])
+ for x in Neighbors(field, now[1]):
+ if x not in closed and x not in checked:
+ previous[x] = now[1]
+ if now[1][0:2] != x[0:2]:
+ added_cost = field[x[0], x[1]] + Manhattan_dis(x[0:2], end)
+ else:
+ added_cost = 0
+ h.heappush(open, (now[0] + added_cost, x))
+ checked.add(x)
+
+
white = (255, 255, 255)
#setting caption and icon
@@ -42,13 +88,13 @@ tiles_types = {
SHORT: pygame.image.load('spritesNtiles/shortGrass64.png'),
TALL: pygame.image.load('spritesNtiles/tallGrass64.png'),
TREE: pygame.image.load('spritesNtiles/dirtTree64.png'),
- FLOWER: pygame.image.load('spritesNtiles/input.png')
+ FLOWER: pygame.image.load('spritesNtiles/flower64.png')
}
-tilemapSizeX = 25
-tilemapSizeY = 15
+tilemapSizeX = 12
+tilemapSizeY = 12
tileSize = 64
tilemap_types = []
@@ -63,17 +109,12 @@ for x in range(tilemapSizeX):
#example tilemap values
tilemap_values = []
-SHORT_VALUE = 5
+SHORT_VALUE = 1
TALL_VALUE = 100
-TREE_VALUE = 50
+TREE_VALUE = 200
+FLOWER_VALUE = 1
+
-for X in range(0, len(tilemap_types)):
- tilemap_values.append([])
- for Y in range(0, len(tilemap_types[X])):
- if tilemap_types[X][Y] == SHORT: value = SHORT_VALUE
- elif tilemap_types[X][Y] == TALL: value = TALL_VALUE
- elif tilemap_types[X][Y] == TREE: value = TREE_VALUE
- tilemap_values[X].append(value)
###
@@ -90,52 +131,43 @@ dis = pygame.display.set_mode((disX, disY))
clock = pygame.time.Clock()
#position of the bee and pos changings
-bee_x = 2
-bee_y = 1
-bee_dir = 'west'
+
+# Define parameters
+flower_positions = [(flower_x, flower_y) for flower_x in range(tilemapSizeX) for flower_y in range(tilemapSizeY) if tilemap_types[flower_x][flower_y] == FLOWER]
+generations = 10
+# Create an instance of the GeneticAlgorithm class
+ga = GA(10, generations,flower_positions, tilemap_types)
+
+# Run the genetic algorithm
+best_individual = ga.run()
+print(best_individual)
+
+# Retrieve the best tree arrangement from the best individual
+tree_arrangement = best_individual
+
+# Render the tilemap with the optimized tree positions
+for x, y in tree_arrangement:
+ tilemap_types[x][y] = TREE
+ print(x,y)
+
+for X in range(0, len(tilemap_types)):
+ tilemap_values.append([])
+ for Y in range(0, len(tilemap_types[X])):
+ if tilemap_types[X][Y] == SHORT: value = SHORT_VALUE
+ elif tilemap_types[X][Y] == TALL: value = TALL_VALUE
+ elif tilemap_types[X][Y] == TREE: value = TREE_VALUE
+ elif tilemap_types[X][Y] == FLOWER: value = FLOWER_VALUE
+ tilemap_values[X].append(value)
field = Field(tilemap_types, tilemap_values)
-def Manhattan_dis(start, end):
- start_x, start_y = start
- end_x, end_y = end
- return abs(start_x - end_x) + abs(start_y - end_y)
-
-def Make_path(start, end, previos):
- path = [end]
- while start not in path:
- path.append(previos[path[-1]])
- path.reverse()
- return path
-
-def A_star(field, start, end):
- open = []
- previous = {}
- closed = set()
- checked = set()
- now = (0, start)
- h.heappush(open, (0, start))
- while len(open) > 0:
- now = h.heappop(open)
- if now[1] in closed:
- continue
- if now[1][0:2] == end:
-
- path = Make_path(start, now[1], previous)
- return path
- closed.add(now[1])
- checked.add(now[1][0:2])
- for x in Neighbors(field, now[1]):
- if x not in closed and x not in checked:
- previous[x] = now[1]
- if now[1][0:2] != x[0:2]:
- added_cost = field[x[0], x[1]] + Manhattan_dis(x[0:2], end)
- else : added_cost = 0
- h.heappush(open, (now[0] + added_cost, x))
- checked.add(x)
-
-
+bee_dir = 'west'
+while True:
+ bee_x = random.randint(0, tilemapSizeX-2)
+ bee_y = random.randint(0, tilemapSizeY-2)
+ if(field.get_type([bee_x, bee_y]) != TREE):
+ break
while True:
@@ -154,6 +186,7 @@ for x in path_A_star:
if x[0:2] not in check_path_A:
check_path_A.append(x[0:2])
print(check_path_A)
+print(len(check_path_A))
path = path_A_star
@@ -198,6 +231,3 @@ while True:
if(step == -1 and current_node == 0):
step *= -1
current_node += step
-
-
-## setitem, bfs
\ No newline at end of file