class Simulation: mode = {"sin": sin, "const": None} #T=30 def __init__( self, ID, statistics, environment, occupyPercent, sidesRatio=[20, 80], hunterRatio=[33, 33, 34], preyRatio=[33, 33, 34], display=False, maxDayNum=10, grassUpdateFrequency=7, T=30, sunMode="const", communicator=None, ): self.environment = environment self.ID = ID self.statistics = statistics self.communicator = Communicator() self.statistics.writeMapData(self.environment) self.occupyPercent = occupyPercent self.sidesRatio = sidesRatio self.hunterRatio = hunterRatio self.preyRatio = preyRatio self.display = display self.cycles = 0 self.days = 0 self.minProductivity = self.environment.grassCellNum // 5 self.grassUpdateFrequency = grassUpdateFrequency self.maxDayNum = maxDayNum self.T = T self.sunMode = self.__class__.mode[sunMode] self.cellDict = {} Animal.AnimalPlacer.initBiota(self) Animal.AnimalPlacer.initAnimalMatrix(self) Animal.AnimalPlacer.placeAllAnimals(self) def run(self): if self.display: self.communicator.sendResolution(self.environment.width, self.environment.height) self.communicator.sendSignal("open") self.communicator.runGraphic() self.maxProductivity = self.environment.startGrassAmount amountListHunter = [] amountListPrey = [] while True: if self.totalNum <= 1 or keyboard.is_pressed( 'q' ) or self.cycles / self.grassUpdateFrequency > self.maxDayNum: self.communicator.closeProgram() break if not self.communicator.getData(): #self.simulationControl([0, 1, 0])# amountListHunter.append(copy.copy(self.speciesAmount[0])) amountListPrey.append(copy.copy(self.speciesAmount[1])) asyncio.run(self.passCycle()) if self.cycles % self.grassUpdateFrequency == 0: self.statistics.writeSimulationData( self, amountListHunter, amountListPrey) amountListHunter = [] amountListPrey = [] self.sunActivityFunc() self.environment.addGrass() self.days += 1 self.cycles += 1 if self.display: resultStr = self.composeResultMatrix() self.communicator.sendData(resultStr) def sunActivityFunc(self): if self.sunMode == None: return None self.environment.startGrassAmount = self.maxProductivity * self.sunMode( self.days, self.T) if self.environment.startGrassAmount < self.minProductivity: self.environment.startGrassAmount = self.minProductivity async def passCycle(self): i = 0 for animal in self.animalList: await animal.activityProcess(i) i += 1 def showAnimalData(self): i = 1 for animal in self.animalList: print(i, ". ", animal.symbol, end=": ") for cell in animal.cellList: print("(", cell.y, ",", cell.x, ")", end=" | ") print(animal.cellLife, " | ", animal.cellList[0].localDirect) i += 1 def showMap(self, needShow=[1, 1, 1]): if needShow[0]: print("mapMatrix:") for i in range(self.environment.height): for j in range(self.environment.width): print(self.environment.groundMatrix[i][j], end="") print() if needShow[1]: print("animalMatrix:") for i in range(self.environment.height): for j in range(self.environment.width): if self.animalMatrix[i][j] != None: print(self.animalMatrix[i][j], end="") else: print(" ", end="") print() resultMatrix = copy.deepcopy(self.environment.groundMatrix) for i in range(self.environment.height): for j in range(self.environment.width): if self.animalMatrix[i][j] != None: resultMatrix[i][j] = self.animalMatrix[i][j] if needShow[2]: print("resultMatrix:") for i in range(self.environment.height): for j in range(self.environment.width): print(resultMatrix[i][j], end="") print() def simulationControl(self, needShow=[1, 1, 1]): self.showMap(needShow) self.showAnimalData() cellCoords = self.cellDict.keys() print(len(cellCoords), cellCoords) def composeResultMatrix(self): resultMatrix = copy.deepcopy(self.environment.groundMatrix) for i in range(self.environment.height): for j in range(self.environment.width): if self.animalMatrix[i][j] != None: resultMatrix[i][j] = self.animalMatrix[i][j] resultList = [] for row in resultMatrix: resultList.extend(row) resultStr = ''.join([str(elem) for elem in resultList]) + ' ' return resultStr
class Map: terrain = {"rock": "#", "ground": ",", "water": "~"} def __init__(self, height, width, terrainRatio, waterIntervals=[1, 2], rockIntervals=[0, 1], grassIntervals=[0, 3], communicator=None): self.terrainRatio = terrainRatio self.waterIntervals = waterIntervals self.rockIntervals = rockIntervals self.grassIntervals = grassIntervals self.height = height self.width = width self.square = height * width self.communicator = Communicator() self.groundMatrix = [] self.createField() self.placeObj(0) self.placeObj(1) self.placeObj(2) def createField(self): self.groundMatrix = [[ Map.terrain["ground"] for _ in range(self.width) ] for _ in range(self.height)] def placeObj(self, obj): percent = self.terrainRatio[obj] if obj == 0: self.interval = self.waterIntervals terrain = "water" multiplier = 5 elif obj == 1: self.interval = self.rockIntervals terrain = "rock" multiplier = 3 elif obj == 2: self.interval = self.grassIntervals grass = range(1, 10) multiplier = 4 cellNum = (self.square // 100) * percent Oy = range(self.height) Ox = range(self.width) sigma = range(self.interval[0], self.interval[1] + 1) if obj == 2: self.grassCellNum = cellNum self.startGrassAmount = cellNum while cellNum: x = random.choice(Ox) y = random.choice(Oy) s = random.choice(sigma) maxX = 0 maxY = 0 n = s * cellNum * multiplier while n: divx = int(random.gauss(x, s)) divy = int(random.gauss(y, s)) if (0 <= divy < self.height) and (0 <= divx < self.width): if self.groundMatrix[divy][divx] == Map.terrain["ground"]: cellNum -= 1 if obj != 2: self.groundMatrix[divy][divx] = Map.terrain[ terrain] elif obj == 2: self.groundMatrix[divy][divx] = random.choice( grass) if not cellNum: return None n -= 1 def saveMap(self): path = "maps_directory" if not os.path.isdir("maps_directory"): os.mkdir("maps_directory") fileList = os.listdir(path) fileName = path + "\\" + "mapObj" + str(len(fileList) + 1) + ".txt" print(fileName) i = 1 while True: if not os.path.exists(fileName): newFile = open(fileName, "wb") pickle.dump(self, newFile) newFile.close() break else: fileName = path + "\\" + "mapObj" + str(len(fileList) + i) + ".txt" i += 1 def copyMap(self, n=1): if n == 1: objCopy = copy.deepcopy(self) return objCopy else: copyList = [] i = 0 while i < n: copyList.append(copy.deepcopy(self)) i += 1 return copyList @staticmethod def loadMap(name): if os.path.isdir("maps_directory"): path = "maps_directory" mapFile = open(path + "\\" + name, "rb") mapObj = pickle.load(mapFile) mapFile.close() return mapObj def rewriteGrass(self): for i in range(self.height): for j in range(self.width): if type(self.groundMatrix[i][j]) is int: self.groundMatrix[i][j] = Map.terrain["ground"] self.placeObj(2) def addGrass(self): if self.grassCellNum < self.startGrassAmount: diff = self.startGrassAmount - self.grassCellNum i = 0 while i < diff: y = random.randint(0, self.height - 1) x = random.randint(0, self.width - 1) if self.groundMatrix[y][x] == ",": self.grassCellNum += 1 self.groundMatrix[y][x] = 1 i += 1 continue elif str(self.groundMatrix[y][x]) not in ("#", "~"): self.groundMatrix[y][x] += 1 if self.groundMatrix[y][x] > 9: self.groundMatrix[y][x] = 9 i += 1 def MatrixToStrFlow(self): resultMatrix = self.groundMatrix resultList = [] for row in resultMatrix: resultList.extend(row) resultStr = ''.join([str(elem) for elem in resultList]) + ' ' return resultStr def showMapGraphic(self): resultStr = self.MatrixToStrFlow() self.communicator.sendResolution(self.width, self.height) self.communicator.sendSignal("open") self.communicator.runGraphic() while True: if keyboard.is_pressed('q'): self.communicator.closeProgram() break if not self.communicator.getData(): self.communicator.sendData(resultStr) def showMapText(self): for i in range(self.height): for j in range(self.width): print(self.groundMatrix[i][j], end="") print()