Magazyn Enter, luty 1995

Adam Ryba

Wyszukiwanie przeciwnika

Najprostszym i chyba też najbardziej intuicyjnym sposobem wyszukiwania wroga jest porównywanie kolejnych komórek rdzenia z komórką zawierającą instrukcję DAT 0 0. Jak pamiętamy, tą właśnie instrukcją sędzia walki czyści arenę przed każdym pojedynkiem, więc dopóki porównania nie będą wykazywać różnic, możemy mieć pewność, że przeglądamy czystą (a więc nie zajętą przez przewnika) arenę.

  wzór        DAT 0       0
  start       CMP wzor    -2
              JMP alarm
              JMP start   <start
  alarm       ...

Tak właśnie działa powyższy wojownik. Przesuwa on po arenie wiązkę skanującą tak długo, aż napotka jakąś komórkę różną od wzorca. Wtedy przechodzi do wiersza alarm, gdzie powinien znajdować się kod odpowiedzialny za zaatakowanie podejrzanego obszaru. Po przeprowadzonym ataku program powinien wrócić do wiersza start, aby kontynuować poszukiwania. Badanie wszystkich komórek, jedna po drugiej, zajmuje dość dużo czasu, spróbujmy więc zwiększyć szybkość przszukiwania kosztem, niestety, dokładności.

  wzór        DAT 0       0
  start       ADD #5      szukaj
  szukaj      CMP wzór    10
              JMP alarm
              JMP start
  alarm       ...

I rzeczywiście, program działa szybciej. Zauważmy teraz że właściwie nie musimy komórek areny porównywać z naszym wzorcem. Wystarczy, jeśli dwie dowolne komórki areny porównamy ze sobą. Gdy będą identyczne, to najprawdopodobniej obie będą zawierać instrukcję DAT 0 0 (możliwość znalezienia dwóch identycznych komórek różnych od DAT 0 0 możemy zaniedbać), więc nie będą nas interesować. Znalezienie natomiast dwóch różnych komórek rodzi podejrzenie, że przynajmniej jedna z nich należy do przeciwnika. Zapiszmy to w Redcode:

  start       ADD krok    szukaj
  szukaj      CMP -20     20
              JMP alarm
              JMP start
  krok        DAT -10     10
  alarm       ...

Ten skaner wyposażony jest w dwie wiązki przemiatające arenę w przeciwnych kierunkach. Każda napotkana „nierówność” rdzenia natychmiast uruchamia procedurę ataku zaczynającą się w linii alarm. Procedura ta może albo od razu ostrzelać obie podejrzane komórki, albo najpierw zbadać, którą z nich warto zaatakować i dopiero wtedy ostrzelać tę jedną. Inaczej będzie w tym, prawie identycznym programie:

  start       ADD krok    szukaj
  szukaj      CMP 20      25
              JMP alarm
              JMP start
  krok        DAT 10      10
  alarm       ...

Tutaj arena przemiatana jest nie dwoma niezależnymi, ale jedną podwójną wiązką skanującą. W razie wykrycia przeciwnika nie trzeba dodatkowo sprawdzać, którą z dwóch komórek należy ostrzelać — atak zawsze będzie skierowany w okolice obu.

Opisane powyżej skanery wyszukują przeciwnika badając zawartość całych komórek. Ponieważ wszystkie one używają w tym celu rozkazu CMP, często określa się je wspólnym mianem CMP-skanerów (CMP-scanner). Oprócz nich istnieją także skanery, które badanie poszczególnych komórek ograniczają wyłączeni do testowania ich B-argumentów. Oczywiście tam, gdzie B-argumenty będą wyzerowane, arena najprawdopodobniej będzie czysta, natomiast tam, gdzie ich wartości będą różne od zera, zapewne coś będzie zapisane. Programy takie zwykle nazywa się B-skanerami (B-field scanner, B-scanner). Oto przykładowy, bardzo prosty B-skaner:

  adres       DAT 0       0
  start       JMZ start   <adres
  alarm       ...

Jak widać, rozkaz JMZ nie pozwala opuścić wiersza start, dopóki wiązka skanująca nie natknie się na niezerowe pole B-argumentu. Wykorzystanie tu trybu adresowania pośredniogo zmniejszanego do przesuwania wiązki skanera skara kod programu, wymuszając jednocześnie bardzo dokładne (a więc powolne) badanie rdzenia. W praktyce, podobnie, jak w przypadku CMP-skanerów, zazwyczaj korzysta się z rozkazu ADD lub SUB.

  start       ADD #10     adres
  adres       JMZ start   10
  alarm       ...

Oczywiście wiązka skanująca nie musi przemiatać areny zawsze z tą samą dokładnością. Niektórzy wojownicy przeglądają arenę najpierw zgrubnie, a potem coraz dokładniej, zmniejszając za każdym razem skok wiązki np. o połowę. W ten sposób można przeciwnika namierzyć niemal natychmiast. Technika ta została opisana przy okazji omawiania finalistów ubiegłorocznych mistrzostw (ENTER-y 8/94, 9/94, 10/94).

O skuteczności danego skanera decyduje nie tylko sposób wyszukiwania przeciwnika, ale również sposób prowadzenia ataku. Trzeba przecież pamiętać, że sam fakt znalezienia jakiejś anomalii na arenie nie świadczy jeszcze o tym, że jest to żywy kod przeciwnika. Może to być równie dobrze rzucona przez niego bomba, jak też jego martwy kod (np. ślad po skoczku lub robaku). Niestety, jednoznaczne określenie, czy daną komórkę (oczywiście różną od DAT 0 0) warto zaatakować, jest niemożliwe. Możemy co najwyżej badać otoczenie tej komórki (jeśli nie będzie to czysta arena, to być może trafiliśmy na coś wartego ostrzelania) lub sprawdzić, czy zawiera ona wykonywalny rokaz. Tak można w prosty sposób zbadać, czy zadana komórka zawiera rozkaz DAT:

  wzór        DAT 0       0
              ...
              SUB @adres  @adres
              CMP wzór    @adres
              ...