diff --git a/route-planning.md b/route-planning.md index 0fae6c6..b6958b7 100644 --- a/route-planning.md +++ b/route-planning.md @@ -17,6 +17,8 @@ Drugim zadaniem dotyczącym projektu jest zastosowanie strategii przeszukiwania - s — pole, na którym jesteśmy - f — pole końcowe - dla s = f program kończy pracę, bo znajdujemy się już w położeniu końcowym, dlatego pominęłyśmy ten przypadek w definicji heurystyki. + + ``` def hscore(self, s, f): if f > s: @@ -29,12 +31,17 @@ def hscore(self, s, f): b_h = s % 5 - f % 5 + 1 return 2 * m.sqrt(a_h * 2 + b_h * 2) ``` + + Wpierw obliczamy wysokość trójkąta, jaki tworzą obecne i końcowe pole, w celu wyznaczenia przeciwprostokątnej — odległość między s i f. ## Funkcja następnika + + Tworzymy listę, do której będziemy kolejno generować sąsiadów dla danego x. + ``` def neighbours(self): self.neighbours = list(range(25)) @@ -54,8 +61,13 @@ def neighbours(self): self.neighbours[x] = [x - 5, x - 1, x + 1, x + 5] ``` + ## Główna pętla strategii przeszukiwania + + Zaczynamy od znalezienia w open_set pola o najniższym f. + + ``` while open_set: # Szukanie pola w open_set z najniższym f @@ -66,28 +78,46 @@ Zaczynamy od znalezienia w open_set pola o najniższym f. x = open_set[i] temp1 = self.f_score[open_set[i]] ``` + + Jeżeli to pole odpowiada temu, do którego chcemy dojść — wywołujemy funkcję tworzącą ścieżkę z pola wyjściowego. Póki nie — pomijamy. + + ``` if x == koniec: return self.reconstruct_path(self.came_from, koniec) ``` + Usuwamy x z open_set i wrzucamy do closed_set, aby upewnić się, że nie będziemy go ponownie sprawdzać. + + ``` open_set.remove(x) closed_set.append(x) ``` + Następnie sprawdzamy sąsiadów: + + ``` for y in self.neighbours[x]: ``` + + To tutaj chcieliśmy mieć pewność, że nie trafimy ponownie na x. + + ``` if y in closed_set: continue ``` + + Chcemy również sprawdzić, czy jeżeli y jest już w open_set, to nie istnieje krótsze przejście np. z pola startowego przez inne pole na y, niż bezpośrednio na pole y. + + ``` tentative_g_score = self.g_score[x] + self.game.fields[y][3] if y not in open_set: @@ -96,7 +126,11 @@ Chcemy również sprawdzić, czy jeżeli y jest już w open_set, to nie istnieje elif tentative_g_score < self.g_score[y]: tentative_is_better = True ``` + + Wyliczamy g i f — przewidywany dystans od startu do celu, dla y. + + ``` if tentative_is_better == True: self.came_from[y] = x @@ -104,8 +138,11 @@ Wyliczamy g i f — przewidywany dystans od startu do celu, dla y. self.f_score[y] = self.g_score[y] + self.hscore(y, koniec) ``` + ## Tworzenie ścieżki Przechodzimy po tablicy poprzedników, aż dojdziemy do początku — pola, które nie ma poprzednika. + + ``` def reconstruct_path(self, came_from, current): total_path = [current] @@ -124,6 +161,7 @@ Zmiany w projekcie zaszły również w pliku run.py, gdzie generujemy losowo pol Mamy tutaj tablicę tablic. Każda z nich zawiera kolejno informacje o: rodzaju upraw, glebie, nawodnieniu pola oraz koszcie podróży na pole z daną uprawą. + ``` def randomize_field(self): for x in range(25):