Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from random import randint
- from copy import deepcopy
- '''
- 0..7 - движение (завершающее действие)
- 8..15 - схватить еду или преобразовать яд в еду (завершающее действие)
- 16..23 - посмотреть
- переход в зависимости от того, что было в направлении действия:
- на 1 - яд
- на 2 - стена
- на 3 - бот
- на 4 - еда
- на 5 - пусто
- 24..31 - поворот
- 32..63 - безусловный переход
- '''
- def get_random_coordinates():
- return randint(0, 7), randint(0, 7)
- class Bot():
- # создаём множества
- GO = {i for i in range(7)} #движение (завершающее действие)
- SEIZE = {i for i in range(8, 15)} #схватить еду или преобразовать яд в еду (завершающее действие)
- LOOK = {i for i in range(16, 23)} #посмотреть
- TURN = {i for i in range(24, 31)} #поворот
- def __init__(self, x=None, y=None):
- self.view = randint(0, 3) # зрение бота: 0 - вверх, 1 - вправо, 2 - вниз, 3 - влево
- self.health = 30 # здоровье бота
- '''
- 0 -- 63
- !
- !
- !
- '''
- self.memory = [randint(0,63) for i in range(64)] # мозг бота
- self.pointer = 0 # указатель на ячейку памяти в мозгу
- self.x = x #координата x бота
- self.y = y #координата y бота
- def __str__(self):
- return str(self.x) + ' ' + str(self.y)
- def change_pointer(self, value): #движение указателя в мозгу
- self.pointer += value
- if self.pointer > 63:
- self.pointer %= 64
- def change_coordinates(self, x, y): #меняет координаты
- self.x = x
- self.y = y
- def change_health(self, value): #меняет здоровье
- self.health += value
- #координаты в зависимости от запроса, взгляда и положения бота
- #value -- memory[pointer]
- def look(self, value, view, x, y):
- value += view * 2
- if value > 7:
- value %= 8
- if value == 0:
- y += 1
- elif value == 1:
- x += 1
- y += 1
- elif value == 2:
- x += 1
- elif value == 3:
- x += 1
- y -= 1
- elif value == 4:
- y -= 1
- elif value == 5:
- x -= 1
- y -= 1
- elif value == 6:
- x -= 1
- else:
- x -= 1
- y += 1
- return x, y
- #в зависимости от значения ячейки двигает указатель
- #value -- значение ячейки
- def move_pointer(self, value):
- # яд
- if value == 3:
- self.change_pointer(1)
- # стена
- elif value == 4:
- self.change_pointer(2)
- # бот
- elif value == 1:
- self.change_pointer(3)
- # еда
- elif value == 2:
- self.change_pointer(4)
- # пусто
- else:
- self.change_pointer(5)
- #bot_number -- номер бота в массиве bots
- def start(self, arena, bot_number):
- flag_finish = False #флаг -- завершать ход бота или нет, изначально False -- не завершать ход
- #пока флаг не станет True
- while not flag_finish:
- # если клетка памяти бота -- это "ходить"
- if self.memory[self.pointer] in self.GO:
- #x1, y1 -- координаты, на которые надо сходить
- x1, y1 = self.look(self.memory[self.pointer], self.view,self.x, self.y)
- #если новые координаты находятся на арене
- if x1 >= 0 and y1 >= 0 and x1 <= 7 and y1 <= 7:
- # если на координаты, куда нам нужно сходить пустота -- то ходим
- if arena.check_coordinates(x1, y1) == '0':
- #меняем координаты у ячейки в арене
- arena.move_bot(self.x, self.y, x1, y1, bot_number)
- # меняем координаты в самом боте
- self.change_coordinates(x1, y1)
- #если еда -- то ходим и пополняем здоровье
- elif arena.check_coordinates(x1, y1) == '2':
- # меняем координаты у ячейки в арене
- arena.move_bot(self.x, self.y, x1, y1, bot_number)
- # меняем координаты в самом боте
- self.change_coordinates(x1, y1)
- #увеличиваем здоровье
- self.change_health(10)
- # если яд -- то ходим и убавляем здоровье бота
- elif arena.check_coordinates(x1, y1) == '3':
- # меняем координаты у ячейки в арене
- arena.move_bot(self.x, self.y, x1, y1, bot_number)
- # меняем координаты в самом боте
- self.change_coordinates(x1, y1)
- #убиваем бота
- self.change_health(-15)
- #если бот или стена, то не ходим
- # перемещаем указатель в голове у бота
- #int(arena.check_coordinates(x1, y1)) -- проверяем, что находится в этой ячейке
- self.move_pointer(int(arena.check_coordinates(x1, y1)))
- flag_finish = True #так как перемещение бота -- завершающее действие
- # если клетка памяти бота -- это "схватить еду или преобразовать яд в еду"
- elif self.memory[self.pointer] in self.SEIZE:
- # x1, y1 -- координаты, на которые надо посмотреть и найти еду или яд
- x1, y1 = self.look(self.memory[self.pointer], self.view, self.x, self.y)
- # если новые координаты находятся на арене
- if x1 >= 0 and y1 >= 0 and x1 <= 7 and y1 <= 7:
- # если еда -- то кушаем её
- if arena.check_coordinates(x1, y1) == '2':
- # меняем значение у ячейки в арене
- arena.delete_food(x1, y1)
- # увеличиваем здоровье бота
- self.change_health(10)
- elif arena.check_coordinates(x1, y1) == '3':
- # меняем значение у ячейки в арене
- arena.poison_to_food(x1, y1)
- #если пустота, бот или стена, то не ходим
- # перемещаем указатель в голове у бота
- # int(arena.check_coordinates(x1, y1)) -- проверяем, что находится в этой ячейке
- self.move_pointer(int(arena.check_coordinates(x1, y1)))
- flag_finish = True # так как -- завершающее действие
- # если клетка памяти бота -- это "смотреть"
- elif self.memory[self.pointer] in self.LOOK:
- # x1, y1 -- координаты, на которые надо посмотреть
- x1, y1 = self.look(self.memory[self.pointer], self.view, self.x, self.y)
- # если новые координаты находятся на арене
- if x1 >= 0 and y1 >= 0 and x1 <= 7 and y1 <= 7:
- # перемещаем указатель в голове у бота
- # int(arena.check_coordinates(x1, y1)) -- проверяем, что находится в этой ячейке
- self.move_pointer(int(arena.check_coordinates(x1, y1)))
- # если клетка памяти бота -- это "повернуть"
- elif self.memory[self.pointer] in self.TURN:
- #обозначим значение в памяти, на которое указывает poiter за value
- value = self.memory[self.pointer]
- #меняем взгляд бота в зависимости от значения
- if value in (24,25):
- self.view += 1
- elif value in (26, 27):
- self.view += 2
- elif value in (28, 29):
- self.view += 3
- else:
- self.view += 4
- # перемещаем указатель в голове у бота
- self.change_pointer(1)
- # если клетка памяти бота -- это "безусловный переход"
- else:
- #перемещаем pointer на значение, которое было в памяти у бота
- self.change_pointer(self.memory[self.pointer])
- #после каждого хода уменьшаем здоровье бота на 1 еденицу
- self.health -= 1
- #если здоровье бота меньше 1, то убиваем его
- if self.health < 1:
- flag_finish = True
- arena.delete_bot(bot_number)
- #мутирование бота, n -- количество мутаций, которое надо произвести
- def mutate_bot(self, n=1):
- #значение ячейки памяти от рандомного числа от 0 до 63 меняем на рандомное число от 0 до 63 n раз
- for i in range(n):
- self.memory[randint(0,63)] = randint(0,63)
- class Cell():
- def __init__(self, value=0, index=None):
- self.value = value #значение ячейки: 0 - пусто, 1 - бот, 2 - еда, 3 - яд, 4 - стена
- if self.value == 1:
- self.index = index #index -- номер бота в ячейки
- def __str__(self):
- return str(self.value)
- def change_value(self, value):
- self.value = value
- def change_index(self, index):
- self.index = index
- class Arena():
- def __init__(self, length=8, height=8, count_of_bots=16, end_count=8):
- self.count_of_bots = count_of_bots
- self.end_count = end_count
- self.length = length #по координате x
- self.height = height #по координате y
- # доска, на которой происходит всё действие
- self.board = [[Cell() for i in range(self.height)] for j in range(self.length)]
- #массив ботов
- self.bots = [Bot() for i in range(self.count_of_bots)]
- def __str__(self):
- a = '['
- for i in range(self.length):
- a += '['
- for j in range(self.height):
- a += str(self.board[i][j])
- if j != self.height-1:
- a += ', '
- if i != self.length-1:
- a += '],'
- else:
- a += ']'
- a += ']'
- return a
- # добавляем на арену стены, count -- количество объектов (нет проверки значение count), name -- что за объект
- def add_obj(self, count, name):
- if name == "wall":
- name_value = 4
- elif name == "food":
- name_value = 2
- elif name == "poison":
- name_value = 3
- else:
- name_value = 0
- i = 0
- while i < count:
- # две рандомных координаты
- x, y = get_random_coordinates()
- # если в этой ячейки пустота -- то изменяем значение этой ячеки на стену
- if str(self.board[x][y]) == '0':
- self.board[x][y].change_value(name_value)
- i += 1
- #закидывает на арену ботов
- def make_bots(self):
- i = 0
- while i < self.count_of_bots:
- # две рандомных координаты
- x, y = get_random_coordinates()
- # если в этой ячейки пустота -- то изменяем значение этой ячеки на бота
- if str(self.board[x][y]) == '0':
- #меняем координаты у i-ого бота в списке bots
- self.bots[i].change_coordinates(x,y)
- #изменяет значение ячейки на '1'(бот)
- self.board[x][y].change_value(1)
- #изменяет значение индекса ячейки на номер бота в списке
- self.board[x][y].change_index(i)
- i += 1
- #возвращает '0' -- если в координатах пусто, '1' -- бот, '2' -- еда, '3' -- яд, '4' -- стена
- def check_coordinates(self, x, y):
- return str(self.board[x][y])
- #x, y -- старые координаты бота, x1,y1 -- новые координаты бота, bot_number -- номер бота в списке bots
- def move_bot(self, x, y, x1, y1, bot_number):
- #меняем значение первой ячейки на 0
- self.board[x][y].change_value(0)
- #меняем индекс первой ячейки на None
- self.board[x][y].change_index(None)
- #меняем значение второй ячейки на 1
- self.board[x1][y1].change_value(1)
- #меняем индекс второй ячейки на номер бота в массиве bots
- self.board[x1][y1].change_index(bot_number)
- def delete_food(self, x, y):
- # меняем значение ячейки с едой на 0
- self.board[x][y].change_value(0)
- def poison_to_food(self, x, y):
- # меняем значение ячейки с ядом на 2
- self.board[x][y].change_value(2)
- # удаляет бота из массива ботов и изменяет значение и индекс клетки, на которой стоял бот
- def delete_bot(self, bot_number):
- #меняем значение клетки, где стоял бот на 0
- self.board[self.bots[bot_number].x][self.bots[bot_number].y].change_value(0)
- #меняем индекс клетки, где стоял бот на None
- self.board[self.bots[bot_number].x][self.bots[bot_number].y].change_index(None)
- #удаляем бота из масиива
- del self.bots[bot_number]
- #генерирует на арене яд и еду
- def spawn_obj(self, obj, kol):
- if obj == "food":
- obj = 2
- elif obj == "poison":
- obj = 3
- else:
- obj = 0
- i = 0
- #пока не заполним нужное количество ячеек
- while i < kol:
- # две рандомных координаты
- x, y = get_random_coordinates()
- # если в этой ячейки пустота -- то изменяем значение этой ячеки на obj
- if str(self.board[x][y]) == '0':
- # изменяет значение ячейки на obj
- self.board[x][y].change_value(obj)
- i += 1
- #копируем ботов до количества count_of_bots -- делаем
- def copy_bots(self):
- #i ходит от 0 до количество ботов - сколько ботов уже есть в списке и т.к. у нас есть ещё вложенный цикл
- #делим на количество его операций
- for i in range((self.count_of_bots-self.end_count) // self.end_count):
- #проходим каждый раз по оставшимся ботам и делаем deepcopy каждого из них
- for j in range(self.end_count):
- self.bots.append(deepcopy(self.bots[j]))
- #мутируем count_of_bots // end_count первых ботов, n -- сколько мутаций надо произвести
- def mutate_bots(self, n=1):
- #i принимает значения от 0 до count_of_bots // end_count
- for i in range(self.count_of_bots // self.end_count):
- #делаем мутацию у данного бота
- self.bots[i].mutate_bot(n)
- arena = Arena() #создаём арену
- arena.add_obj(3, "wall") #добавляем на арену стены
- arena.add_obj(8, "food") #добавляем на арену еду
- arena.add_obj(8, "poison") #добавляем на арену яд
- arena.make_bots()
- #ввод числа посторений
- number_of_repeat = int(input("Input number of repeat:\n"))
- #делаем number_of_repeat операций
- for g in range(number_of_repeat):
- #пока у нас на арене больше 8 ботов
- while len(arena.bots) > arena.end_count:
- bot_number = 0 #номер текущего бота
- #пока номер текущего бота не дойдёт до конца масиива bots или ботов не останется 8
- while bot_number < len(arena.bots) and len(arena.bots) > arena.end_count:
- #запоминаем длинну массива bots
- length = len(arena.bots)
- #оправляем номер бота в функцию start -- делает несколько ходов бота до заверщающего дейтсвия
- arena.bots[bot_number].start(arena, bot_number)
- #проверяем длинну массива bots, если она не изменилась(данный бот не умер), то идём по массиву дальше
- if length == len(arena.bots):
- bot_number += 1
- #спавним на арене яд
- arena.spawn_obj("poison", 3)
- # спавним на арене еду
- arena.spawn_obj("food", 3)
- #копируем ботов до изначального количества
- arena.copy_bots()
- #делаем мутацию у ботов
- arena.mutate_bots()
- print(g)
- print(arena.bots[0].memory)
- #не проходит нужное количество итераций, останавливает примерно 1 - 2
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement