├── .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 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | 1622388230395
89 |
90 |
91 | 1622388230395
92 |
93 |
94 |
95 |
96 |
97 | 1622561880307
98 |
99 |
100 |
101 | 1622561880307
102 |
103 |
104 | 1622566701036
105 |
106 |
107 |
108 | 1622566701036
109 |
110 |
111 | 1622569000131
112 |
113 |
114 |
115 | 1622569000131
116 |
117 |
118 | 1622573039049
119 |
120 |
121 |
122 | 1622573039049
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
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 | 
25 |
26 |
27 | A sample run with GUI (Level 8):
28 |
29 |
30 | 
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 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/geneticProject/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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
--------------------------------------------------------------------------------