import logging import os import numpy as np # TODO: if set to competition mode, get the seed from the api FORCE_SEED = int(os.getenv("FORCE_SEED", "-1")) logger = logging.getLogger("complib-logger") class Gamestate: @staticmethod def __set_random_seed(seed: int): logger.debug(f"Seeding seed to: {seed}") np.random.seed(seed) @staticmethod def __get_random_number(min: int, max: int): return np.random.randint(256 ** 4, dtype=' str: return f"""Seed: {self.seed} Heu Color: {self.heu_color} Material Pairs: {self.material_pairs} Material Zones: {self.materials} Logistic Plan: {self.logistic_plan} Logistic Centers: {self.logistic_center}""" def __init__(self, seed: int): """ Erstellt den Seeding "Gamestate" für den angegebenen Seed. :param seed: Seed welcher zum Erstellen des Gamestates benutzt werden soll. """ if FORCE_SEED == -1: self.seed = seed else: print(f"Wettkampfmodus, zufälliger Seed wird verwendet: Seed={FORCE_SEED}") self.seed = FORCE_SEED logger.debug(f"Creating gamestate with seed: {self.seed}") self.__set_random_seed(self.seed) self.heu_color = self.__get_random_number(1, 2) self.materials = [0, 0, 0, 0] self.material_pairs = [] for i in range(0, 4): num1 = self.__get_random_number(0, 3) self.material_pairs.append([num1, num1]) while self.material_pairs[i][1] == num1: self.material_pairs[i][1] = self.__get_random_number(0, 3) flat = [item for sublist in self.material_pairs for item in sublist] for i in range(0, 4): self.materials[i] = flat.count(i) self.logistic_plan = [0 for i in range(0, 21)] self.logistic_center = [[0, 0, 0, 0] for i in range(0, 4)] visited = [5, 5, 5, 5] def __logistic_plan_generator(i: int): drive_to = self.__get_random_number(0, 3) for j in range(0, 4): drive_to = (drive_to + j) % 4 if visited[drive_to] <= 0 or drive_to == self.logistic_plan[i - 1]: continue self.logistic_plan[i] = drive_to visited[drive_to] -= 1 finished = True for k in visited: if k != 0: finished = False if finished and drive_to == 2: visited[drive_to] += 1 continue if finished: return True if i < len(self.logistic_plan): if __logistic_plan_generator(i + 1): return True visited[drive_to] += 1 return False self.logistic_plan[0] = 2 visited[2] -= 1 _ = __logistic_plan_generator(1) self.logistic_plan[-1] = 2 for i in range(0, len(self.logistic_plan) - 1): self.logistic_center[self.logistic_plan[i]][self.logistic_plan[i + 1]] += 1 self.logistic_plan = [x + 10 for x in self.logistic_plan] logger.debug(f"Created gamesate: {str(self)}") def get_heuballen(self) -> int: """ Die Funktion gibt entweder die Zahl "1" oder "2" zurück. Wenn die Funktion "1" zurückgibt, dann liegen die Heuballen auf den gelben Linien. Wenn die Funktion "2" zurückgibt, dann liegen sie auf den blauen Flächen. :return: Gibt entweder die Zahl 1 oder 2 zurück. """ return self.heu_color def get_logistic_plan(self) -> []: """ Die Funktion gibt den "Logistik Plan" zurück. Also die Reihenfolge, in welcher der Roboter die Logistik Zonen Abfahren muss, um die Pakete welche dort liegen zu sortieren. :return: Eine Liste an Zahlen zwischen 10 und 13. """ return self.logistic_plan def get_material_deliveries(self) -> [[]]: """ Die Funktion gibt die einzelnen "Material Lieferungen" zurück. Da der Roboter immer zwei Paare an Materialien anliefern muss, gibt die Funktion eine Liste an Material Paaren zurück. Die Materialien werden dabei durch ihre Zonen-ID representiert. Also Holz ist z.B. "0" und die Ziegelsteine sind "3". :return: Eine Liste and Material Paaren. """ return self.material_pairs