Magazyn Enter, kwiecień 1994, strona 146

Adam Ryba

Krzemowe armie (1)

Jedną z ciekawszych cech języka Redcode jest możliwość równoległego wykonywania kilku (według standardu WA'91 do 64) niezależnych procesów w ramach jedngo walczącego programu. Procesy te są wykonywane na przemian po jednym rozkazie. tak że wszystkie działają z identyczną szybkością. Jednak im więcej takich sprzymierzonych procesów znajduje się na arenie, tym wolniej każdy z nich jest wykonywany, ale także tym trudniej je wszystkie zniszczyć.

Oto Mice, jeden ze starszych wojowników korzystających z tej zasady:

  ;MICE
  ;Chip Wendell
  ptr    DAT            0
  start  MOV #12        ptr
  loop   MOV @ptr       <dest
         DJN loop       ptr
         SPL @dest
         ADD #653       dest
         JMZ start      ptr
  dest   DAT            833
         END

Mice rozrzuca po rdzeniu kopie swojego kodu, podobnie jak Gnom robi to z bombami DAT. a każdą z tych kopii ożywia rozkazem SPL. Każda tak uruchomiona kopia jest w pełni samodzielnym wojownikiem, która, tak samo, jak pierwowzór, rozrzuca po arenie swoje kopie, także ożywiając je rozkazem SPL. W ten sposób już po niedługim czasie arena zostaje zalana wciąż powiększającymi się zastępami żołnierzy.

Za powielenie kodu programu odpowiedzialne są trzy początkowe rozkazy. Pierwszy z nich wpisuje do linii ptr liczbę kopiowanych komórek areny. Nieprzypadkowo jest to wartość dwukrotnie większa od rzeczywistej długości programu. Mice ze swym kodem przepisuje kawałek areny wypełniony rozkazami DAT, którymi ma nadzieję trafić i uszkodzić przeciwnika. Tak więc pętla kopiująca (wiersz loop i następny), której konstrukcję znamy już z wojownika Gemini, obok swej zasadniczej funkcji prowadzi ostrzał rdzenia, co znacznie zwiększa skuteczność programu.

Mice uruchamia swojego sobowtóra natychmiast po utworzeniu, po czym ustala adres następnej kopii i wszystko zaczyna się od nowa. Ciekawostką jest, że skok zapętlający kod tego wojownika wykonywany jest nie instrukcją JMP, a JMZ start ptr. Zazwyczaj po skopiowaniu programu wskaźnik ptr jest wyzerowany, więc skok jest wykonywany. Jeśli jednak kod wojownika zostałby uszkodzony, np. przez Skoczka, ptr zawierałby wartość niezerową, JMZ nie wykonałby skoku i uszkodzony proces popełniłby samobójstwo, aby nie spowalniać niepotrzebnie działań sprawnych towarzyszy.

Mice jest już leciwym programem, a mimo to od 1985 roku, kiedy to wygrał I Międzynarodowy Turniej Wojen Rdzeniowych, utrzymuje dobrą formę i nadal wdeptuje w arenę większość swoich przeciwników. Aby go pokonać, należałoby unieszkodliwić wszystkie jego procesy w stosunkowo krótkim czasie. Zwykłe miotacze bomb DAT (nie wspominając już o robakach) nie są w stanie tego dokonać — w miejsce każdego uśmierconego procesu wroga natychmiast pojawia się gdzieś następny…

Każdy proces Mice'a działa jako całkowicie samodzielny i niezależny od pozostałych program. ORK_URK jest natomiast przykładem wojownika, którego poszczególne procesy wpsółpracują ze sobą lub uzupełniają się wzajemnie:

  ;ORK_URK
  ;Jarosław Pyszny, 1992
         DAT 0          0
  start  SPL kopia      19
         SPL st1
         SPL st2
         DAT 0          0
  cel    DAT 0          #5
  st1    MOV cel        @cel
         ADD #5         cel
  cel1   JMP st1        #-5
         DAT 0          0
  cel2   DAT 0          0
  st2    MOV cel2       @cel1
         SUB #5         cel1
  adr    JMP st2        1003
         DAT 0          0
         DAT 0          0
  kopia  MOV @start     <adr
         DJN kopia      start
         JMP @adr
         DAT 0          0
         DAT 0          0
         END

Jeśli Mice'a można porównać do rozmnażającego się robaka, to ORK_URK jest raczej wieloprocesową wersją Gnoma. Skłąda się on z czterech bardzo wyraźnie wyodrębnionych procesów. Zadaniem pierwszego z nich, rozpoczynającego się od etykiety start, jest uruchomienie trzech pozostałych. Dwa z nich, st1 i st2, to znane nam już miotacze bomb DAT. Ostrzeliwuję one arenę w dwóch kierunkach, do przodu i do tyłu, niczym dwaj strzelcy oparci o siebie plecami. Natomiast trzeci z nich, kopia, zajmuje się przepisaniem obu strzelców w inny rejon dzenia (w przypadku areny o rozmiarze 2000 komórek będzie to mniej więcej połowa) i uruchomieniem ich jako dodatkowych procesów. Kopiuje on w tym celu kod całego wojownika (bez linii start) i wykonuje fragment kodu procesu inicjującego.

Warto zauważyć, że strzelec st2 nie trafia bombami w dziury w kodzie ORK_URK-a i w konsekwencji proces kopia po przepisaniu całego wojownika może ożywić jedynie kopię strzelca st1 (rozkaz SPL st2 jest bowiem zamazany). ORK_URK działa więc jako trzy samodzielne miotacze, z których po pewnym czasie, zależącym głównie od rozmiarów rdzenia, przy życiu pozostaje tylko jeden, ale za to bombardujący arenę na najwyższych obrotach.

Można się pokusić o drobną modyfikację kodu ORK_URK-a i zmienić treść wiersza cel z JMP st1 #-5 na JMP st1 #-4. Będzie on wówczas działał jako cztery, nie ostrzeliwujące się nawzajem miotacze, jednak zmiana ta nie będzie miała znaczącego wpływu na jego zdolności bojowe.