Jak (można) trenować wojowników?
Młodzi adepci Wojen Rdzeniowych po opanowaniu języka Redcode bardzo często stają przed problemem, jak właściwie zabrać się za tworzenie wojownika?
Niestety, na to pytanie nie istnieje jednoznaczna odpowiedź — jest wiele metod treningu i trudno opisać szczegółowo którąkolwiek z nich.
Mimo to postaram się przynajmniej naszkicować metodę, jaką posługiwałem się podczas tworzenia Sharka. Szkic ten składa się z czterech punktów będących bardziej opisami podstawowych zagadnień niż kolejnych etapów treningu.
Opracowanie strategii
Wiadomo, że skuteczność wojownika w dużej mierze zależy od jego strategii, czyli pomysłu na zwycięstwo (mniej więcej tak, jak efektywność programu od wyboru algorytmu). Ponieważ sprawa jest poważna, przysiadamy fałdów i wypisujemy cechy programu mogącego według nas być najlepszym, np.:mobilny, wieloprocesowy, posługujący się skoczkami, wyszukujący przeciwnika itd. Przy projektowaniu strategii kierujemy się własnym wyczuciem i doświadczeniem, choć przydaje się znajomość warunków, w jakich pisany przez nas program będzie walczył — determinują one używanie określonych stylów walki.
Ocenianie wojowników
W trakcie doskonalenia kodu wojownika często stajemy przed koniecznością wyboru z kilku wersji programu tej najsprawniejszej. Najprościej przeprowadzć w tym celu serie walk każdego z ocenianych programów z grupą kontrolną, czyli kilkoma specjalnie dobranymi wojownikami, po czym porównujemy uzyskane przez niego wyniki. Skład grupy kontrolnej wybieramy zależnie od przyjętych kryteriów, z czym nie ma problemów, gdy przygotowujemy naszego wojownika do walki z określonym typem przeciwnika. Jeśli chcemy wytrenować uniwersalnego zawodnika, możemy mieć problem z dobraniem naprawdę reprezentatywnej grupy kontrolnej. Proponuję zatem jej połowę obsadzić najlepszymi posiadanymi wojownikami, a przeciętnymi stosując różne strategie. Aby móc porównywać wyniki uzyskane w grupach o różnej liczbie powtórzeń walk, wygodnie jest przedstawić je w procentach (maksymalna możliwa liczba punktów : liczba punktów / liczba maksymalna * 100%).
Podział na podproblemy
Po napisaniu pierwszej wersji programu realizującego założoną strategię, „dzielimy” jego kod na części, które później będziemy mogli ulepszać niezależnie od pozostałych. Jedna część może być odpowiedzialna za rozrzucanie bomb po rdzeniu, inna za kopiowanie wojownika w inne części rdzenia, jeszcze inna za obliczanie adresów podczas mnożenia się programu itd. W ten sposób problem polegający na ulepszeniu naszego wojownika spowadzamy do doprowadzenia do perfekcji jego poszczególnych części, co znakomicie ułatwia pracę.
Optymalizacja fragmentów kodu
Każdą wydzieloną część programu ulepszamy teraz na wszelkie możliwe
sposoby, opracowując najróżniejsze metody ich wykonania, podstawiając je
do kodu wojownika i sprawdzając na rdzeniu ich wpływ na jego
skuteczność. Dla przykładu, jeśli ulepszamy procedurę rozrzucającą bomby
DAT
, trudno nam przewidzieć, czy lepiej rzucać je do
przodu, czy lepiej do tyłu? Co trzy, cztery, a może co siedem komórek?
Może zastosować zmienną gęstość rozrzutu, może rzucić równocześnie do
przodu i do tyłu itd. Musimy sprawdzić wszystkie możliwe pomysły, jakie
przyjdą nam do głowy, nawet te na pozór absurdalne. Jeden z nich na
pewno będzie najlepszy. Każdy fragment staramy się napisać jak
najkrócej, gdyż mniejsze programy działają szybciej, trudniej je trafić
i łatwiej przemieszczać.
Po udoskonaleniu ostatniego fragmentu nasz wojownik jest gotowy. Jeśli jego umiejętności nie są zadowalające, możemy cofnąć się do optymalizacji kodu lub też do opracowywania strategii — jeśli wystarczy nam sprytu, cierpliwości i dobrych pomysłów, w końcu dojdziemy do perfekcji, czego życzę wszystkim miłośnikom Wojen Rdzeniowych.