diff --git a/gaTraveling.md b/gaTraveling.md index ef32e4d..e0cd71b 100644 --- a/gaTraveling.md +++ b/gaTraveling.md @@ -4,11 +4,12 @@ ## Cel algorytmu Celem tego algorytmu jest wyznaczenie optymalnej trasy w zbieraniu ziół o konkretnych pozycjach, które są generowane losowo. Algorytm decyduje po które zioło udać się najpierw, starając się, aby końcowa suma odległości -pomiędzy odwiedzonymi pozycjami była jak najmniejsza. +pomiędzy odwiedzonymi pozycjami była jak najmniejsza. Gdy agent zbierze wszystkie zioła i dojdzie do ogniska, aby +odpocząć, utworzy również eliksir, który odnowi mu wszystkie statystyki pierwotnego (pełnego) stanu. ## Osobnik Traveling Osobnik jest to jednostka polegająca ewolucji za pomocą operacji genetycznych. -W mojej implementacji osobnika reprezentuje obiekt [Traveling.py](). Ten obiekt przechowuje następujące metody: +W mojej implementacji osobnika reprezentuje obiekt [Traveling.py](https://git.wmi.amu.edu.pl/s444409/DSZI_Survival/src/wirus_dev/src/AI/GaTravelingForHerbs/Traveling.py). Ten obiekt przechowuje następujące metody: ```python class Traveling: @@ -67,7 +68,7 @@ def __repr__(self): * Obiekt ten zwracany jest w formie tekstowej listy koordynatów. ## Obiekt GeneticAlgorithm -W pliku [GeneticAlgorithm.py]() znajduje się model selekcji osobników, warunek stopu, oraz główna pętla +W pliku [GeneticAlgorithm.py](https://git.wmi.amu.edu.pl/s444409/DSZI_Survival/src/wirus_dev/src/AI/GaTravelingForHerbs/GeneticAlgorithm.py) znajduje się model selekcji osobników, warunek stopu, oraz główna pętla algorytmu. ```python @@ -128,4 +129,88 @@ a następnie obliczamy długość populacji i deklarujemy iterator pętli, któr * Dopełniamy do pełnej liczności populacji, poprzez operację krzyżowania (metoda **crossover**), oraz ewentualną mutację (metodą **mutation**). * Wybieramy najlepszego osobnika z populacji po minimalnej odległości, oraz wyświetlamy wynik. - * Przeprowadzamy w ten sposób kolejną generację dopóki nie będzie ich 64. \ No newline at end of file + * Przeprowadzamy w ten sposób kolejną generację dopóki nie będzie ich 64. + +```python +def listOfTravel(self): + strTravel = self.run() + import ast + return ast.literal_eval(strTravel) +``` + +* Ta metoda, odpowiada za uruchomienie algorytmu oraz zwrócenie najlepszego wyniku w postaci listy koordynatów +(nie jako string). + +## Inicjalizacja pierwszej populacji i uruchomienie algorytmu + +Uruchamiając projekt za pomocą [Run.py](https://git.wmi.amu.edu.pl/s444409/DSZI_Survival/src/wirus_dev/Run.py) z użyciem parametru **ga_travel**, projekt uruchomi się tak jak w przypadku +testowej wersji z dodatkiem kodu (znajduje się on w [Game.py](https://git.wmi.amu.edu.pl/s444409/DSZI_Survival/src/wirus_dev/src/game/Game.py)) zaprezentowanego poniżej; + +```python + # Generate random travel list + self.travelCoords = random.sample(self.map.movableList(), 10) + import ast + self.travelCoords = ast.literal_eval(str(self.travelCoords)) + + # Insert herbs on random travel coordinates + self.map.insertHerbs(self.travelCoords) + + # Initialize genetic algorithm + firstGeneration = [Traveling(START_COORD + sample(self.travelCoords, len(self.travelCoords)) + END_COORD) for _ + in range(100)] + mutationProbability = float(0.1) + ga = GeneticAlgorithm(firstGeneration, mutationProbability) + self.movementList = ga.listOfTravel() + + # Define list of entities which player should pass to collect herbs + self.entityToVisitList = [] + for i in self.movementList: + self.entityToVisitList.append(self.map.getEntityOnCoord(i)) + + # Remove first element, because start coordinates is None + self.entityToVisitList.remove(self.entityToVisitList[0]) + + self.screen.ui.console.printToConsole("First generation: " + str(firstGeneration[0])) + self.screen.ui.console.printToConsole("The best generation: " + str(self.entityToVisitList)) + + self.mainLoop() +``` + +* Generujemy losową listę 10 koordynatów na mapie wolnych od entity za pomocą metody **map.movableList()** i konwertujemy +ją na normalną listę (nie *string*). +* Umieszczamy entity ziół w miejscach wygenerowanych koordynatów. +* Tworzymy pierwszą generację w postaci 100-elementowej listy, za pomocą konstruktora obiektu **Traveling** o koordynatach ziół plus startowa pozycja gracza +i pozycja ogniska, gdzie agent będzie w stanie sporządzić miksturę odnawiającą jego statystyki. +* Deklarujemy algorytm genetyczny przekazując pierwszą generację oraz prawdopodobieństwo mutacji wynoszące 10% +* Tworzymy listę kordynatów na których będziemy się poruszać, gdzie jej wartość co zwrócona lista przez +metodę **ga.listOfTravel()** +* Aby udać się po odpowiednie cele, tworzymy listę entity, które musimy zebrać, wykorzystując przy tym +wcześniej stworzoną listę **movementList** oraz metodę **map.getEntityOnCoord**. +* Usuwamy z listy **entityToVisitList** pierwszy element, gdyż jest to startowa pozycja gracza, na której nie +ma żadnego entity. + +## Poruszanie się +*Zdefiniowane jest w pliku/klasie [EventManager.py](https://git.wmi.amu.edu.pl/s444409/DSZI_Survival/src/wirus_dev/src/game/EventManager.py).* + +```python + if keys[pygame.K_t]: # Handle traveling movement to collect herbs + if self.player.movementTarget is None and self.iterator <= 10: + target = self.game.entityToVisitList[self.iterator] + self.player.gotoToTarget(target, self.game.map) + self.iterator += 1 + + if self.player.herbs > self.takenHerbs: # Console log when player collect herb + self.game.screen.ui.console.printToConsole("Ziele zebrane! Ilość: " + str(self.player.herbs)) + self.takenHerbs = self.player.herbs + + if self.player.readyToCrafting: # Console log and reset statistics because of collect all herbs + self.game.screen.ui.console.printToConsole("Eliksir został utworzony i spożyty!") + self.player.statistics.set_hp(100) + self.player.statistics.set_stamina(100) + self.player.statistics.set_thirst(-100) + self.player.statistics.set_hunger(-100) + self.player.readyToCrafting = False +``` +Po kliknięciu przycisku **t** agent uda się po kolejne ziele do zebranie w +kolejce za pomocą algorytmu **A***. Obok jest również zaimplementowane wypisywanie ilości zebranych ziół, +oraz odnawianie statystyk po spożyciu eliksiru. \ No newline at end of file