Nauczenie żabki omijania samochodów w grze Frogger

0

Cześć,

Pisze grę w podobie Froggera i chciałem do niej dorzucić AI, żeby zabka sama probowala omijać samochody i przeszkody.
Potrzebuję informacji jak się za to zabrać :)

0

Reinforced learning się nada.

0
Czitels napisał(a):

Reinforced learning się nada.

no właśnie do tak prostej gry to chyba jest za mocne. nie chcę żeby ona się uczyła.
w wierszach 1 - 5 musi iść do przodu jeśli ma wolne pole, ale musi też uważać na boki, żeby nic jej nie rozjechało.
w wierszach 7 - 12 musi iść tylko do przodu jeśli ma obiekt przed sobą, na który może wskoczyć, a dodatkowo uważać na szerokość planszy, żeby nie spadła z tego obiektu ;)

4

Tego typu "sztuczną inteligencję" od dziesiątek lat w grach robi się z użyciem maszyny stanów. Reinforced learning i inne tego typu modne wynalazki to jest overkill.

0

Na internecie, czy youtube istnieje wiele wątków odnośnie wykorzystania sztucznej inteligencji. Polecam zacząć od podstaw, takich jak przedstawili inni w swoich odpowiedziach

0

ludu jakie neural networks. Można zacząć od wpisania w google( Kursy, wideo itp.)
pathfinder algorithm

1

Jeśli dobrze myślę masz na myśli tą grę co są 4-5 pasów i jeżdżą samochody, to z góry widać, że najlepiej w pamięci(policzyć parę ruchów do przodu), czyli masz grid, nie musisz go sobie wyobrażać akurat, ale masz każdy samochód z danego pasa na jakiejś pozycji i co klatkę o ileś się przesuwa kratek, teraz musisz znaleźć taką kombinację, ruchów, która przejdzie na drugą stronę i nie trafi na żadne auto.

Najlepiej całą grę zrobić dyskretną do minimalnych kroków i robisz przejście grafu, czyli idziesz, idziesz i jak trafisz na auto, to cofasz jedną klatkę się do tyłu i wybierasz inne działanie np. czekanie 1-2 ruchy, aż przejdzie auto i dalej do przodu, aż nie przejdziesz na drugą stronę, kombinacja, która przejdzie to będzie twoje rozwiązanie.
Oczywiście co krok żaby aktualizujesz położenie samochodów, ale realną żabą nie ruszasz to robisz w pamięci dopiero jak wynik w pamięci przejdzie to wykonujesz ruchy żaby daną ścieżką.

To najprostsze co mi przychodzi do głowy i na pewno zadziała.

Jak sieci neuronowe chcesz użyć, to byś musiał dawać jakieś informacje sieci gdzie są położone wszystkie samochody, jeśli mają jednakową prędkość to tyle informacji starczy, jeśli nie to położenie + prędkość lub nawet i przyspieszenie.
Następnie podejmować decyzję czy do przodu, do tyłu, czy czekać w miejscu jeden tick.

Jeśli chcesz dać screena z gry zamiast położeń samochodów to sieć znacznie dłużej i znacznie więcej danych uczących będzie potrzebować żeby się nauczyć przechodzić grę.

Rozwiązanie bez użycia sieci neuronowych jest najłatwiejsze i powinno się od tego zacząć i potem zrobić z sieciami neuronowymi jako następne rozwiązanie tego samego problemu.

1

Podrzucę trochę inny pomysł, pokrewny do @nightm4re

Jest stan początkowy gry, czyli żabka na punkcie startowym, pojazdy i belki w określonej pozycji. Z każdego stanu jest możliwe przejście do innego stanu, przy czym odczekanie określonego czasu (które może być wielokrotne) to też zmiana stanu, bo belki i pojazdy przemieszczą się.

Potrzebna jest lista instancji stanu gry. Zaczynasz od jednego elementu, którym jest stan początkowy.
Potem, dla każdej instancji wykonujesz taką rzecz:

  1. Zapamiętujesz instancję i usuwasz ją z listy.
  2. Na tej instancji wykonujesz wszystkie możliwe, ale dozwolone zmiany stanu, wraz z odczekaniem jednego odcinka czasu. Otrzymasz od zera nowych instancji (gdy żaden ruch żabki nie jest możliwy, a odczekanie również spowoduje koniec gry) do pięciu nowych instancji (możliwy ruch w każdym kierunku i możliwe jest odczekanie).
  3. Dodajesz nowe instancje do listy. W każdej instancji należy zapamiętać całą historię ruchów (odczekanie traktowane jako ruch) od początku gry.
    W każdej iteracji liczba instancji może rosnąc do 5 razy, w każdej instancji jest stan gry po wykonaniu tej samej liczby ruchów. Prędzej czy później, jedna z instancji będzie reprezentować stan gry odpowiadający zwycięstwu, czyli żabka na mecie. W tej sytuacji masz opisany przebieg gry od startu do mety wykonując najmniejsza liczbę ruchów.

