Sztuczna_inteligencja_gr_13/bin/main/main.py

600 lines
19 KiB
Python
Raw Normal View History

2021-04-24 03:05:17 +02:00
import os
import random
2021-04-29 18:07:47 +02:00
import time
2021-04-02 03:39:46 +02:00
from tkinter import *
2021-05-30 00:25:54 +02:00
import pandas as pd
2021-04-02 03:39:46 +02:00
from bin.Classess.Field import Field
from bin.Classess.Mine import Mine
2021-05-23 22:32:00 +02:00
from bin.Classess.Travel import Travel
from bin.Classess.Player import Player
import bin.Classess.Node as nd
2021-05-23 22:32:00 +02:00
import bin.Classess.Travel as tr
2021-04-30 23:52:55 +02:00
from resources.Globals import *
2021-05-30 00:25:54 +02:00
from bin.Classess.DecisionTree import DecisionTree
2021-04-30 23:52:55 +02:00
# WINDOW_X = 533 + 1200
# WINDOW_Y = 950
# FRAME_WIDTH = 533
# FRAME_HEIGHT = 533
#
# # Size of small image
# IMAGE_SIZE = 50
#
# AMOUNT_OF_MINES = 10
#
# DELAY_TIME = 0.5
2021-04-29 18:07:47 +02:00
2021-04-02 03:39:46 +02:00
# Creating objects
player = Player()
field = Field()
2021-05-23 22:32:00 +02:00
travel = Travel()
2021-05-30 00:25:54 +02:00
decision_tree = DecisionTree()
2021-04-29 16:28:43 +02:00
2021-05-30 00:25:54 +02:00
# Globals
2021-04-26 18:21:56 +02:00
fringe = []
explored = []
2021-04-29 16:28:43 +02:00
action_list = []
images_coord = []
2021-04-02 03:39:46 +02:00
2021-05-30 00:25:54 +02:00
label = None
2021-04-02 03:39:46 +02:00
2021-04-24 03:05:17 +02:00
def Arrow(direction):
image = ""
if direction == "north":
image = player.arrow_north_image
elif direction == "south":
image = player.arrow_south_image
elif direction == "west":
image = player.arrow_west_image
elif direction == "east":
image = player.arrow_east_image
2021-04-24 17:32:07 +02:00
field.small_field_canvas.itemconfig(player.image_canvas_id, image=image)
2021-04-24 03:05:17 +02:00
2021-04-02 03:39:46 +02:00
# Putting images
2021-04-24 17:32:07 +02:00
def Fill(bool):
global images_coord
2021-04-24 17:32:07 +02:00
if bool:
field.PuttingSmallImages()
2021-04-02 03:39:46 +02:00
2021-05-23 22:32:00 +02:00
travel.points_coord.append(field.small_field_canvas.coords(field.canvas_small_images[0]))
travel.points_coord.extend(field.mines_coord)
for i in range(0, len(travel.points_coord)):
travel.points_map[i + 1] = travel.points_coord[i]
2021-05-24 16:43:07 +02:00
print(travel.points_map)
2021-05-23 22:32:00 +02:00
for i in range(0, len(field.canvas_small_images)):
images_coord.append(field.small_field_canvas.coords(field.canvas_small_images[i]))
2021-05-23 22:32:00 +02:00
# print("Coords List: ", images_coord)
nd.init_data(images_coord, field.cell_expense)
2021-05-30 00:25:54 +02:00
# # Drawing red/green rectangles
# for el in field.state_of_cell_array:
# if el[0] != 0:
# field.small_field_canvas.create_rectangle(el[0], el[1], el[0] + player.step - 2,
# el[1] + player.step - 2, width=3, outline=el[2])
2021-04-02 03:39:46 +02:00
DrawingLargeImage()
def DrawingLargeImage():
large_img_name = field.large_image_array[player.current_array_y][player.current_array_x]
2021-04-02 04:08:50 +02:00
field.PuttingLargeImage(large_img_name)
2021-04-02 03:39:46 +02:00
2021-04-29 18:07:47 +02:00
def NextDirection(action):
2021-04-24 03:05:17 +02:00
# Define next direction
current_direction = player.direction
t = -1
for i in range(4):
if player.directions[i] == current_direction:
t = i
break
# Write next direction to Player
2021-04-29 18:07:47 +02:00
if action == "Right":
2021-04-24 03:05:17 +02:00
player.direction = player.directions[(t + 1) % 4]
2021-04-29 18:07:47 +02:00
elif action == "Left":
2021-04-24 03:05:17 +02:00
player.direction = player.directions[(t - 1) % 4]
return player.direction
2021-04-24 17:32:07 +02:00
def MovingForward():
if player.direction == "east" and field.small_field_canvas.coords(player.image_canvas_id)[0] + player.step < FRAME_WIDTH:
field.small_field_canvas.move(player.image_canvas_id, player.step, 0)
elif player.direction == "west" and field.small_field_canvas.coords(player.image_canvas_id)[0] > player.x_start:
field.small_field_canvas.move(player.image_canvas_id, -player.step, 0)
elif player.direction == "north" and field.small_field_canvas.coords(player.image_canvas_id)[1] > player.y_start:
field.small_field_canvas.move(player.image_canvas_id, 0, -player.step)
elif player.direction == "south" and field.small_field_canvas.coords(player.image_canvas_id)[1] + player.step < FRAME_HEIGHT:
field.small_field_canvas.move(player.image_canvas_id, 0, player.step)
2021-04-29 18:07:47 +02:00
def Moving(action):
2021-04-02 03:39:46 +02:00
# Moving
2021-04-29 18:07:47 +02:00
if action == "Right":
2021-04-24 03:05:17 +02:00
# player.MovingRight()
2021-04-02 04:08:50 +02:00
field.Moving()
2021-04-24 17:32:07 +02:00
Fill(False)
2021-04-29 18:07:47 +02:00
next_direction = NextDirection(action)
2021-04-24 03:05:17 +02:00
Arrow(next_direction)
2021-04-29 18:07:47 +02:00
elif action == "Left":
2021-04-24 03:05:17 +02:00
# player.MovingLeft()
2021-04-02 04:08:50 +02:00
field.Moving()
2021-04-24 17:32:07 +02:00
Fill(False)
2021-04-29 18:07:47 +02:00
next_direction = NextDirection(action)
2021-04-24 03:05:17 +02:00
Arrow(next_direction)
2021-04-29 18:07:47 +02:00
elif action == "Up":
2021-04-24 03:05:17 +02:00
player.Moving()
2021-04-02 04:08:50 +02:00
field.Moving()
2021-04-24 17:32:07 +02:00
Fill(False)
MovingForward()
2021-04-24 03:05:17 +02:00
Arrow(player.direction)
2021-04-02 03:39:46 +02:00
def ImagesInArray(directory, array):
# Filling array from directory
row = column = 0
for file in os.listdir(directory):
image_name = file
image_path = f"{directory}/{image_name}"
if directory == "../files/large_images":
image = PhotoImage(master=field.large_image_canvas, file=image_path)
else:
image = PhotoImage(master=field.small_field_canvas, file=image_path)
is_done = False
while not is_done:
if array[row][column] == 0:
array[row][column] = image
is_done = True
else:
column += 1
if column == 10:
column = 0
row += 1
2021-05-23 22:32:00 +02:00
if row == 10:
break
2021-04-02 03:39:46 +02:00
column += 1
if column == 10:
column = 0
row += 1
2021-05-23 22:32:00 +02:00
if row == 10:
break
2021-04-02 03:39:46 +02:00
def CellDesignation(array, color):
for element in array:
if element[0] == 0:
element[0] = player.current_x
element[1] = player.current_y
element[2] = color
break
2021-04-29 18:07:47 +02:00
def Action(action):
if action in ["Right", "Left", "Up", "space"]:
Moving(action)
2021-05-30 00:25:54 +02:00
# elif action in ["1", "2"]:
# if action == "1":
# CellDesignation(field.state_of_cell_array, "red")
# else:
# CellDesignation(field.state_of_cell_array, "green")
2021-04-02 03:39:46 +02:00
2021-04-24 17:32:07 +02:00
# Modified by Artem to search in the status area
2021-04-29 16:28:43 +02:00
def create_action_list(states, index):
global fringe
global action_list
if index == 0:
action_list.reverse()
return True
action_list.append(fringe[index].action)
state_parent = [fringe[index].parent[0], fringe[index].parent[1]]
2021-04-29 16:28:43 +02:00
create_action_list(states, states.index(state_parent))
2021-05-30 00:25:54 +02:00
def MakeDecision():
if player.current_array_x != 0 or player.current_array_y != 0:
mine = field.state_of_cell_array[player.current_array_y][player.current_array_x]
# print(field.state_of_cell_array)
# print(mine)
attributes_dict = {'known': [mine.known], 'power': [mine.power], 'new': [mine.new], 'location': [mine.location],
'stable': [mine.stable], 'chain_reaction': [mine.chain_reaction]}
attributes = f'{mine.known}; {mine.power}; {mine.new}; {mine.location}; {mine.stable}; {mine.chain_reaction}'
global label_text
label_text += attributes + '\n'
global label
label.config(text=label_text)
field.win.update()
data_frame = pd.DataFrame.from_dict(attributes_dict)
predict = decision_tree.classifier.predict(data_frame)
return predict
def MarkMine(prediction):
if prediction == 0:
DrawFlag(field.flag_green_img)
if prediction == 1:
DrawFlag(field.flag_yellow_img)
if prediction == 2:
DrawFlag(field.flag_red_img)
if prediction == 3:
DrawFlag(field.flag_bleu_img)
field.win.update()
2021-05-24 16:43:07 +02:00
def MouseClickEvent(track):
2021-04-26 18:21:56 +02:00
global fringe
2021-04-29 16:28:43 +02:00
global explored
global action_list
2021-05-24 16:43:07 +02:00
print("The best individual is: {} {}".format(track[1], track[0]))
for point in range(0, len(track[1]) + 1):
start_position = field.small_field_canvas.coords(player.image_canvas_id)
if point == len(track[1]):
end_position = travel.points_map[1]
else:
end_position = travel.points_map[track[1][point]]
2021-04-29 16:28:43 +02:00
2021-05-24 16:43:07 +02:00
node = nd.Node()
if len(fringe) == 0:
node.state.coord = start_position
node.state.direction = "east"
else:
states = []
for k in range(0, len(fringe)):
new_state = fringe[k].state.coord
states.append(new_state)
start_node = fringe[-1]
2021-05-24 16:43:07 +02:00
node.state.coord = start_node.state.coord
node.state.direction = start_node.state.direction
2021-04-29 16:28:43 +02:00
2021-05-24 16:43:07 +02:00
fringe.clear()
explored.clear()
action_list.clear()
fringe = nd.graph_search_A(fringe, explored, node.state, end_position)
2021-04-26 18:21:56 +02:00
states = []
2021-05-24 16:43:07 +02:00
goal_all = []
for i in range(0, len(fringe)):
new_state = [fringe[i].state.coord, fringe[i].state.direction]
states.append(new_state)
2021-05-24 16:43:07 +02:00
if end_position[0] == fringe[i].state.coord[0] and end_position[1] == fringe[i].state.coord[1]:
goal_all.append(fringe[i])
elem_min = goal_all[0]
for i in range(1, len(goal_all)):
if elem_min.priority > goal_all[i].priority:
elem_min = goal_all[i]
index = fringe.index(elem_min)
fringe = fringe[:index + 1]
create_action_list(states, -1)
# Start moving
AutoMove()
2021-05-30 00:25:54 +02:00
# Decision by tree
prediction = MakeDecision()
# Draw the right flag
MarkMine(prediction)
2021-05-24 16:43:07 +02:00
time.sleep(SLEEP_AFTER_CHECK_MINE)
2021-05-30 00:25:54 +02:00
# Check in which locations is mine
def CheckLocation(x, y):
# Add x + y like strings that create xy number
temp_x = str(x)
temp_y = str(y)
position_str = temp_x + temp_y
position = int(position_str)
color_number = -1
if field.cell_expense[position] == standard_cell_cost:
color_number = 0
elif field.cell_expense[position] == sand_cell_cost:
color_number = 1
elif field.cell_expense[position] == water_cell_cost:
color_number = 2
elif field.cell_expense[position] == swamp_cell_cost:
color_number = 3
return color_number
2021-04-24 17:32:07 +02:00
2021-05-30 00:25:54 +02:00
# Add mines on the field and to arrays
def PutMines(mines_array):
counter = 0
while counter < AMOUNT_OF_MINES:
x = random.randint(0, 9)
y = random.randint(0, 9)
is_equal = False
for mine in mines_array:
if mine.array_x == x and mine.array_y == y:
is_equal = True
if not is_equal:
2021-05-23 22:32:00 +02:00
if x == 0 and y == 0:
continue
else:
2021-05-30 00:25:54 +02:00
known = random.randint(0, 1)
power = random.randint(1, 10)
new = random.randint(0, 1)
location = CheckLocation(x, y)
stable = random.randint(0, 1)
mine = Mine(x, y, known, power, new, location, stable)
2021-05-23 22:32:00 +02:00
mines_array.append(mine)
2021-05-30 00:25:54 +02:00
# Add mine to array at the right position
field.state_of_cell_array[x][y] = mine
2021-05-23 22:32:00 +02:00
field.field_state_array[x][y] = True
2021-05-23 22:32:00 +02:00
counter += 1
2021-05-23 22:32:00 +02:00
def MinesInArrays(mines_array, directory, imgs_array, bool_mines_coord):
counter = 0
temp_array = []
if directory == "../../files/small_mines_images":
for file in os.listdir(directory):
if counter < AMOUNT_OF_MINES:
image_name = file
image_path = f"{directory}/{image_name}"
image = PhotoImage(master=field.small_field_canvas, file=image_path)
temp_array.append(image)
counter += 1
for i in range(AMOUNT_OF_MINES):
mines_array[i].small_img = temp_array[i]
# Add images in image array
imgs_array[mines_array[i].array_x][mines_array[i].array_y] = temp_array[i]
elif directory == "../../files/large_mines_images":
for file in os.listdir(directory):
if counter < AMOUNT_OF_MINES:
image_name = file
image_path = f"{directory}/{image_name}"
image = PhotoImage(master=field.large_image_canvas, file=image_path)
temp_array.append(image)
counter += 1
for i in range(AMOUNT_OF_MINES):
mines_array[i].large_img = temp_array[i]
# Add images in image array
imgs_array[mines_array[i].array_x][mines_array[i].array_y] = temp_array[i]
2021-05-23 22:32:00 +02:00
if bool_mines_coord:
for i in range(len(mines_array)):
field.mines_coord.append([mines_array[i].array_x, mines_array[i].array_y])
2021-05-30 00:25:54 +02:00
def DrawFlag(image):
field.small_field_canvas.create_image(player.current_x, player.current_y, anchor=NW, image=image)
2021-05-23 22:32:00 +02:00
2021-05-24 16:43:07 +02:00
# def IsItMine():
# visited = 0 # 0 - not mine; 1 - on this mine for the first time; 2 - already been on this mine
#
# # Checks if the player is on the mine
# for i in field.mines_coord:
# if i[0] == player.current_x and i[1] == player.current_y:
# visited = 1
# # Checks if the player has already been on this mine
# for y in field.visited_mines:
# if y[0] == player.current_x and y[1] == player.current_y:
# visited = 2
# if visited == 1:
# DrawFlag()
2021-05-23 22:32:00 +02:00
2021-04-29 18:07:47 +02:00
def AutoMove():
for action in action_list:
# Program wait for better illustration
time.sleep(DELAY_TIME)
# Move once
Action(action)
2021-05-23 22:32:00 +02:00
# Check if player on mine and if yes, draw flag
2021-05-24 16:43:07 +02:00
# IsItMine()
2021-04-29 18:07:47 +02:00
# Update main window
field.win.update()
2021-04-30 23:52:55 +02:00
# Draws rectangles that indicate type of cells
def DrawRectangle():
2021-05-01 01:24:35 +02:00
x = 4
y = 4
2021-04-30 23:52:55 +02:00
color = None
# Chose color for rectangle
for i in range(len(field.cell_expense)):
2021-05-24 16:43:07 +02:00
if field.cell_expense[i] == standard_cell_cost:
2021-04-30 23:52:55 +02:00
color = "None"
2021-05-24 16:43:07 +02:00
elif field.cell_expense[i] == sand_cell_cost:
2021-04-30 23:52:55 +02:00
color = "yellow"
2021-05-24 16:43:07 +02:00
elif field.cell_expense[i] == water_cell_cost:
color = "dodger blue"
2021-05-24 16:43:07 +02:00
elif field.cell_expense[i] == swamp_cell_cost:
2021-04-30 23:52:55 +02:00
color = "green4"
if color != "None":
2021-05-30 00:25:54 +02:00
field.small_field_canvas.create_rectangle(x, y, x + IMAGE_SIZE + 2, y + IMAGE_SIZE + 2, width=2,
outline=color)
2021-04-30 23:52:55 +02:00
x += player.step
if x + IMAGE_SIZE + 2 > field.width:
2021-05-01 01:24:35 +02:00
x = 4
2021-04-30 23:52:55 +02:00
y += player.step
def AddCostCellsToArray(amount, cost):
counter = 0
while counter < amount:
r = random.randint(0, 99)
if field.cell_expense[r] == 0:
field.cell_expense[r] = cost
counter += 1
def CostingOfCells():
AddCostCellsToArray(amount_of_sand_cells, sand_cell_cost)
AddCostCellsToArray(amount_of_water_cells, water_cell_cost)
AddCostCellsToArray(amount_of_swamp_cells, swamp_cell_cost)
2021-05-30 00:25:54 +02:00
AddCostCellsToArray(
field.rows * field.columns - (amount_of_sand_cells + amount_of_water_cells + amount_of_swamp_cells),
standard_cell_cost)
2021-04-30 23:52:55 +02:00
# Draw rectangles
DrawRectangle()
2021-05-23 22:32:00 +02:00
def click_button():
btn.destroy()
2021-05-30 00:25:54 +02:00
global label
label = Label(field.win, text="Wait...\nAI conquers the world...", fg='black', font="20", bg='gray')
label.place(x=10, y=560)
2021-05-24 16:43:07 +02:00
field.win.update()
track = tr.genetic_algorithm(travel.points_map)
track[1].remove(1)
label.config(text=track[1])
field.win.update()
MouseClickEvent(track)
2021-05-23 22:32:00 +02:00
2021-05-30 00:25:54 +02:00
# Check if there mines near and if, mark it
def CheckForMinesNear(x, y):
if x > 0:
if field.state_of_cell_array[x - 1][y] != "None":
# Mark by chain reaction current mine
field.state_of_cell_array[x][y].chain_reaction = 1
# Mark by chain reaction mine that near
field.state_of_cell_array[x - 1][y].chain_reaction = 1
if x < 9:
if field.state_of_cell_array[x + 1][y] != "None":
# Mark by chain reaction current mine
field.state_of_cell_array[x][y].chain_reaction = 1
# Mark by chain reaction mine that near
field.state_of_cell_array[x + 1][y].chain_reaction = 1
if y > 0:
if field.state_of_cell_array[x][y - 1] != "None":
# Mark by chain reaction current mine
field.state_of_cell_array[x][y].chain_reaction = 1
# Mark by chain reaction mine that near
field.state_of_cell_array[x][y - 1].chain_reaction = 1
if y < 9:
if field.state_of_cell_array[x][y + 1] != "None":
# Mark by chain reaction current mine
field.state_of_cell_array[x][y].chain_reaction = 1
# Mark by chain reaction mine that near
field.state_of_cell_array[x][y + 1].chain_reaction = 1
def CheckForChainReaction():
for x in range(field.columns):
for y in range(field.rows):
if field.state_of_cell_array[x][y] != "None":
CheckForMinesNear(x, y)
2021-04-02 03:39:46 +02:00
def main():
# Creating the main window of an application
win_size = f'{WINDOW_X}x{WINDOW_Y}'
field.win.title("Sapper")
field.win.configure(bg='gray')
field.win.geometry(win_size)
2021-05-23 22:32:00 +02:00
print(f'Amount of mines: {AMOUNT_OF_MINES}')
2021-05-30 00:25:54 +02:00
2021-05-23 22:32:00 +02:00
global btn
btn = Button(field.win,
text="Search for mines", # текст кнопки
background="#555", # фоновый цвет кнопки
foreground="#ccc", # цвет текста
padx="20", # отступ от границ до содержимого по горизонтали
pady="8", # отступ от границ до содержимого по вертикали
2021-05-24 16:43:07 +02:00
font="24", # высота шрифта
2021-05-23 22:32:00 +02:00
command=click_button
)
2021-05-30 00:25:54 +02:00
btn.place(x=10, y=560)
2021-04-02 03:39:46 +02:00
# Create array with mines objects
mines_array = []
2021-05-30 00:25:54 +02:00
CostingOfCells()
# Put mines on coordinates
PutMines(mines_array)
2021-05-30 00:25:54 +02:00
CheckForChainReaction()
# Add images of mines in arrays
2021-05-23 22:32:00 +02:00
MinesInArrays(mines_array, "../../files/small_mines_images", field.small_image_array, True)
MinesInArrays(mines_array, "../../files/large_mines_images", field.large_image_array, False)
2021-04-02 03:39:46 +02:00
# Filling image arrays
small_directory = "../../files/small_images"
ImagesInArray(small_directory, field.small_image_array)
large_directory = "../../files/large_images"
ImagesInArray(large_directory, field.large_image_array)
2021-04-02 03:39:46 +02:00
2021-04-24 03:05:17 +02:00
# Add arrow image to Player class
images = []
for file in os.listdir("../../files/arrow"):
path = f"../../files/arrow/{file}"
img = PhotoImage(master=field.small_field_canvas, file=path)
images.append(img)
player.arrow_east_image = images[0]
player.arrow_north_image = images[1]
player.arrow_south_image = images[2]
player.arrow_west_image = images[3]
2021-04-02 03:39:46 +02:00
# Filling window with images
2021-04-24 17:32:07 +02:00
Fill(True)
2021-04-24 03:05:17 +02:00
# Drawing arrow (player)
2021-04-24 17:32:07 +02:00
image = player.arrow_east_image
player.image_canvas_id = field.small_field_canvas.create_image(player.current_x, player.current_y, anchor=NW,
image=image)
# Arrow(player.direction)
# Rectangle(True, "None")
2021-04-24 03:05:17 +02:00
# Rectangle()
2021-04-02 03:39:46 +02:00
# Binding keyboard press to function
2021-04-29 18:07:47 +02:00
# field.win.bind("<Key>", Action)
2021-05-24 16:43:07 +02:00
# field.small_field_canvas.bind("<Button-1>", MouseClickEvent)
2021-05-30 00:25:54 +02:00
2021-04-02 03:39:46 +02:00
# Starting mainloop for window
field.win.mainloop()
if __name__ == '__main__':
main()