Advertisement
Guest User

Untitled

a guest
Feb 23rd, 2019
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 19.48 KB | None | 0 0
  1. from random import randint
  2. from copy import deepcopy
  3. '''
  4. 0..7 - движение (завершающее действие)
  5. 8..15 - схватить еду или преобразовать яд в еду (завершающее действие)
  6. 16..23 - посмотреть
  7.  
  8.    переход в зависимости от того, что было в направлении действия:
  9.    на 1 - яд
  10.    на 2 - стена
  11.    на 3 - бот
  12.    на 4 - еда
  13.    на 5 - пусто
  14.  
  15. 24..31 - поворот
  16. 32..63 - безусловный переход
  17. '''
  18.  
  19. def get_random_coordinates():
  20.     return randint(0, 7), randint(0, 7)
  21.  
  22. class Bot():
  23.     # создаём множества
  24.     GO = {i for i in range(7)} #движение (завершающее действие)
  25.     SEIZE = {i for i in range(8, 15)} #схватить еду или преобразовать яд в еду (завершающее действие)
  26.     LOOK = {i for i in range(16, 23)} #посмотреть
  27.     TURN = {i for i in range(24, 31)} #поворот
  28.  
  29.     def __init__(self, x=None, y=None):
  30.         self.view = randint(0, 3)  # зрение бота: 0 - вверх, 1 - вправо, 2 - вниз, 3 - влево
  31.         self.health = 30  # здоровье бота
  32.         '''
  33.        0 -- 63
  34.        !
  35.        !
  36.        !        
  37.        '''
  38.         self.memory = [randint(0,63) for i in range(64)]  # мозг бота
  39.         self.pointer = 0  # указатель на ячейку памяти в мозгу
  40.         self.x = x #координата x бота
  41.         self.y = y #координата y бота
  42.  
  43.     def __str__(self):
  44.         return str(self.x) + ' ' + str(self.y)
  45.  
  46.     def change_pointer(self, value): #движение указателя в мозгу
  47.         self.pointer += value
  48.         if self.pointer > 63:
  49.             self.pointer %= 64
  50.  
  51.     def change_coordinates(self, x, y): #меняет координаты
  52.         self.x = x
  53.         self.y = y
  54.  
  55.     def change_health(self, value): #меняет здоровье
  56.         self.health += value
  57.  
  58.  
  59.     #координаты в зависимости от запроса, взгляда и положения бота
  60.     #value -- memory[pointer]
  61.     def look(self, value, view, x, y):
  62.         value += view * 2
  63.         if value > 7:
  64.             value %= 8
  65.  
  66.         if value == 0:
  67.             y += 1
  68.         elif value == 1:
  69.             x += 1
  70.             y += 1
  71.         elif value == 2:
  72.             x += 1
  73.         elif value == 3:
  74.             x += 1
  75.             y -= 1
  76.         elif value == 4:
  77.             y -= 1
  78.         elif value == 5:
  79.             x -= 1
  80.             y -= 1
  81.         elif value == 6:
  82.             x -= 1
  83.         else:
  84.             x -= 1
  85.             y += 1
  86.         return x, y
  87.  
  88.     #в зависимости от значения ячейки двигает указатель
  89.     #value -- значение ячейки
  90.     def move_pointer(self, value):
  91.         # яд
  92.         if value == 3:
  93.             self.change_pointer(1)
  94.         # стена
  95.         elif value == 4:
  96.             self.change_pointer(2)
  97.         # бот
  98.         elif value == 1:
  99.             self.change_pointer(3)
  100.         # еда
  101.         elif value == 2:
  102.             self.change_pointer(4)
  103.         # пусто
  104.         else:
  105.             self.change_pointer(5)
  106.  
  107.     #bot_number -- номер бота в массиве bots
  108.     def start(self, arena, bot_number):
  109.         flag_finish = False #флаг -- завершать ход бота или нет, изначально False -- не завершать ход
  110.         #пока флаг не станет True
  111.         while not flag_finish:
  112.             # если клетка памяти бота -- это "ходить"
  113.             if self.memory[self.pointer] in self.GO:
  114.                 #x1, y1 -- координаты, на которые надо сходить
  115.                 x1, y1 = self.look(self.memory[self.pointer], self.view,self.x, self.y)
  116.                 #если новые координаты находятся на арене
  117.                 if x1 >= 0 and y1 >= 0 and x1 <= 7 and y1 <= 7:
  118.                     # если на координаты, куда нам нужно сходить пустота -- то ходим
  119.                     if arena.check_coordinates(x1, y1) == '0':
  120.                         #меняем координаты у ячейки в арене
  121.                         arena.move_bot(self.x, self.y, x1, y1, bot_number)
  122.                         # меняем координаты в самом боте
  123.                         self.change_coordinates(x1, y1)
  124.                     #если еда -- то ходим и пополняем здоровье
  125.                     elif arena.check_coordinates(x1, y1) == '2':
  126.                         # меняем координаты у ячейки в арене
  127.                         arena.move_bot(self.x, self.y, x1, y1, bot_number)
  128.                         # меняем координаты в самом боте
  129.                         self.change_coordinates(x1, y1)
  130.                         #увеличиваем здоровье
  131.                         self.change_health(10)
  132.                     # если яд -- то ходим и убавляем здоровье бота
  133.                     elif arena.check_coordinates(x1, y1) == '3':
  134.                         # меняем координаты у ячейки в арене
  135.                         arena.move_bot(self.x, self.y, x1, y1, bot_number)
  136.                         # меняем координаты в самом боте
  137.                         self.change_coordinates(x1, y1)
  138.                         #убиваем бота
  139.                         self.change_health(-15)
  140.                     #если бот или стена, то не ходим
  141.  
  142.                     # перемещаем указатель в голове у бота
  143.                     #int(arena.check_coordinates(x1, y1)) -- проверяем, что находится в этой ячейке
  144.                     self.move_pointer(int(arena.check_coordinates(x1, y1)))
  145.  
  146.                     flag_finish = True #так как перемещение бота -- завершающее действие
  147.             # если клетка памяти бота -- это "схватить еду или преобразовать яд в еду"
  148.             elif self.memory[self.pointer] in self.SEIZE:
  149.                 # x1, y1 -- координаты, на которые надо посмотреть и найти еду или яд
  150.                 x1, y1 = self.look(self.memory[self.pointer], self.view, self.x, self.y)
  151.                 # если новые координаты находятся на арене
  152.                 if x1 >= 0 and y1 >= 0 and x1 <= 7 and y1 <= 7:
  153.                     # если еда -- то кушаем её
  154.                     if arena.check_coordinates(x1, y1) == '2':
  155.                         # меняем значение у ячейки в арене
  156.                         arena.delete_food(x1, y1)
  157.                         # увеличиваем здоровье бота
  158.                         self.change_health(10)
  159.                     elif arena.check_coordinates(x1, y1) == '3':
  160.                         # меняем значение у ячейки в арене
  161.                         arena.poison_to_food(x1, y1)
  162.                     #если пустота, бот или стена, то не ходим
  163.  
  164.                     # перемещаем указатель в голове у бота
  165.                     # int(arena.check_coordinates(x1, y1)) -- проверяем, что находится в этой ячейке
  166.                     self.move_pointer(int(arena.check_coordinates(x1, y1)))
  167.  
  168.                     flag_finish = True  # так как -- завершающее действие
  169.             # если клетка памяти бота -- это "смотреть"
  170.             elif self.memory[self.pointer] in self.LOOK:
  171.                 # x1, y1 -- координаты, на которые надо посмотреть
  172.                 x1, y1 = self.look(self.memory[self.pointer], self.view, self.x, self.y)
  173.                 # если новые координаты находятся на арене
  174.                 if x1 >= 0 and y1 >= 0 and x1 <= 7 and y1 <= 7:
  175.                     # перемещаем указатель в голове у бота
  176.                     # int(arena.check_coordinates(x1, y1)) -- проверяем, что находится в этой ячейке
  177.                     self.move_pointer(int(arena.check_coordinates(x1, y1)))
  178.             # если клетка памяти бота -- это "повернуть"
  179.             elif self.memory[self.pointer] in self.TURN:
  180.                 #обозначим значение в памяти, на которое указывает poiter за value
  181.                 value = self.memory[self.pointer]
  182.                 #меняем взгляд бота в зависимости от значения
  183.                 if value in (24,25):
  184.                     self.view += 1
  185.                 elif value in (26, 27):
  186.                     self.view += 2
  187.                 elif value in (28, 29):
  188.                     self.view += 3
  189.                 else:
  190.                     self.view += 4
  191.                 # перемещаем указатель в голове у бота
  192.                 self.change_pointer(1)
  193.             # если клетка памяти бота -- это "безусловный переход"
  194.             else:
  195.                 #перемещаем pointer на значение, которое было в памяти у бота
  196.                 self.change_pointer(self.memory[self.pointer])
  197.  
  198.             #после каждого хода уменьшаем здоровье бота на 1 еденицу
  199.             self.health -= 1
  200.             #если здоровье бота меньше 1, то убиваем его
  201.             if self.health < 1:
  202.                 flag_finish = True
  203.                 arena.delete_bot(bot_number)
  204.  
  205.     #мутирование бота, n -- количество мутаций, которое надо произвести
  206.     def mutate_bot(self, n=1):
  207.         #значение ячейки памяти от рандомного числа от 0 до 63 меняем на рандомное число от 0 до 63 n раз
  208.         for i in range(n):
  209.             self.memory[randint(0,63)] = randint(0,63)
  210.  
  211.  
  212.  
  213.  
  214.  
  215. class Cell():
  216.     def __init__(self, value=0, index=None):
  217.         self.value = value #значение ячейки: 0 - пусто, 1 - бот, 2 - еда, 3 - яд, 4 - стена
  218.         if self.value == 1:
  219.             self.index = index #index -- номер бота в ячейки
  220.  
  221.     def __str__(self):
  222.         return str(self.value)
  223.  
  224.     def change_value(self, value):
  225.         self.value = value
  226.  
  227.     def change_index(self, index):
  228.         self.index = index
  229.  
  230. class Arena():
  231.     def __init__(self, length=8, height=8, count_of_bots=16, end_count=8):
  232.         self.count_of_bots = count_of_bots
  233.         self.end_count = end_count
  234.         self.length = length #по координате x
  235.         self.height = height #по координате y
  236.         # доска, на которой происходит всё действие
  237.         self.board = [[Cell() for i in range(self.height)] for j in range(self.length)]
  238.         #массив ботов
  239.         self.bots = [Bot() for i in range(self.count_of_bots)]
  240.  
  241.     def __str__(self):
  242.         a = '['
  243.         for i in range(self.length):
  244.             a += '['
  245.             for j in range(self.height):
  246.                 a += str(self.board[i][j])
  247.                 if j != self.height-1:
  248.                     a += ', '
  249.             if i != self.length-1:
  250.                 a += '],'
  251.             else:
  252.                 a += ']'
  253.         a += ']'
  254.         return a
  255.  
  256.     # добавляем на арену стены, count -- количество объектов (нет проверки значение count), name -- что за объект
  257.     def add_obj(self, count, name):
  258.         if name == "wall":
  259.             name_value = 4
  260.         elif name == "food":
  261.             name_value = 2
  262.         elif name == "poison":
  263.             name_value = 3
  264.         else:
  265.             name_value = 0
  266.  
  267.         i = 0
  268.         while i < count:
  269.             # две рандомных координаты
  270.             x, y = get_random_coordinates()
  271.             # если в этой ячейки пустота -- то изменяем значение этой ячеки на стену
  272.             if str(self.board[x][y]) == '0':
  273.                 self.board[x][y].change_value(name_value)
  274.                 i += 1
  275.  
  276.     #закидывает на арену ботов
  277.     def make_bots(self):
  278.         i = 0
  279.         while i < self.count_of_bots:
  280.             # две рандомных координаты
  281.             x, y = get_random_coordinates()
  282.  
  283.             # если в этой ячейки пустота -- то изменяем значение этой ячеки на бота
  284.             if str(self.board[x][y]) == '0':
  285.                 #меняем координаты у i-ого бота в списке bots
  286.                 self.bots[i].change_coordinates(x,y)
  287.  
  288.                 #изменяет значение ячейки на '1'(бот)
  289.                 self.board[x][y].change_value(1)
  290.  
  291.                 #изменяет значение индекса ячейки на номер бота в списке
  292.                 self.board[x][y].change_index(i)
  293.                 i += 1
  294.  
  295.     #возвращает '0' -- если в координатах пусто, '1' -- бот, '2' -- еда, '3' -- яд, '4' -- стена
  296.     def check_coordinates(self, x, y):
  297.         return str(self.board[x][y])
  298.  
  299.     #x, y -- старые координаты бота, x1,y1 -- новые координаты бота, bot_number -- номер бота в списке bots
  300.     def move_bot(self, x, y, x1, y1, bot_number):
  301.         #меняем значение первой ячейки на 0
  302.         self.board[x][y].change_value(0)
  303.         #меняем индекс первой ячейки на None
  304.         self.board[x][y].change_index(None)
  305.         #меняем значение второй ячейки на 1
  306.         self.board[x1][y1].change_value(1)
  307.         #меняем индекс второй ячейки на номер бота в массиве bots
  308.         self.board[x1][y1].change_index(bot_number)
  309.  
  310.     def delete_food(self, x, y):
  311.         # меняем значение ячейки с едой на 0
  312.         self.board[x][y].change_value(0)
  313.  
  314.     def poison_to_food(self, x, y):
  315.         # меняем значение ячейки с ядом на 2
  316.         self.board[x][y].change_value(2)
  317.  
  318.     # удаляет бота из массива ботов и изменяет значение и индекс клетки, на которой стоял бот
  319.     def delete_bot(self, bot_number):
  320.         #меняем значение клетки, где стоял бот на 0
  321.         self.board[self.bots[bot_number].x][self.bots[bot_number].y].change_value(0)
  322.         #меняем индекс клетки, где стоял бот на None
  323.         self.board[self.bots[bot_number].x][self.bots[bot_number].y].change_index(None)
  324.         #удаляем бота из масиива
  325.         del self.bots[bot_number]
  326.  
  327.     #генерирует на арене яд и еду
  328.     def spawn_obj(self, obj, kol):
  329.         if obj == "food":
  330.             obj = 2
  331.         elif obj == "poison":
  332.             obj = 3
  333.         else:
  334.             obj = 0
  335.         i = 0
  336.         #пока не заполним нужное количество ячеек
  337.         while i < kol:
  338.             # две рандомных координаты
  339.             x, y = get_random_coordinates()
  340.  
  341.             # если в этой ячейки пустота -- то изменяем значение этой ячеки на obj
  342.             if str(self.board[x][y]) == '0':
  343.                 # изменяет значение ячейки на obj
  344.                 self.board[x][y].change_value(obj)
  345.                 i += 1
  346.  
  347.     #копируем ботов до количества count_of_bots -- делаем
  348.     def copy_bots(self):
  349.         #i ходит от 0 до количество ботов - сколько ботов уже есть в списке и т.к. у нас есть ещё вложенный цикл
  350.         #делим на количество его операций
  351.         for i in range((self.count_of_bots-self.end_count) // self.end_count):
  352.             #проходим каждый раз по оставшимся ботам и делаем deepcopy каждого из них
  353.             for j in range(self.end_count):
  354.                 self.bots.append(deepcopy(self.bots[j]))
  355.  
  356.     #мутируем count_of_bots // end_count первых ботов, n -- сколько мутаций надо произвести
  357.     def mutate_bots(self, n=1):
  358.         #i принимает значения от 0 до count_of_bots // end_count
  359.         for i in range(self.count_of_bots // self.end_count):
  360.             #делаем мутацию у данного бота
  361.             self.bots[i].mutate_bot(n)
  362.  
  363.  
  364. arena = Arena() #создаём арену
  365. arena.add_obj(3, "wall") #добавляем на арену стены
  366. arena.add_obj(8, "food") #добавляем на арену еду
  367. arena.add_obj(8, "poison") #добавляем на арену яд
  368. arena.make_bots()
  369.  
  370.  
  371. #ввод числа посторений
  372. number_of_repeat = int(input("Input number of repeat:\n"))
  373. #делаем number_of_repeat операций
  374. for g in range(number_of_repeat):
  375.     #пока у нас на арене больше 8 ботов
  376.     while len(arena.bots) > arena.end_count:
  377.         bot_number = 0 #номер текущего бота
  378.         #пока номер текущего бота не дойдёт до конца масиива bots или ботов не останется 8
  379.         while bot_number < len(arena.bots) and len(arena.bots) > arena.end_count:
  380.             #запоминаем длинну массива bots
  381.             length = len(arena.bots)
  382.             #оправляем номер бота в функцию start -- делает несколько ходов бота до заверщающего дейтсвия
  383.             arena.bots[bot_number].start(arena, bot_number)
  384.             #проверяем длинну массива bots, если она не изменилась(данный бот не умер), то идём по массиву дальше
  385.             if length == len(arena.bots):
  386.                 bot_number += 1
  387.         #спавним на арене яд
  388.         arena.spawn_obj("poison", 3)
  389.         # спавним на арене еду
  390.         arena.spawn_obj("food", 3)
  391.     #копируем ботов до изначального количества
  392.     arena.copy_bots()
  393.     #делаем мутацию у ботов
  394.     arena.mutate_bots()
  395.     print(g)
  396. print(arena.bots[0].memory)
  397. #не проходит нужное количество итераций, останавливает примерно 1 - 2
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement