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.