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.