import random import json # from ant import Ant # from gatherer import Gatherer from simulation.logic.fsm_ant import FSMAnt from simulation.board import Board class BlobManager: def __init__(self, board, default_knowledge): """ :type board: Board """ self.board = board self.knowledge = dict() self.scouters = [] with open(default_knowledge, 'r') as file: self.knowledge.update(json.load(file)) self.knowledge['food'] = [] for x in range(self.board.width): for y in range(self.board.height): if self.board.has_food(x, y) and self.board.is_touched(x, y): self.knowledge['food'].append((x, y)) self.knowledge['max_scouters'] = self.compute_max_scouters() while len(self.scouters) < self.knowledge['max_scouters']: self.add_scouter() print("Scouters: " + str(len(self.scouters))) def save(self): d = self.knowledge.copy() del d["food"] del d["max_scouters"] return json.dumps(d, indent=4, sort_keys=True) def move(self): deads = [] for scouter in self.scouters: old = (scouter.x, scouter.y) scouter.move() if old == (scouter.x, scouter.y): deads.append(scouter) else: if self.board.has_food(scouter.x, scouter.y) and (scouter.x, scouter.y) not in self.knowledge['food']: self.food_discovered(scouter.x, scouter.y) scouter.update() new_max = self.compute_max_scouters() if new_max != self.knowledge['max_scouters']: print("Scouters: " + str(new_max)) self.knowledge['max_scouters'] = new_max scouters_qt = len(self.scouters) diff = self.knowledge['max_scouters'] - scouters_qt if diff > 0: for _ in range(diff): self.add_scouter() elif diff < 0: for _ in range(-diff): self.remove_scouter() for dead in deads: self.scouters.remove(dead) self.add_scouter() self.board.manage_blob(self.knowledge["Global Decrease"], self.knowledge["Remaining Blob on Food"]) def add_scouter(self): if len(self.scouters) < self.knowledge['max_scouters']: if len(self.knowledge['food']) != 0: index = random.randrange(len(self.knowledge['food'])) (x, y) = self.knowledge['food'][index] else: x, y = self.find_blob_square() self.scouters.append(FSMAnt(self.board, self.knowledge, x, y)) else: print("Max scouters already reached !") def remove_scouter(self): nbr = random.randrange(len(self.scouters)) del self.scouters[nbr] def compute_max_scouters(self): total_scouters = self.knowledge["Computing"]["Blob Size Factor"] * self.board.get_blob_total() \ + self.knowledge["Computing"]["Covering Factor"] * self.board.get_cover() \ + self.knowledge["Computing"]["Known Foods Factor"] * len(self.knowledge['food']) total_scouters *= (self.knowledge["Computing"]["Global Factor"] * (self.board.height * self.board.width / 100000)) return max(self.knowledge["Scouters"]["Min"], int(total_scouters)) def find_blob_square(self): availables = [] total_blob = 0 for x in range(self.board.width): for y in range(self.board.height): if self.board.is_touched(x, y): qt = self.board.get_blob(x, y) + 1 total_blob += qt availables.append(((x, y), qt)) if len(availables) == 0: return 0, 0 # Random need cast to integer # Floor cast will make sure a solution is found index_pond = random.randrange(int(total_blob)) acc = 0 for square, qt in availables: acc += qt if acc >= index_pond: return square def reset(self, x, y): for scouter in self.scouters.copy(): if scouter.x == x and scouter.y == y: self.scouters.remove(scouter) for food in self.knowledge['food'].copy(): if food == (x, y): self.knowledge['food'].remove(food) self.knowledge['max_scouters'] -= 1 def food_discovered(self, x, y): self.knowledge['food'].append((x, y)) # self.knowledge['max_scouters'] += 1 # for _ in range(1): # self.scouters.append(FSMAnt(self.board, self.knowledge, x, y, Blob_Manager.DROP_VALUE)) # print("Food discovered in (" + str(x) + ", " + str(y) + ")") def food_destroyed(self, x, y): self.knowledge['food'].remove((x, y))