Wyobraź sobie, że mamy czarodzieja znającego kilka zaklęć. Każde zaklęcie ma 3 atrybuty: Obrażenia, czas ostygnięcia i czas rzucania. Całkiem standardowe rzeczy RPG.
Czas odnowienia: czas (t) potrzebny do ponownego rzucenia tego czaru. Zaklęcie „odnawia się” w momencie rozpoczęcia rzucania.
Czas rzucania: czas (t) potrzebny do użycia zaklęcia. Podczas gdy czarodziej rzuca coś, innego czaru nie można rzucić i nie można go anulować.
Pytanie brzmi: jak zmaksymalizować obrażenia przy różnych zestawach zaklęć?
Łatwo jest obliczyć najwyższe obrażenia na czas rzucania. Ale co z sytuacjami, w których lepiej jest poczekać, a potem utknąć, rzucając zaklęcie o niskim poziomie obrażeń, gdy dostępne jest znacznie wyższe?
Na przykład,
Kula ognia: 3000 obrażeń, 3 sekundy rzucania, 6 sekund ostygnięcia.
Frostbolt: 20 obrażeń, 4 sekundy rzucania, 4 sekundy ostygnięcia.
Fireblast: 3 obrażenia, 3 sekundy rzucania, 3 sekundy ostygnięcia.
W takim przypadku twoje obrażenia na sekundę są większe, jeśli zdecydujesz się wybrać niższe zaklęcie DPCT (podmuch ognia) zamiast zamrożenia. Musimy więc rozważyć konsekwencje wyboru zaklęcia.
W poniższym przykładzie przedstawiono przypadki „przerzucania” i „oczekiwania”.
źródło
Odpowiedzi:
Kiedy wchodzisz w sedno sztucznej inteligencji, niesamowite jest, jak wiele z tego naprawdę stanowi wyszukiwanie .
Alternatywnie, cel można wydać mniej niż 50 sekund, a poszukiwanie znalazłoby maksymalne obrażenia, które można by zadać w 50 sekund.
Podłącz te parametry do Uniform Cost Search (UCS) i presto, co gwarantuje optymalny plan bitwy. Jeszcze lepiej, jeśli możesz wymyślić heurystykę, wyszukiwanie za pomocą A * lub IDA *, a otrzymasz tę samą odpowiedź znacznie szybciej.
Dodatkowymi zaletami korzystania z LUW jest to, że może znaleźć optymalną kolejność rzutowania dla znacznie bardziej skomplikowanych sytuacji niż ta, w której podano tylko 3 zmienne. Niektóre inne aspekty, które można łatwo dodać:
LUW nie jest wszechmocny. Nie może modelować korzyści zaklęć ochronnych. W tym celu musisz uaktualnić do wyszukiwania alfa-beta lub minimax.
Również nie radzi sobie zbyt dobrze z obszarami afektu i walkami grupowymi. LUW można dostosować, aby zapewnić rozsądne rozwiązania w takich sytuacjach, nie ma gwarancji znalezienia optymalnego rozwiązania.
źródło
Jest to specjalistyczny problem optymalizacji kombinatorycznej. Wraz ze wzrostem liczby zaklęć znacznie wzrasta trudność w znalezieniu optymalnej kombinacji / wzoru zaklęć. Heurystyka podobna do tej stosowanej w przypadku problemu plecakowego byłaby cenna w rozwiązaniu tego problemu.
źródło
Musisz pomyśleć w kategoriach „obrażeń na jednostkę czasu rzucania” (DPCT) - na przykład kula ognia z 3-sekundowym rzuceniem i zadaniem 3000 obrażeń spowodowałaby 1000 DPCT.
Jeśli musiałbyś poczekać 3 sekundy na odnowienie przed rzuceniem go, zmniejszyłoby to do 500 DPCT (3000 obrażeń podzielonych przez 6 sekund łącznie, łącznie z oczekiwaniem)
Musisz więc tylko określić czas uszkodzenia każdego czaru, łącznie z pozostałym czasem oczekiwania na odnowienie. Wybierz ten z najwyższym DPCT, poczekaj w razie potrzeby, a następnie rzuć. Powtarzaj, dopóki szef nie umrze :)
źródło
Korzystając z tego przykładu, prawdopodobnie chciałbyś, aby dwa zaklęcia były bardziej skuteczne, ale być może dałyby ci inną przewagę. Krótki czas rzucania (lub brak czasu rzucania w tym przypadku) byłby bardzo przydatny, więc może być warto użyć, nawet jeśli zadaje mniej obrażeń i wymaga dłuższego użycia.
Zawsze możesz narzucić inny element równaniu. Punkty Many / Magiczne mogą służyć temu celowi, pozwalając graczowi ustalić, czy użycie tych punktów jest warte korzyści.
Ogólnie jednak, jak powiedział bluescrn, DPCT (lub DPS, jak jest nazywany w wielu grach, które są wysoce dostrojone i omawiane przez graczy szukających najlepszego miksu) jest naprawdę głównym elementem, który chcesz zbalansować, szczególnie jeśli masz jakieś drzewka technologii / umiejętności, które umożliwiają różnym graczom postęp z różnymi umiejętnościami, ale z możliwością zadawania podobnych obrażeń na danej pozycji w grze.
źródło
Zrozumiałem ten algorytm, który działa dobrze dla moich celów.
Ludzie przynieśli kilka świetnych punktów. Podanie ostatecznych parametrów celu pozwoliłoby normalnym algorytmom wyszukiwania robić swoje. to znaczy. zadaj optymalne obrażenia w t sekund, zadaj x obrażeń w optymalnym czasie.
Mój algorytm po prostu zwraca sekwencję zaklęć o najwyższym DPS. Jest to szybki algorytm, ponieważ zmniejsza rozmiar zestawu, przez który przechodzisz, nie wymaga znajomości innych technik drzewa wyszukiwania.
Pierwszym krokiem jest zidentyfikowanie zaklęcia o największej wartości obrażeń na czas rzucania. Zaklęcie to staje się zaklęciem „podstawowym”, ponieważ gwarantuje najwyższe obrażenia na sekundę. Oznacza to, że zawsze powinieneś rzucić to zaklęcie, jeśli spełnione są następujące 2 warunki: 1) Zaklęcie bazowe jest dostępne (nie przy odnawianiu). 2) Obecnie nie rzucasz czaru.
Zatem staje się to kwestią wypełniania innych zaklęć, gdy zaklęcie podstawowe jest odnawiane. Pomiędzy (czas rzucania) a (czas odnowienia - czas rzucania). Jednak może wystąpić pewne nakładanie się (powyższa reguła 2 jest fałszywa).
Następnie staje się kwestią rekurencji przez wszystkie zaklęcia nie bazowe, aby znaleźć wszystkie sekwencje zaklęć, które nie naruszają 2 zasad.
W przypadku zaklęć, które nakładają się na siebie, należy je ukarać za potencjalne obrażenia, które mogło spowodować zaklęcie podstawowe (do maksymalnych obrażeń).
Weźmy na przykład 2 zaklęcia
1: 300 obrażeń, czas rzucania 3 s, czas odnowienia 10 s
2: 290 obrażeń, czas rzucania 3 s, czas odnowienia 3 s
Najwięcej obrażeń pochodzi z sekwencji 1–2–2–2, co powoduje nakładanie się 2 sekund na potencjalny rzut nr 1. Jest to jednak nadal korzystne, ponieważ jeśli nie rzucisz trzeciego zaklęcia (tj. 1–2–2), zadasz 880 obrażeń na 1 sekundę, aby zaoszczędzić. Jeśli rzucisz dodatkowe zaklęcie # 2, wykonasz 1170 - 2 sekundy z # 1, czyli 200. Zatem 970 obrażeń to obrażenia względne.
źródło
Możesz zrobić prostą obudowę przełącznika w stylu „poziomu bezpieczeństwa”.
To jest tuż poza moją głową, więc strzeżcie się błędów logicznych wykraczających poza poziom myślenia mojego zmęczonego stanu, ale mam nadzieję, że to pomoże wam zacząć.
Zakładając, że Twój czas jest wykonywany w liczbach całkowitych bloku -
Niektóre wywołania metod są niepotrzebne z powodu twoich czasów zaklęć, ale w ten sposób zawsze jest miejsce na aktualizacje.
Edycja: Właśnie zdałem sobie sprawę, że będziesz musiał zresetować pozostały czas po rzuceniu nowego zaklęcia, prawdopodobnie najlepiej, aby uczynić go atrybutem klasy / polem i ustawić go z wywołania w ramach metod castSpell.
źródło