Aby trochę bardziej uzmysłowić, to opisze taki sposób dla kostki Rubika. Kostkę traktujemy jako obiekt, którym jest nie tylko sama kostka i tym samym układ elementów, ale też lista dotychczas wykonanych ruchów, która początkowo jest pusta. Dla standardowej kostki można wykonać 6 możliwych ruchów elementarnych. Zaczynam od jednej pomieszanej kostki. Ponieważ można wykonać 6 ruchów, klonuję kostkę otrzymując 6 egzemplarzy tak samo pomieszanej kostki, na każdym egzemplarzu wykonuje inny ruch. Od tej chwili, za dozwolony ruch uznaję tylko taką zmianę układu, która nie prowadzi do stanu poprzedniego, czyli inaczej mówiąc, nie jest to ruch przeciwny do ostatnio wykonanego w danej instancji. Przy takim ograniczeniu, dla każdej z 6 kostek możliwych jest tylko 5 ruchów, bo jeden ruch prowadzi do stanu, który miałem wcześniej. W związku z tym, każda kostkę klonuję 5 razy, czyli otrzymuję 30 kostek, w których jest 6 zbiorów po 5 takich samych kostek. Dla każdej kostki wykonuję jeden dozwolony ruch. Mam 30 kostek, z których każda ma inny układ. W kolejnej iteracji znowu robię klonowanie, w której jedna kostka zamienia się w 5 takich samych kostek, więc otrzymuję 30*5=150 kostek i dla każdej kostki z piątki wykonuję inny ruch. Ten algorytm można nieco zoptymalizować w taki sposób, że jeżeli po którejś iteracji, w zbiorze będą istnieć tak samo ułożone kostki, to usuwam nadmiarowe kopie, żeby każda kostka była inna.

Tak postępując, co każdą iterację liczba kostek rośnie pięciokrotnie, ale prędzej czy później (jeżeli wierzyć Wikipedii, to najpóźniej po 20 iteracjach), co najmniej jedna z nich będzie ułożona. W tym momencie wyrzucam wszystkie nieułożone kostki, a z ułożonej odtwarzam historię wykonanych ruchów. W ten sposób dostaję informację, jak ze stanu początkowego (określony układ kostki, od którego zaczynam jej układanie) otrzymać ułożoną kostkę wykonując najmniejszą liczbę ruchów.

3
andrzejlisek napisał(a):

Podałeś identyczne rozwiązanie co ja wcześniej, ale co do kostki, kostkę rubika można ułożyć rozwiązując z dwóch stron jednocześnie, wtedy spotkasz rozwiązanie pośrodku z angielskiego meet in the middle, potęga szybko rośnie, a dzięki rozwiązywaniu z dwóch stron jednocześnie można mega przyspieszyć rozwiązanie( normalnie miałbyś np. x^30, a tak wychodzi 2x^15, czyli mega zysk obliczeniowy), chodź w przypadku żaby, ciężko znaleźć końcową klatkę gdyż tu jest jeszcze czas chyba, że byśmy wiedzieli w jakim czasie powinna przejść to wtedy można znacznie szybciej znaleźć rozwiązanie, lub można losowo założyć potencjalne rozwiązania i bazując na tym szukać rozwiązania.

1

W całym tym temacie nie ma wcześniejszego postu (oprócz tego, o kostce rubika z filmem na YT) ani komentarza od @GodOfCode nawet po odświeżeniu.

Co do odczekiwania czasu, to też można wprowadzić czas dyskretny, a właściwie kilka możliwych długości czasu oczekiwania, czy czym żaden nie może być wielokrotnością innego. Na przykład 1/3 sekundy, 1/4 sekundy i 1/5 sekundy. W ten sposób od danego stanu możliwe jest siedem ruchów, czyli skok żabki w jeden z czterech kierunków lub odczekanie jeden z trzech odcinków czasu.

Grę tak samo można analizować od końca, czyli żabka skacze lub czeka, ale belki i pojazdy przemieszczają się w drugą stronę. W kostce, to można przyjąć różne interpretacje, jaki ruch jest ruchem elementarnym, bo są trzy możliwości:

  1. Obrót o 90 stopni zgodnie z ruchem wskazówek zegara (obrót w drugą stronę to jest to samo, to wykonanie trzech obrotów, a obrót o 180 stopni to dwa obroty) - 6 możliwych ruchów i taką wersje opisałem.
  2. Obrót o 90 stopni w dowolną stronę, obrót o 180 stopni to dwa obroty. - 12 możliwych ruchów.
  3. Obrót o 90 stopni w dowolną stronę lub o 180 stopni - 18 możliwych ruchów tak, jak na filmiku.

Co do iterowania, to rozumiem, że analiza kończy się w chwili, gdy zaistnieje taki sam stan w zbiorze generowanym od początku i w zbiorze generowanym od końca. Samą iterację można wykonywać na dwa sposoby:

  1. W każdym kroku iteruje się tylko jeden zbiór. Co drugi krok iteruje się zbiór początkowy, a w pozostałych zbiór końcowy.
  2. Potrzebne są dwa zbiory (dwie kopie) początkowe lub końcowe, przy czym przed rozpoczęciem głównego algorytmu, robi się jedną iterację na jednej z kopii. Załóżmy dwa zbiory początkowe, w których drugi jest po jednej iteracji. W głównym algorytmie wykonuje się iterację na trzech zbiorach jednocześnie. Jeżeli najkrótsza droga od początku do końca ma parzystą liczbę kroków, to "spotkają się" pierwszy zbiór początkowy i końcowy, a jeżeli najkrótsza droga ma nieparzystą liczbę iteracji, to "spotkają się" drugi zbiór początkowy (ten po dodatkowej iteracji) i zbiór końcowy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1