├── .idea ├── AI_P2.iml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── AI_P2.pdf ├── AI_P2_Report.pdf ├── README.md ├── geneticProject ├── .idea │ ├── .gitignore │ ├── geneticProject.iml │ ├── inspectionProfiles │ │ ├── Project_Default.xml │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── AdditionalFunctions.py ├── Chromosome.py ├── Game.py ├── Genetic.py ├── GraphicalUserInterface.py ├── Main.py ├── attachments │ └── levels │ │ ├── level1.txt │ │ ├── level10.txt │ │ ├── level2.txt │ │ ├── level3.txt │ │ ├── level4.txt │ │ ├── level5.txt │ │ ├── level6.txt │ │ ├── level7.txt │ │ ├── level8.txt │ │ └── level9.txt └── picture_for_gui │ ├── cell.png │ ├── flag.jpg │ ├── ghost.jpg │ ├── goomba.jpg │ ├── mushrooms.jpg │ ├── superMario1.png │ └── superMario2.png ├── sample run l9.jpg └── sample_run_level8.gif /.idea/AI_P2.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 51 | 52 | 53 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 1622388230395 89 | 96 | 97 | 1622561880307 98 | 103 | 104 | 1622566701036 105 | 110 | 111 | 1622569000131 112 | 117 | 118 | 1622573039049 119 | 124 | 127 | 128 | 130 | 131 | 132 | 133 | 134 | 135 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /AI_P2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Genetic-Algorithm/4bfb71e39a87e1600623a2912e886d4e8ff76622/AI_P2.pdf -------------------------------------------------------------------------------- /AI_P2_Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Genetic-Algorithm/4bfb71e39a87e1600623a2912e886d4e8ff76622/AI_P2_Report.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Genetic Algorithm 2 | Artificial Intelligence Course 2nd Project: Implementing genetic algorithm in order to solve Super Mario game. 3 |
4 | In this group project we ([Amirhossein-Rajabpour](https://github.com/Amirhossein-Rajabpour) and [arminZolfaghari](https://github.com/arminZolfaghari)) implemented `genetic algorithm` to solve Super-Mario game.
5 | Mario can jump, go straight or dodge. Mario must jump over Goomba and must dodge when it reaches Lakito. If Mario jumps 2 step before Goomba it can kill Goomba and then it gets more points. 6 | If Mario jumps when it reaches at the end of the board it gets more points (but it's adjustable). If Mario jumps on a Goomba it gets additional points. 7 |
8 | 9 | We implemented different types of `crossover`: 10 | * crossover from one point which is chosen and randomly 11 | * crossover from one point which you can specify (by index) 12 | * crossover from two points which are chosen randomly 13 | * crossover from two points which you can specify (by index) 14 | 15 | and `selection`: 16 | * weighted random 17 | * best selection 18 | 19 | that you can choose from. Also you can the number of `initial population` and `mutation probability`. 20 |
21 | A sample for inputs:
22 | 23 | 24 | ![alt text](https://github.com/Amirhossein-Rajabpour/Genetic-Algorithm/blob/main/sample%20run%20l9.jpg "sample run") 25 | 26 |
27 | A sample run with GUI (Level 8): 28 | 29 | 30 | ![alt text](https://github.com/Amirhossein-Rajabpour/Genetic-Algorithm/blob/main/sample_run_level8.gif) 31 | 32 | 33 | Check full description (in persian): [here](https://github.com/Amirhossein-Rajabpour/Genetic-Algorithm/blob/main/AI_P2.pdf) 34 |
35 | Project report (in persian): [here](https://github.com/Amirhossein-Rajabpour/Genetic-Algorithm/blob/main/AI_P2_Report.pdf) 36 |
37 | Check our other AI Course projects: 38 | * [Project 1: Searching Algorithms (IDS, BBFS, A*)](https://github.com/arminZolfaghari/AI_project1) 39 | * [Project 3: Constraint-Satisfaction-Problems](https://github.com/Amirhossein-Rajabpour/Constraint-Satisfaction-Problems) 40 | * [Project 4: NLP Comment Filtering](https://github.com/arminZolfaghari/NLP) 41 | -------------------------------------------------------------------------------- /geneticProject/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /../../../../../../../../../../:\Armin\AUT\CEIT\Sem6\Artificial Intelligence\Project\AI_P2\geneticProject\.idea/dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /geneticProject/.idea/geneticProject.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /geneticProject/.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | -------------------------------------------------------------------------------- /geneticProject/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /geneticProject/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /geneticProject/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /geneticProject/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /geneticProject/AdditionalFunctions.py: -------------------------------------------------------------------------------- 1 | from Chromosome import * 2 | from Game import * 3 | import random 4 | 5 | 6 | # continuous two "2" movement is ok but continuous three "2" movement isn't ok! 7 | # continuous two "1" movement isn't ok 8 | def check_game_rules(current_string, new_char): 9 | res = True 10 | if len(current_string) >= 1 and new_char == "1" and current_string[-1] == "1": 11 | res = False 12 | elif len(current_string) >= 2 and new_char == "2" and current_string[-1] == "2" and current_string[-2] == "2": 13 | res = False 14 | 15 | return res 16 | 17 | 18 | def generate_randomly_string(length): 19 | string, i = "", 0 20 | while i < length: 21 | random_number = random.randint(1, 10) 22 | char = "" 23 | # probability 50 => select "0" (move right), 24 | # probability 30 => select "1" (jump and move right), 25 | # probability 20 => select "2" (dodge and move right) 26 | if random_number <= 5: 27 | char = "0" 28 | i += 1 29 | elif 5 < random_number <= 8: 30 | if check_game_rules(string, "1"): 31 | char = "1" 32 | i += 1 33 | elif 8 < random_number <= 10: 34 | if check_game_rules(string, "2"): 35 | char = "2" 36 | i += 1 37 | string += char 38 | 39 | return string 40 | 41 | 42 | def read_level_game(test_case_name): 43 | path = "./attachments/levels/" + test_case_name 44 | with open(path, 'r') as file: 45 | game_plate = file.readline() 46 | 47 | return game_plate 48 | 49 | 50 | def generate_initial_population(number_of_population, game_plate_string, score_mode): 51 | game = Game(game_plate_string) 52 | chromosome_length = len(game_plate_string) 53 | array_of_chromosome = [] 54 | for i in range(number_of_population): 55 | chromosome_string = generate_randomly_string(chromosome_length) 56 | chromosome_score, chromosome_failure_points = game.get_score(chromosome_string, score_mode) 57 | chromosome = Chromosome(chromosome_string, chromosome_score, 1, chromosome_failure_points) 58 | array_of_chromosome.append(chromosome) 59 | 60 | return array_of_chromosome 61 | 62 | 63 | def sort_by_score(array_of_chromosomes): 64 | # sort by their scores 65 | # return sorted array 66 | # return 67 | array_of_chromosomes.sort(key=lambda x: x.score, reverse=True) 68 | 69 | 70 | def return_scores(array_of_chromosomes): 71 | scores = [chromosome.score for chromosome in array_of_chromosomes] 72 | return scores -------------------------------------------------------------------------------- /geneticProject/Chromosome.py: -------------------------------------------------------------------------------- 1 | class Chromosome: 2 | def __init__(self, string, score, generation, failure_points): 3 | self.string = string 4 | self.score = score 5 | self.generation = generation 6 | self.failure_points = failure_points -------------------------------------------------------------------------------- /geneticProject/Game.py: -------------------------------------------------------------------------------- 1 | import copy 2 | 3 | 4 | class Game: 5 | def __init__(self, game_plate): 6 | # Get a strings as game_plate 7 | # Store level length to determine if a sequence of action passes all the steps 8 | self.game_plate = game_plate 9 | 10 | def calculate_maximum_substring_length(self, failure_points): 11 | game_plate = self.game_plate 12 | length_game_plate = len(game_plate) 13 | substring_length = [] 14 | 15 | failure_points.insert(0, 0) 16 | failure_points.append(length_game_plate) 17 | 18 | for i in range(1, len(failure_points)): 19 | length = failure_points[i] - failure_points[i - 1] 20 | substring_length.append(length) 21 | 22 | return max(substring_length) 23 | 24 | def get_score(self, actions, get_score_mode): 25 | # Get an action sequence and determine the steps taken/score 26 | # Return a tuple, the first one indicates if these actions result in victory 27 | # and the second one shows the steps taken 28 | 29 | game_plate = self.game_plate 30 | length_game_plate = len(game_plate) 31 | failure_points = [] 32 | steps = 0 33 | scores = 0 34 | for i in range(length_game_plate): 35 | current_step = game_plate[i] 36 | if current_step == '_': 37 | steps += 1 38 | elif current_step == 'G': 39 | if actions[i - 1] == '1': 40 | steps += 1 41 | elif i - 2 >= 0 and actions[i - 2] == "1": # score section project 42 | steps += 1 43 | scores += 2 44 | else: failure_points.append(i) 45 | 46 | elif current_step == "M": # score section project 47 | if actions[i - 1] != "1": scores += 2 48 | steps += 1 49 | # elif i == length_game_plate - 1 and current_step == "1": # score section project 50 | # steps += 1 51 | # scores += 1 52 | elif current_step == 'L': 53 | if i - 2 >= 0: 54 | if actions[i - 1] == "2" and actions[i - 2] != "1": 55 | steps += 1 56 | else: failure_points.append(i) 57 | elif actions[i - 1] == '2': 58 | steps += 1 59 | else: failure_points.append(i) 60 | else: 61 | failure_points.append(i) 62 | 63 | if actions[-1] == "1": scores += 1 # score section project (when final action is jump and move right) 64 | 65 | # print(scores) 66 | # print(failure_points) 67 | failure_points_copy = copy.deepcopy(failure_points) 68 | maximum_substring_length = self.calculate_maximum_substring_length(failure_points_copy) 69 | 70 | # print(maximum_substring_length) 71 | if get_score_mode == "1": 72 | if len(failure_points) == 0: scores += 5 # if failure_points is empty => chromosome is win. 73 | 74 | return maximum_substring_length + scores, failure_points -------------------------------------------------------------------------------- /geneticProject/Genetic.py: -------------------------------------------------------------------------------- 1 | from AdditionalFunctions import * 2 | from Chromosome import * 3 | import math 4 | MAX_GENERATION = 10000 5 | 6 | 7 | def is_end(number_generation): 8 | if number_generation > MAX_GENERATION: 9 | return True 10 | return False 11 | 12 | 13 | def calculate_average_score(array_of_chromosomes): 14 | sum_scores = 0 15 | for chromosome in array_of_chromosomes: 16 | sum_scores += chromosome.score 17 | return sum_scores / len(array_of_chromosomes) 18 | 19 | 20 | def find_max_score(array_of_chromosomes): 21 | array_of_chromosomes.sort(key=lambda x: x.score, reverse=True) 22 | return array_of_chromosomes[0].score 23 | 24 | 25 | def find_min_score(array_of_chromosomes): 26 | array_of_chromosomes.sort(key=lambda x: x.score, reverse=False) 27 | return array_of_chromosomes[0].score 28 | 29 | 30 | def choose_two_parents(array_of_chromosomes): 31 | parent1, parent2 = random.sample(array_of_chromosomes, 2) 32 | return parent1, parent2 33 | 34 | 35 | def selection(array_of_prev_chromosomes, selection_mode): 36 | selected_parents = [] 37 | len_population = len(array_of_prev_chromosomes) 38 | 39 | # randomly (with their scores as their weights) select from previous generation 40 | if selection_mode == 'random': 41 | score_weights = return_scores(array_of_prev_chromosomes) 42 | selected_parents += random.choices(list(array_of_prev_chromosomes), weights=score_weights, 43 | k=math.ceil(len_population * 0.5)) 44 | 45 | # sort array_of_prev_chromosomes and take top chromosomes 46 | elif selection_mode == 'best': 47 | sort_by_score(array_of_prev_chromosomes) 48 | selected_parents += array_of_prev_chromosomes[:math.ceil(len_population * 0.5)] 49 | 50 | return selected_parents 51 | 52 | 53 | def crossover(chromosome1, chromosome2, crossover_point, crossover_mode): 54 | # caution: chromosomes are objects here not their strings! 55 | offspring1, offspring2 = "", "" 56 | chromosome_length = len(chromosome1.string) 57 | 58 | if crossover_mode == 'random 1': 59 | crossing_point = random.randint(2, chromosome_length - 2) 60 | offspring1 = chromosome1.string[:crossing_point] + chromosome2.string[crossing_point:] 61 | offspring2 = chromosome2.string[:crossing_point] + chromosome1.string[crossing_point:] 62 | 63 | elif crossover_mode == 'specified 1': 64 | offspring1 = chromosome1.string[:crossover_point] + chromosome2.string[crossover_point:] 65 | offspring2 = chromosome2.string[:crossover_point] + chromosome1.string[crossover_point:] 66 | 67 | elif crossover_mode == 'random 2': 68 | crossing_points = random.sample(range(2,chromosome_length-2), 2) 69 | crossing_points.sort() 70 | offspring1 = chromosome1.string[0:crossing_points[0]] + chromosome2.string[crossing_points[0]:crossing_points[1]] + chromosome1.string[crossing_points[1]:] 71 | offspring2 = chromosome2.string[0:crossing_points[0]] + chromosome1.string[crossing_points[0]:crossing_points[1]] + chromosome2.string[crossing_points[1]:] 72 | 73 | 74 | elif crossover_mode == 'specified 2': 75 | offspring1 = chromosome1.string[:crossover_point[0]] + chromosome2.string[crossover_point[0]:crossover_point[1]] + chromosome1.string[crossover_point[1]:] 76 | offspring2 = chromosome2.string[:crossover_point[0]] + chromosome1.string[crossover_point[0]:crossover_point[1]] + chromosome2.string[crossover_point[1]:] 77 | 78 | return offspring1, offspring2 79 | 80 | 81 | def mutation(chromosome, mutation_probability, game, score_mode): 82 | chromosome_failure_points = chromosome.failure_points 83 | if len(chromosome_failure_points) > 0: 84 | mutation_index = random.sample(chromosome_failure_points, 1)[0] 85 | new_value_mutation_index = "0" 86 | left_part = chromosome.string[:mutation_index] 87 | right_part = chromosome.string[mutation_index + 1:] 88 | 89 | chromosome.string = left_part + new_value_mutation_index + right_part 90 | new_score, new_failure_points = game.get_score(chromosome.string, score_mode) 91 | chromosome.score = new_score 92 | chromosome.failure_points = new_failure_points 93 | # chromosome.update_score_failurepoints(new_score, new_failure_points) 94 | 95 | 96 | def check_goal_chromosome(new_generation): 97 | new_generation_copy = copy.deepcopy(new_generation) 98 | new_generation_copy.sort(key=lambda x: x.score, reverse=True) 99 | for chromosome in new_generation_copy: 100 | if len(chromosome.failure_points) == 0: 101 | return True, chromosome 102 | 103 | return False, False 104 | 105 | 106 | class Genetic: 107 | # population is a dictionary of generation and array of chromosome objects 108 | # => {1: [chromosome1, chromosome2, ...], 2:[chromosomeK, ...]} 109 | def __init__(self, generations, game_plate, selection_mode, crossover_mode, crossover_point, mutation_prob, 110 | score_mode): 111 | self.generations = generations 112 | self.game_plate = game_plate 113 | self.selection_mode = selection_mode 114 | self.crossover_mode = crossover_mode 115 | self.crossover_point = crossover_point 116 | self.mutation_prob = mutation_prob 117 | self.score_mode = score_mode 118 | self.best_answer = '' 119 | self.generation_average_scores = {} 120 | self.generation_max_score = {} 121 | self.generation_min_score = {} 122 | 123 | len_population = len(self.generations[1]) 124 | self.generation_average_scores[1] = calculate_average_score(self.generations[1]) 125 | self.generation_max_score[1] = find_max_score(self.generations[1]) 126 | self.generation_min_score[1] = find_min_score(self.generations[1]) 127 | 128 | current_generation = 2 129 | game = Game(self.game_plate) 130 | 131 | while len(self.generations) < MAX_GENERATION: 132 | 133 | # 70% of new population are from new chromosome (children of selected parents) 134 | # 30% of new population are from selected parents (after selection step) 135 | 136 | # selection step 137 | selected_parents = selection(self.generations[current_generation - 1], self.selection_mode) 138 | 139 | # crossover step 140 | new_generation, new_generation_strings = [], [] 141 | while True: 142 | 143 | parent1, parent2 = choose_two_parents(selected_parents) 144 | child1, child2 = crossover(copy.deepcopy(parent1), copy.deepcopy(parent2), self.crossover_point, self.crossover_mode) 145 | 146 | if child1 not in new_generation_strings: 147 | score1, failure_points1 = game.get_score(child1, self.score_mode) 148 | new_generation.append(Chromosome(child1, score1, current_generation, failure_points1)) 149 | new_generation_strings.append(child1) 150 | if len(new_generation_strings) == math.ceil(len_population * 0.7): 151 | break 152 | 153 | if child2 not in new_generation_strings: 154 | score2, failure_points2 = game.get_score(child2, self.score_mode) 155 | new_generation.append(Chromosome(child2, score2, current_generation, failure_points2)) 156 | new_generation_strings.append(child2) 157 | if len(new_generation_strings) == math.ceil(len_population * 0.7): 158 | break 159 | 160 | new_generation += selected_parents 161 | 162 | # mutation step 163 | self.generations[current_generation] = new_generation 164 | for chromosome in self.generations[current_generation]: 165 | if random.random() < self.mutation_prob: 166 | mutation(chromosome, self.mutation_prob, game, self.score_mode) 167 | 168 | self.generation_average_scores[current_generation] = calculate_average_score(self.generations[current_generation]) 169 | self.generation_max_score[current_generation] = find_max_score(self.generations[current_generation]) 170 | self.generation_min_score[current_generation] = find_min_score(self.generations[current_generation]) 171 | 172 | find_chromosome, goal_chromosome = check_goal_chromosome(self.generations[current_generation]) 173 | if find_chromosome: 174 | self.best_answer = goal_chromosome 175 | print(len(self.generations)) 176 | break 177 | 178 | current_generation += 1 179 | -------------------------------------------------------------------------------- /geneticProject/GraphicalUserInterface.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | from tkinter import ttk 3 | from PIL import ImageTk, Image 4 | import copy 5 | 6 | root = tk.Tk() 7 | 8 | 9 | def create_game_plate_arr(game_plate_str): 10 | end_string = "_F______" 11 | game_plate_str += end_string 12 | first_row, second_row = "", "" 13 | for char in game_plate_str: 14 | if char == "_": 15 | first_row += "_" 16 | second_row += "_" 17 | elif char == "G": 18 | first_row += "_" 19 | second_row += "G" 20 | elif char == "L": 21 | first_row += "L" 22 | second_row += "_" 23 | elif char == "M": 24 | first_row += "_" 25 | second_row += "M" 26 | elif char == "F": 27 | first_row += "_" 28 | second_row += "F" 29 | 30 | first_row_split = [char for char in first_row] 31 | second_row_split = [char for char in second_row] 32 | game_plate_arr = [first_row_split, second_row_split] 33 | return game_plate_arr 34 | 35 | 36 | def get_first_state(game_plate_arr): 37 | game_plate_arr_copy = copy.deepcopy(game_plate_arr) 38 | game_plate_arr_copy[1][0] = "SM" # super mario 39 | return game_plate_arr_copy 40 | 41 | 42 | def get_super_mario_index(arr): 43 | string1, string2 = "SM", "SML" 44 | row_number = len(arr) 45 | for i in range(row_number): 46 | if string1 in arr[i]: 47 | index_j = arr[i].index(string1) 48 | return i, index_j 49 | 50 | if string2 in arr[i]: 51 | index_j = arr[i].index(string2) 52 | return i, index_j 53 | 54 | 55 | def get_sequence_movement(win_path, game_plate_arr): 56 | sequence_movement_arr = [] 57 | super_mario_index = 0 58 | 59 | first_state = get_first_state(game_plate_arr) 60 | sequence_movement_arr.append(first_state) 61 | 62 | i = 0 63 | while i < len(win_path): 64 | current_super_mario_index = get_super_mario_index(sequence_movement_arr[-1]) 65 | 66 | if win_path[i] == "0": 67 | next_state = copy.deepcopy(sequence_movement_arr[-1]) 68 | next_state[current_super_mario_index[0]][current_super_mario_index[1]] = "_" 69 | next_state[1][current_super_mario_index[1] + 1] = "SM" 70 | sequence_movement_arr.append(next_state) 71 | i += 1 72 | 73 | elif win_path[i] == "1": 74 | next_state = copy.deepcopy(sequence_movement_arr[-1]) 75 | next_state[current_super_mario_index[0]][current_super_mario_index[1]] = "_" 76 | next_state[0][current_super_mario_index[1] + 1] = "SM" 77 | sequence_movement_arr.append(next_state) 78 | two_next_state = copy.deepcopy(sequence_movement_arr[-1]) 79 | two_next_state[0][current_super_mario_index[1] + 1] = "_" 80 | two_next_state[1][current_super_mario_index[1] + 2] = "SM" 81 | sequence_movement_arr.append(two_next_state) 82 | i += 2 83 | 84 | elif win_path[i] == "2": 85 | next_state = copy.deepcopy(sequence_movement_arr[-1]) 86 | next_state[current_super_mario_index[0]][current_super_mario_index[1]] = "_" 87 | next_state[1][current_super_mario_index[1] + 1] = "SML" 88 | sequence_movement_arr.append(next_state) 89 | i += 1 90 | 91 | return sequence_movement_arr 92 | 93 | 94 | # print(get_sequence_movement("0000", test)) 95 | 96 | 97 | class GraphicalUserInterface(): 98 | 99 | def __init__(self, path): 100 | self.path = path 101 | self.step = 0 102 | self.Visualize() 103 | 104 | def Visualize(self, e=1): 105 | num_rows, num_cols = 2, 8 106 | 107 | WIDTH = (num_cols * 100) + 10 108 | HEIGHT = (num_rows * 100) + 10 109 | root.geometry(f"{WIDTH}x{HEIGHT}") 110 | root.title("goal chromosome!") 111 | root.config(bg="white") 112 | 113 | root.columnconfigure(0, weight=num_cols) 114 | root.columnconfigure(1, weight=num_rows) 115 | 116 | super_mario_image = ImageTk.PhotoImage(Image.open('./picture_for_gui/superMario1.png').resize((100, 100), Image.ANTIALIAS)) 117 | half_super_mario_image = ImageTk.PhotoImage(Image.open('./picture_for_gui/superMario2.png').resize((100, 100), Image.ANTIALIAS)) 118 | mushroom_image = ImageTk.PhotoImage(Image.open('./picture_for_gui/mushrooms.jpg').resize((100, 100), Image.ANTIALIAS)) 119 | ghost_image = ImageTk.PhotoImage(Image.open('./picture_for_gui/ghost.jpg').resize((100, 100), Image.ANTIALIAS)) 120 | goomba_image = ImageTk.PhotoImage(Image.open('./picture_for_gui/goomba.jpg').resize((100, 100), Image.ANTIALIAS)) 121 | cell_image = ImageTk.PhotoImage(Image.open('./picture_for_gui/cell.png').resize((100, 100), Image.ANTIALIAS)) 122 | flag_image = ImageTk.PhotoImage(Image.open('./picture_for_gui/flag.jpg').resize((100, 100), Image.ANTIALIAS)) 123 | 124 | if self.step < len(self.path): 125 | root.geometry(f"{WIDTH}x{HEIGHT}") 126 | root.title("goal chromosome!") 127 | root.config(bg="white") 128 | 129 | root.columnconfigure(0, weight=num_cols) 130 | root.columnconfigure(1, weight=num_rows) 131 | super_mario_index = get_super_mario_index(self.path[self.step]) 132 | super_mario_index_i, super_mario_index_j = super_mario_index[0], super_mario_index[1] - 1 133 | 134 | for r in range(num_rows): 135 | for c in range(num_cols): 136 | if self.path[self.step][r][c + super_mario_index_j] == "_": 137 | cell_label = ttk.Label(root, image=cell_image) 138 | cell_label.grid(column=c, row=r) 139 | 140 | 141 | elif self.path[self.step][r][c + super_mario_index_j] == "G": 142 | gumpa_label = ttk.Label(root, image=goomba_image) 143 | gumpa_label.grid(column=c, row=r) 144 | 145 | elif self.path[self.step][r][c + super_mario_index_j] == "L": 146 | ghost_label = ttk.Label(root, image=ghost_image) 147 | ghost_label.grid(column=c, row=r) 148 | 149 | elif self.path[self.step][r][c + super_mario_index_j] == "SM": 150 | super_mario_label = ttk.Label(root, image=super_mario_image) 151 | super_mario_label.grid(column=c, row=r) 152 | 153 | elif self.path[self.step][r][c + super_mario_index_j] == "M": 154 | mushroom_label = ttk.Label(root, image=mushroom_image) 155 | mushroom_label.grid(column=c, row=r) 156 | 157 | elif self.path[self.step][r][c + super_mario_index_j] == "SML": 158 | half_super_mario_label = ttk.Label(root, image=half_super_mario_image) 159 | half_super_mario_label.grid(column=c, row=r) 160 | 161 | elif self.path[self.step][r][c + super_mario_index_j] == "F": 162 | flag_label = ttk.Label(root, image=flag_image) 163 | flag_label.grid(column=c, row=r) 164 | 165 | self.step += 1 166 | root.after(1000, self.Visualize) 167 | root.mainloop() -------------------------------------------------------------------------------- /geneticProject/Main.py: -------------------------------------------------------------------------------- 1 | from Genetic import * 2 | from AdditionalFunctions import * 3 | from GraphicalUserInterface import * 4 | import matplotlib.pyplot as plt 5 | 6 | 7 | generation_dict = {} 8 | 9 | def get_input_from_user(): 10 | test_case = input("Enter your level: ") 11 | test_case_file_name = test_case + ".txt" 12 | num_of_population = input("Enter the amount of population: ") 13 | score_mode = input("Enter score mode:\n0) Without calculating winning points\n1) With calculating winning points\n") 14 | selection_mode_input = input("Enter selection mode:\n1) Weighted random selection\n2) Best selection\n") 15 | if selection_mode_input == '1': 16 | selection_mode = 'random' 17 | elif selection_mode_input == '2': 18 | selection_mode = 'best' 19 | else: 20 | print('Wrong selection mode input!') 21 | exit() 22 | 23 | crossover_mode_input = input("Enter crossover mode:\n1) One point random crossover\n2) one point specified crossover\n3) two points random crossover\n4) two points specified crossover\n") 24 | if crossover_mode_input == '1': 25 | crossover_mode = 'random 1' 26 | crossover_point = 0 27 | elif crossover_mode_input == '2': 28 | crossover_mode = 'specified 1' 29 | crossover_point = int(input('Enter crossover point: \n')) 30 | elif crossover_mode_input == '3': 31 | crossover_mode = 'random 2' 32 | crossover_point = 0 33 | elif crossover_mode_input == '4': 34 | crossover_mode = 'specified 2' 35 | crossover_point = input('Enter crossover points: \n').split(" ") 36 | crossover_point = [int(point) for point in crossover_point] 37 | else: 38 | print('Wrong crossover mode input!') 39 | exit() 40 | 41 | mutation_prob = input("Enter mutation probability: \n") 42 | return test_case_file_name, num_of_population, score_mode, selection_mode, crossover_mode, crossover_point, float(mutation_prob) 43 | 44 | 45 | 46 | def start_genetic_algorithm(game_plate, num_of_population, score_mode, selection_mode, crossover_mode, crossover_point, mutation_prob): 47 | initial_population = generate_initial_population(int(num_of_population), game_plate, score_mode) 48 | generations = {1: initial_population} 49 | genetic = Genetic(generations, game_plate, selection_mode, crossover_mode, crossover_point, mutation_prob, score_mode) 50 | return genetic 51 | 52 | 53 | def plot_results(genetic): 54 | generation_average_scores = genetic.generation_average_scores 55 | generation_max_scores = genetic.generation_max_score 56 | generation_min_scores = genetic.generation_min_score 57 | 58 | plt.plot(*zip(*sorted(generation_average_scores.items())), color='r', label='avg scores') 59 | plt.plot(*zip(*sorted(generation_max_scores.items())), color='g', label='max scores') 60 | plt.plot(*zip(*sorted(generation_min_scores.items())), color='b', label='min scores') 61 | 62 | plt.xlabel('generations') 63 | plt.ylabel('score') 64 | plt.legend(loc=0) 65 | plt.show() 66 | 67 | 68 | if __name__ == "__main__": 69 | test_case_file_name, num_of_population, score_mode, selection_mode, crossover_mode, crossover_point, mutation_prob = get_input_from_user() 70 | game_plate_str = read_level_game(test_case_file_name) 71 | result_genetic_algorithm = start_genetic_algorithm(game_plate_str, num_of_population, score_mode, selection_mode, crossover_mode, crossover_point, mutation_prob) 72 | 73 | if len(result_genetic_algorithm.generation_average_scores) != 10000: 74 | result_path_str = result_genetic_algorithm.best_answer.string 75 | print("String of goal chromosome: {}".format(result_path_str)) 76 | print("Generation of goal chromosome: {}".format(result_genetic_algorithm.best_answer.generation)) 77 | print("Score of goal chromosome: {}".format(result_genetic_algorithm.best_answer.score)) 78 | 79 | # plot results 80 | plot_results(result_genetic_algorithm) 81 | 82 | # render GUI 83 | game_plate_arr = create_game_plate_arr(game_plate_str) 84 | super_mario_movements = get_sequence_movement(result_path_str, game_plate_arr) 85 | game = GraphicalUserInterface(super_mario_movements) 86 | game.Visualize() 87 | 88 | else: 89 | print("can't win the game or maximum generation limit reached!") 90 | -------------------------------------------------------------------------------- /geneticProject/attachments/levels/level1.txt: -------------------------------------------------------------------------------- 1 | __M_____ -------------------------------------------------------------------------------- /geneticProject/attachments/levels/level10.txt: -------------------------------------------------------------------------------- 1 | _G___M_____LL_____G__G______L_____G____MM___G_G____LML____G___L____LMG___G___GML______G____L___MG___ -------------------------------------------------------------------------------- /geneticProject/attachments/levels/level2.txt: -------------------------------------------------------------------------------- 1 | ____G_____ -------------------------------------------------------------------------------- /geneticProject/attachments/levels/level3.txt: -------------------------------------------------------------------------------- 1 | __G___L_ -------------------------------------------------------------------------------- /geneticProject/attachments/levels/level4.txt: -------------------------------------------------------------------------------- 1 | __G__G_L___ -------------------------------------------------------------------------------- /geneticProject/attachments/levels/level5.txt: -------------------------------------------------------------------------------- 1 | ____G_ML__G_ -------------------------------------------------------------------------------- /geneticProject/attachments/levels/level6.txt: -------------------------------------------------------------------------------- 1 | ____G_MLGL_G_ -------------------------------------------------------------------------------- /geneticProject/attachments/levels/level7.txt: -------------------------------------------------------------------------------- 1 | _M_M_GM___LL__G__L__G_M__ -------------------------------------------------------------------------------- /geneticProject/attachments/levels/level8.txt: -------------------------------------------------------------------------------- 1 | ____G_G_MMM___L__L_G_____G___M_L__G__L_GM____L____ -------------------------------------------------------------------------------- /geneticProject/attachments/levels/level9.txt: -------------------------------------------------------------------------------- 1 | ___M____MGM________M_M______M____L___G____M____L__G__GM__L____ML__G___G___L___G__G___M__L___G____M__ -------------------------------------------------------------------------------- /geneticProject/picture_for_gui/cell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Genetic-Algorithm/4bfb71e39a87e1600623a2912e886d4e8ff76622/geneticProject/picture_for_gui/cell.png -------------------------------------------------------------------------------- /geneticProject/picture_for_gui/flag.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Genetic-Algorithm/4bfb71e39a87e1600623a2912e886d4e8ff76622/geneticProject/picture_for_gui/flag.jpg -------------------------------------------------------------------------------- /geneticProject/picture_for_gui/ghost.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Genetic-Algorithm/4bfb71e39a87e1600623a2912e886d4e8ff76622/geneticProject/picture_for_gui/ghost.jpg -------------------------------------------------------------------------------- /geneticProject/picture_for_gui/goomba.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Genetic-Algorithm/4bfb71e39a87e1600623a2912e886d4e8ff76622/geneticProject/picture_for_gui/goomba.jpg -------------------------------------------------------------------------------- /geneticProject/picture_for_gui/mushrooms.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Genetic-Algorithm/4bfb71e39a87e1600623a2912e886d4e8ff76622/geneticProject/picture_for_gui/mushrooms.jpg -------------------------------------------------------------------------------- /geneticProject/picture_for_gui/superMario1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Genetic-Algorithm/4bfb71e39a87e1600623a2912e886d4e8ff76622/geneticProject/picture_for_gui/superMario1.png -------------------------------------------------------------------------------- /geneticProject/picture_for_gui/superMario2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Genetic-Algorithm/4bfb71e39a87e1600623a2912e886d4e8ff76622/geneticProject/picture_for_gui/superMario2.png -------------------------------------------------------------------------------- /sample run l9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Genetic-Algorithm/4bfb71e39a87e1600623a2912e886d4e8ff76622/sample run l9.jpg -------------------------------------------------------------------------------- /sample_run_level8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Genetic-Algorithm/4bfb71e39a87e1600623a2912e886d4e8ff76622/sample_run_level8.gif --------------------------------------------------------------------------------